Proper size calculation of grid tooltip - user-interface

Using Dyalog APL I'm trying to create a grid with cell tooltips. These tooltips are created with the method AddComment. For some reason the tooltip does not resize itself to fit the content so if the text doesn't fit it will be cut off. Therefor a size calculation is required before the tooltip is created. The method GetTextSize can be used to retrieve the size of a text in pixels for the used font. However, this method seems to report the wrong size despite setting the Coord property to 'Pixel'.
Here is an example which illustrates the problem:
∇ ShowGrid;col;comment;height;row;width
'F'⎕WC'Form'
'F.G'⎕WC'Grid'(2 2⍴0)(0 0)(100 100)
comment←↑'line one' 'line two' 'line three'
row col←1 2
'F.G' ⎕WS'Coord' 'Pixel'
height width←4+F.G.GetTextSize comment
F.G.AddComment row col comment height width
∇
I also add four pixels to the reported size of the text since the border and padding of the tooltip seems to be one pixel each. The window created with this function is shown in the image below. Only the text "line one" is visible in the tooltip. I also tried setting Coord to 'RealPixel' and 'ScaledPixel' respectively but it made no difference. My question is basically: What is the proper way to calculate the tooltip size so that any given text will be displayed in its entirety? I'm using Dyalog APL 16.0 Classic.

The comment is drawn with a font that is different to the one used by F.G.GetTextSize. Unfortunately there is currently no simple way to retrieve the size of the font that is actually used.
We will look into ways to fix this.

OK, try this one for 32 bit CLASSIC. The difference is in the SIZE of the structure (504 bytes for a Unicode interpreter, 344 for classic). This is because the font names use 2 byte characters in Unicode and 1 byte characters in classic.
⎕IO ⎕ML←1 0
FNT←' I4 I4 I4 I4 I4 U1 U1 U1 U1 U1 U1 U1 U1 T[32] ' ⍝ A LOGFONT structure
NCM←'{U4 I4 I4 I4 I4 I4 ',FNT,'I4 I4',FNT,'I4 I4',FNT,FNT,FNT,'I4}' ⍝ A NONCLIENTMETRICSW structure
SIZE←344 ⍝ The size of the above
⎕NA'DYALOG32|MEMCPY >',NCM,' <U1[] U' ⍝ Useful copy with format
⎕NA'U user32|SystemParametersInfo* U U =U1[',(⍕SIZE),'] U ' ⍝ Get the data as an array of bytes
r←SystemParametersInfo 41 0(SIZE↑88 1)0
f←MEMCPY(83⍴0)(2⊃r)SIZE ⍝ And copy to a NCM structure
tip←f[53 66] ⍝ And extract the relevant bits
(2⊃tip)~←⎕UCS 0 ⍝ and remove trailing nulls from name

A workaround suggested by Adám is to determine and hard code the font used for comments and then use GetTextSize with this font as a parameter. With some guess work and testing I found it to be "Segoe UI" of size 15 pixels. Below is a (rather fragile) solution. It's fragile in the sense that it only works correctly if the user hasn't changed the default font or font size.
∇ ShowGrid;border;col;comment;boxSize;commentSize;padding;row
'F'⎕WC'Form'
'F.G'⎕WC'Grid'(2 2⍴0)(0 0)(100 100)
comment←↑'line one' 'line two' 'line three'
row col←1 2
'F.G'⎕WS'Coord' 'Pixel'
'F.G.FNT'⎕WC'Font' 'Segoe UI' 15
commentSize←F.G.GetTextSize comment'#.F.G.FNT'
(border padding)←1
boxSize←commentSize+2×border+padding
F.G.AddComment row col comment,boxSize
∇

The following is an APL/⎕NA translation of how the interpreter gets thr information about the tip font from the operating system.
∇ tip←tip_font;FNT;NCM;SIZE;⎕IO;⎕ML;SystemParametersInfo;MEMCPY;tip;r;GetLastError;f
⎕IO ⎕ML←1 0
FNT←' I4 I4 I4 I4 I4 U1 U1 U1 U1 U1 U1 U1 U1 T[32] ' ⍝ A LOGFONT structure
NCM←'{U4 I4 I4 I4 I4 I4 ',FNT,'I4 I4',FNT,'I4 I4',FNT,FNT,FNT,'I4}' ⍝ A NONCLIENTMETRICSW structure
SIZE←504 ⍝ The size of the above
⎕NA'DYALOG64|MEMCPY >',NCM,' <U1[] U' ⍝ Useful copy with format
⎕NA'U user32|SystemParametersInfo* U U =U1[',(⍕SIZE),'] U ' ⍝ Get the data as an array of bytes
r←SystemParametersInfo 41 0(SIZE↑248 1)0
f←MEMCPY(83⍴0)(2⊃r)SIZE ⍝ And copy to a NCM structure
tip←f[53 66] ⍝ And extract the relevant bits
(2⊃tip)~←⎕UCS 0 ⍝ and remove trailing nulls from name
∇

Related

Polybar Math: Calculating offset-x to center bar automatically

I am trying to calculate the offset-x value by doing some simple math. I want offset-x to be calculated by looking at width value, subtracting it from 100, strip off the % (main issue) and dividing by 2 . This will make sure the bar is always centered no matter the width value.
This is what I have so far:
[bar/top]
; Dimension defined as pixel value (e.g. 35) or percentage (e.g. 50%),
; the percentage can optionally be extended with a pixel offset like so:
; 50%:-10, this will result in a width or height of 50% minus 10 pixels
width = 70%
height = 28pt
; divide negative space (20%) evenly and set the offset-x to that value
; 80% width = 20% negative space /2 = 10%
; test variable calculation:
barXoffset="$((echo 100-70)/2 | bc))"
; Offset defined as pixel value (e.g. 35) or percentage (e.g. 50%)
; the percentage can optionally be extended with a pixel offset like so:
; 50%:-10, this will result in an offset in the x or y direction
; of 50% minus 10 pixels
; offset-x = 15%
offset-x = ${barXoffset}%
offset-y = 2
How would you try to solve this?
Currently trying to pipe into bc but still need to strip of the % at the end.

Camera from POCO M3 returns unreadable image bytes

I'm trying to detect faces fith ml_kit_face_detection on flutter.
It works fine for other phones. But on POCO M3 ml kit can't detect faces.
I take one of image from camera & save it to file.
The file is bellow:
https://drive.google.com/file/d/1mvt2klSwWFA5YL96bz1itfeEX4dai4Oh/view?usp=sharing
I undersand that the file is not readable. I tryed to convert it to base64 but it also no readable.
I'm trying to convert it to png & got this
Reverse engineering the format is challenging...
The file format is raw binary format, with some non-standard padding.
I managed to get the following result:
It looks right, but I am not sure that it is entirely correct....
It looks like the file format is NV12 (or NV21) with some padding.
For better understanding NV12 format, you may refer to my following post.
By reverse engineering the file I figured out the following information:
Image resolution: 1280x720
The stored resolution is 1536x720 (there is a padding of 256 pixels in the right side).
File storage format (raw binary format):
Y channel plane: First 1536x719+720 bytes.
UV channel plane: 1536x360 bytes.
Spare bytes, and duplication for UV channel plane.
I don't know why UV channel is duplicated, but the data looks identical.
Illustration:
256 padding bytes
<----->
1536 bytes
<------------------------>
YYYYYYYYYYYYYYYYYY00000000
YYYYYYYYYYYYYYYYYY00000000
YYYYYYYYYYYYYYYYYY00000000 719 rows
YYYYYYYYYYYYYYYYYY00000000
YYYYYYYYYYYYYYYYYY00000000
YYYYYYYYYYYYYYYYYY <--- 1280 bytes (last row of Y)
UVUVUVUVUVUVUVUVUV00000000
UVUVUVUVUVUVUVUVUV00000000 359 rows
UVUVUVUVUVUVUVUVUV00000000
UVUVUVUVUVUVUVUVUV <---- 1280 bytes (last row of UV)
MATLAB code that reads the data and convert to RGB:
f = fopen('photo', 'r'); % Open binary file for reading.
I1 = fread(f, [1536, 719], '*uint8')'; % Read 1536x719 image (Y channel).
I1last_row = fread(f, 1280, '*uint8')'; % Read 1280 bytes (last row of Y).
I2 = fread(f, [1536, (720-1)/2], '*uint8')'; % Read 1536x359 image (UV channel).
I2last_row = fread(f, 1280, '*uint8')'; % Read 1280 bytes (last row of UV).
fclose(f);
%figure;imshow(I1);impixelinfo % Show I1 for testing.
%figure;imshow(I2);impixelinfo % Show I2 for testing.
I1 = I1(:, 1:1280); % Crop valid part: 1280x719 pixels.
I1 = [I1; I1last_row]; % Add last row to the bottom (complete to 1280x720).
I2 = I2(:, 1:1280); % Crop valid part (1280x359 UV elements).
I2 = [I2; I2last_row]; % Add last row to the bottom. (complete to 1280x360).
% Convert from NV12 to RGB:
Y = I1;
U = I2(:, 1:2:end); % Extract U color channel
V = I2(:, 2:2:end); % Extract V color channel
U = imresize(U, size(Y)); % Resize U to be the same size of Y
V = imresize(V, size(Y)); % Resize V to be the same size of Y
YUV = cat(3, Y, U, V); % Merge Y,U,V channels
RGB = ycbcr2rgb(YUV); % Convert from YCbCr color format to RGB.
% Show and save RGB for testing:
figure;imshow(RGB);impixelinfo
imwrite('RGB', RGB);
Note:
For better figuring out the format (NV12 or NV21), I suggest you to take a picture with various colors. Post the raw file, and if you can, post a colored reference image for comparison.

Get X/Y position of pixel in PNG file

After stripping off header bytes and de-compressing the pixel values, a PNG file leaves us with a set of rows (a horizontal strip of the image one pixel high).
Each row starts with a single byte specifying the filter used, followed by RGB values:
+-----+-----+-----+-----+-----+-----+-----+
| 0:F | 1:R | 2:G | 3:B | 4:R | 5:G | 6:B | // end of first row in image
+-----+-----+-----+-----+-----+-----+-----+
| 7:F | 8:R | 9:G |10:B |11:R |12:G |13:B | // end of second row
+-----+-----+-----+-----+-----+-----+-----+
In an image without the filter byte, I could just divide the index by 3 (since there are three values per RGB pixel), then use these formulas to get the x/y position of that pixel:
x = index % width
y = index / width
But the filter byte is throwing me off! How do I get the x/y position of a pixel, given a red pixel's byte index? (Say at byte 4 or at byte 11, as shown above.)
I've tried all kinds of permutations but I think there must be an elegant solution!
Based on comments from #usr2564301, I think this works correctly:
y = ((index-1) / 3) / width
x = ((index-y) / 3) % width
Where width is the width of the image in pixels, not the width of the row of bytes.
We subtract y from the index because each row has a single filter byte and we need to remove them all to get the x position.
Alternatively, y can be calculated using:
y = index / row_width
Where row_width is the number of bytes per row: three for RGB and one filter byte times the width of the image.

error in MATLAB regarding dimensions mismatch

Actually i am trying to implement the code on the following website http://www.mathworks.com/matlabcentral/fileexchange/28300 but this works only when two images given have the same dimensions , i want to make this code work where one image has some dimension and other has some other dimension, if i do this with current code, it gives the error
??? Sub scripted assignment dimension mismatch. Error in ==> example2 at 27
Line 27:
I(:,1:size(I1,2),:)=I1; I(:,size(I1,2)+1:size(I1,2)+size(I2,2),:)=I2;
can you resolve this for me?
You can try padding the smaller image with zeros so that is has the same dimensions as the larger image. For example
%Start with rows:
if size(I1,1) > size(I2,1) %I1 has more rows so pad I2
pad = zeros (size(I1,1) - size(I2,1), size(I2,2));
I2 = [I2 ; pad]; %Append the rows of zeros to the bottom of I2
else %I2 has more rows so pad I1
pad = zeros (size(I2,1) - size(I1,1), size(I1,2));
I1 = [I1 ; pad]; %Append the rows of zeros to the bottom of I1
%Pad the columns
if size(I1,2) > size(I2,2) %I1 has more rows so pad I2
pad = zeros (size(I2,1), size(I1,2) - size(I2,2));
I2 = [I2 , pad]; %Append the columns of zeros to the left of I2
else %I2 has more rows so pad I1
pad = zeros (size(I1,1), size(I2,2) - size(I1,2));
I1 = [I1 , pad]; %Append the columns of zeros to the left of I1
I haven't tested that though so you might need to fiddle a bit to get the dimension perfect, like maybe size(I2,2) - size(I1,2) + 1 instead of size(I2,2) - size(I1,2), that sort of thing.
But you need to first figure out the logic of what you are trying to do. Padding with zeros might not make sense in your application. Also my code pads on the bottom and the left but you might want to pad all the way around so your image is in the centre of the new image.

Whiten skin color in an image

Is there any theory or image filter for whitening the skin color in an image on iPhone ?
I have the RGB data on hand. But whatever I change, it cannot archieve my needs. I alter the RGB as follows:
New value of R/G/B = (int)roundf(Old R/G/B - 128) * contrast_value + 128 + brightness_value);
Where contrast_value = 1 to 1.3 and brightness_value = 0 to 50
But I found that it comes to pale yellow ...
Convert your image to YUV colorspace first. This gives you two advantages:
easily detect skin areas using this approach (see my answer to that question)
easily increase the brightness (just increment the Y value)
One thing I have seen to work is to add a constand value to all the three components of the color, like R + 0x33 G + 0x33 B + 0x33
EDITED: I just found another thread that has additional information: Programmatically Lighten a Color

Resources