Specifying a pitch for SetDIBitsToDevice - image

I am displaying bitmaps with the function SetDIBitsToDevice. This function knows about the total image size via a LPBITMAPINFO structure that has Width and Height fields. It also knows about the region of interest to be drawn via the arguments XDest, YDest, Width, Height. All these are specified in pixels.
So far so good when the image is stored as a canonical one, i.e. with a row pitch (number of bytes between a pixel and the one immediately below) that matches the image width in bytes, with padding (if necessary) to reach the next multiple of four bytes.
For technical reasons, I have images with a larger pitch (but still a multiple of four). For instance, width=1000 but pitch=1024. For a grayscale image (1 byte per pixel), I can trick the function by declaring a width of 1024 in LPBITMAPINFO and a width of 1000 when passed to SetDIBitsToDevice.
But for a 3 bytes per pixels image (RGB), I am stuck because 1024 bytes do not correspond to an integer number of pixels, and I see no way to specify that pitch.
Do you see a workaround or something I missed in the documentation ? (I don't think that the field SizeImage can be of any use.)

Related

how to read correct pixels from windows clipboard copy image?

i'm using this:
GetClipboardData(CF_DIB);
i view it as a BITMAPINFOHEADER and take into account
biWidth
biHeight
biBitCount 24 vs 32
if biCompression is BI_BITFIELDS then i skip over the first 3*4 bytes of the pixel data.
most of the time when i copy an image i can get the pixel data from it just fine. but when copying from certain applications like Telegram, sometimes the colors are messed up, sometimes the image is skewed, all sorts of crazy artifacts happen when trying to view the clipboard image. i don't see anything special in the BITMAPINFOHEADER of these images i'm rendering incorrectly. what could i possibly be forgetting to handle?
A little-known fact about Microsoft bitmaps is that every row is padded to an even multiple of 4 bytes. It is natural to assume that one row follows the next immediately, but there may be 1 to 3 bytes of padding on each row that will throw your alignment off. You will see this as colors that aren't what they should be, or a skewed image as each row is shifted from its proper position.
If your pixels are all 4 bytes (RGBA) or your image width is a multiple of 4 (more common than random chance would suggest) each row will already be a multiple of 4 bytes, and you won't notice a problem.

Read the width and length of the pixel in .dcm format with dicominfo

I have pictures in .dcm format.
I'm looking for the width and length of the pixel.
As far as I know that Dicominfo gives the information of the picture.
Do you know what parameters are used to obtain the width and length of the pixel in the Dicominfo?
I had an idea that I first need the FOVx "Field Of View" and then I can divide by the number of pixels. This is how I get the width and length of the pixel.
I am very grateful for every answer.
Not sure what you exactly mean by "length". Furthermore, geometrical information (pixel size in mm) may vary regarding the tag numbers, depending on the type of object. The attribute tags I am providing here should work for the majority of DICOM images that have geometrical information at all.
image size in pixels (x,y) -> Columns (0028,0011), Rows (0028,0010)
size of the pixels (y,x) -> Pixel Spacing (0028,0030)
Pixel Spacing is a multi-valued attribute from which you can obtain two values which are separated by a Backslash "\". Not sure how the API of DicomInfo allows access to multiple values in the same attribute.
Note the difference "(y,x)" in Pixel Spacing. This is very unintuitive, but it is like it is.

How to determine the number of bytes necessary to store an uncompressed grayscale image of size 8000 × 3400 pixels?

This is all of the information I was provided in the practice question. I am trying to figure out how to calculate it when prompted to do so on an exam...
How to determine the number of bytes necessary to store an uncompressed grayscale image of size 8000 × 3400 pixels?
I am also curious how the calculation changes if the image is a compressed binary image.
"I am trying to figure out how to calculate it when prompted to do so on an exam."
There are 8 bits to make 1 byte, so once you know how many bits-per-pixel (bpp) you have, this is a very simple calculation.
For 8 bits per pixel greyscale, just multiply the width by the height.
8000 * 3400 = 27200000 bytes.
For 1 bit per pixel black&white, multiply the width by the height and then divide by 8.
(8000 * 3400) / 8 = 3400000 bytes.
It's critical that the image is uncompressed, and that there's no padding at the end of each raster line. Otherwise the count will be off.
The first thing to work out is how many pixels you have. That is easy, it is just the width of the image multiplied by the height:
N = w * h
So, in your case:
N = 8000 * 3400 = 27200000 pixels
Next, in general you need to work out how many samples (S) you have at each of those 27200000 pixel locations in the image. That depends on the type of the image:
if the image is greyscale, you will have a single grey value at each location, so S=1
if the image is greyscale and has transparency as well, you will have a grey value plus a transparency (alpha) value at each location, so S=2
if the image is colour, you will have three samples for each pixel - one Red sample, one Green sample and one Blue sample, so S=3
if the image is colour and has transparency as well, you will get the 3 RGB values plus a transparency (alpha) value for each pixel, so S=4
there are others, but let's not get too complicated
The final piece of the jigsaw is how big each sample is, or how much storage it takes, i.e. the bytes per sample (B).
8-bit data takes 1 byte per sample, so B=1
16-bit data takes 2 bytes per sample, so B=2
32-bit floating point or integer data take 4 bytes per sample, so B=4
there are others, but let's not get too complicated
So, the actual answer for an uncompressed greyscale image is:
storage required = w * h * S * B
and in your specific case:
storage required = 8000 * 3400 * 1 * 1 = 27200000 bytes
If the image were compressed, the only thing you should hope and expect is that it takes less storage. The actual amount required will depend on:
how repetitive/predictable the image is - the more predictable the image is, in general, the better it will compress
how many colours the image contains - fewer colours generally means better compression
which image file format you require (PNG, JPEG, TIFF, GIF)
which compression algorithm you use (RLE, LZW, DCT)
how long you are prepared to wait for compression and decompression - the longer you can wait, the better you can compress in general
what losses/inaccuracies you are prepared to tolerate to save space - if you are prepared to accept a lower quality version of your image, you can get a smaller file

HPDF units for text width and height

Maybe it's just my head spinning, but there seems to be no documentation on the units of measure for HPDF's HPDF_Font_TextWidth() function, nor can I figure it out.
The number I get for a particular text of 7 characters is around 3000. The rendered text seems to be around 80 pixels, which is also returned from HPDF_Page_TextWidth().
HPDF_Font_TextWidth() does not know the font size so it must use some other unit. What is it?
And is that the same unit that HPDF_Font_GetBBox() returns?
I'm actually trying to put text in the center of a rectangle, and need the width and height of the text in the units of the rectangle.
This is an old post but I just stumbled upon it because I had the same issue. As far as I know, looking into the source of HPDF_Font_GetUnicodeWidth(), the units that it returns needs to be multiplied by the font size, then divided by 1000 to get the width in points, which is what the rest of the PDF coordinate system uses.
width = (HPDF_Font_TextWidth() * font_size) / 1000.0;
All the following return EM units, which must be divided by 1000 and multiplied by the point size to get points, as stated above:
The units are relative to the baseline. Descender, BBox left & bottom are negative. The zone between caps Height and ascender is for diacritics.
To calculate the height of a slug of text, compute caps height less descender, or ascender less descender if your text has upper-case diacritics.
Keyword: Haru PDF

stride and padding of an image

I wanted to use CreateBitmapFromMemory method, and its requires the stride as an input. and this stride confused me.
cbStride [in]
Type: UINT
The number of bytes between successive scanlines in pbBuffer.
and here it says: stride = image width + padding
Why do we need these extra space(padding). why dont just image width.
This is how calculate the stride right?
lWidthByte = (lWidth * bits + 7) / 8;
lWidth→pixel count
bits→bits per pixel
I suppuse deviding by 8 is for convert to byte. but,
What is (+7) doing here?
and finally
cbStride =((lWidthByte + 3) / 4) * 4;
Whats going on here? (why not cbStride = lWidthByte)
Please help me to clear these.
The use of padding is due to various (old and current) memory layout optimizations.
Having image pixel-rows have a length (in bytes) that is an integral multiple of 4/8/16 bytes can significantly simplify and optimized many image based operations. The reason is that these sizes allow proper storing and parallel pixel processing in the CPU registers, e.g. with SSE/MMX, without mixing pixels from two consecutive rows.
Without padding, extra code has to be inserted to handle partial WORD/DWORD pixel data since two consecutive pixels in memory might refer to one pixel on the right of one row and the left pixel on the next row.
If your image is a single channel image with 8 bit depth, i.e. grayscale in the range [0,255], then the stride would be the image width rounded up to the nearest multiple of 4 or 8 bytes. Note that the stride always specified in bytes even when a pixel may have more than one byte depth.
For images with more channels and/or more than one byte per pixel/channel, the stride would be the image width in bytes rounded up to the nearest multiple of 4 or 8 bytes.
The +7 and similar arithmetic examples you gave just make sure that the numbers are correctly rounded since integer math truncates the non-integer component of the division.
Just insert some numbers and see how it works. Don't forget to truncate (floor()) the intermediate division results.

Resources