I'm writing my own BMP file reader in C++, and there's some docs that i'm not so sure about.
In the Wiki page for the BMP File Format, there's a diagram of all the practical formats of BMP used out in the wild.
For the values that look like 8.8.8.0.8 like the 32 bpp BI_RGB in BITMAPINFOHEADER, does each value represent the amount of bits that can be used to represent each color channel in RGBAX? If this is the case, What is the 'X'? And why are there 8 bits devoted to it? Could i use this for an alpha channel?
The R.G.B.A.X notation used to be documented on Wikipedia (even with some colorful diagrams), but it has been deleted by some busybody there. However, you can still find it in the history of the article, though. See here.
Anyway, 8.8.8.0.8 means that there are 32 bits per pixel (because the sum of all of the digits equals 32) and the 0 means, there are no bits for the Alpha channel (Alpha channel is not encoded in this format, nor in any of the palletized pixel formats). The last 8 (at the fifth X position) means that there are 8 unused bits per pixel, in this encoding.
Also, the Wikipedia article and diagram below is more complete than anything the MSDN has on the subjet. See Chris Cox's criticism of the MSDN documentation here:
Related
I am trying to develop a dicom image viewer. I have successfully decoded the image buffer. I store all the image pixel values in an unsigned char buffer in C++.
Now, when I display the image it is working fine for images with pixel representation (0028,0103) =0. Could someone show me how to apply this signed conversion into these decoded buffer. I don't know how to convert this signed bits into unsigned bit (I think the usual conversion using typecast doesn't work well). Please post the replay for 16 bit image, that is what I really need now.
I am trying to create a viewer from scratch, which simply puts the image in screen. I have successfully completed the decoding and displaying of the dicom image. But when I try to open an image which has a pixel representation (tag 0028,0103) =1, the image is not showing correctly. The conversion from 16 bit to 8 bit is done along with applying window level and width (value found inside the dicom image), the conversion is simply linear.
Make sure to correctly read the pixel data into a signed short array by taking the TransferSyntax (endianess) into account. Then apply the windowing equation from the DICOM Standard. In setting ymin=0, ymax = 255 rescaling to 8 bit is achieved.
In general, there is more to take into account about handling DICOM pixel data:
Photometric Interpretation
Bits Stored, High Bit
Modality LUT (Rescale Slope/Intercept or a lookup table stored in the DICOM header)
I am assuming that Photometric Interpretation is MONOCRHOME2, High Bit = Bits Stored - 1, Modality LUT is Identity transformation (Slope = 1, Intercept = 0).
Other SO posts dealing with this topic:
Converting Pixel Data to 8 bit
Pixel Data Interpretation
I have data for every pixel red one byte, green one byte, blue one byte. I need to pack this to 8 bits bitmap, so I have only one byte for pixel. How to transform rgb (three bytes) to one byte for bitmap format ?
( I am using C++ and cannot use any external libraries)
I think you misunderstood how to form a bitmap structure. You do not need to pack (somehow) 3 bytes into one. That is not possible after all, unless you throw away information (like using special image formats GL_R3_G3_B2).
The BMP file format wiki page shows detailed BMP format : it is a header, followed by data. Now depending on what you set in your header, it is possible to form a BMP image containing RBG data component, where each component is one byte.
First you need to decide how many bits you want to allocate for each color.
3bit per color will overflow a byte (9bits)
2bits per color will underflow;
In three byte RGB bitmap you have one byte to represent each color's intensity. Where 0 is minimum and 255 is max intensity. When you convert it to 1 byte bitmap (assuming you will choose 2bits per color ) transform should be:
1-byte red color/64
i.e you will get only 4 shades out of a spectrum of 265 shades per color.
First you have to produce 256 colors palette that best fits your source image.
Then you need to dither the image using the palette you've generated.
Both problems have many well-known solutions. However, it's impossible to produce high-quality result completely automatic: for different source images, different approaches work best. For example, here's the Photoshop UI that tunes the parameters of the process:
I'm trying to work with this camera SDK, and let's say the camera has this function called CameraGetImageData(BYTE* data), which I assume takes in a byte array, modifies it with the image data, and then returns a status code based on success/failure. The SDK provides no documentation whatsoever (not even code comments) so I'm just guestimating here. Here's a code snippet on what I think works
BYTE* data = new BYTE[10000000]; // an array of an arbitrary large size, I'm not
// sure what the exact size needs to be so I
// made it large
CameraGetImageData(data);
// Do stuff here to process/output image data
I've run the code w/ breakpoints in Visual Studio and can confirm that the CameraGetImageData function does indeed modify the array. Now my question is, is there a standard way for cameras to output data? How should I start using this data and what does each byte represent? The camera captures in 8-bit color.
Take pictures of pure red, pure green and pure blue. See what comes out.
Also, I'd make the array 100 million, not 10 million if you've got the memory, at least initially. A 10 megapixel camera using 24 bits per pixel is going to use 30 million bytes, bigger than your array. If it does something crazy like store 16 bits per colour it could take up to 60 million or 80 million bytes.
You could fill this big array with data before passing it. For example fill it with '01234567' repeated. Then it's really obvious what bytes have been written and what bytes haven't, so you can work out the real size of what's returned.
I don't think there is a standard but you can try to identify which values are what by putting some solid color images in front of the camera. So all pixels would be approximately the same color. Having an idea of what color should be stored in each pixel you may understand how the color is represented in your array. I would go with black, white, reg, green, blue images.
But also consider finding a better SDK which has the documentation, because making just a big array is really bad design
You should check the documentation on your camera SDK, since there's no "standard" or "common" way for data output. It can be raw data, it can be RGB data, it can even be already compressed. If the camera vendor doesn't provide any information, you could try to find some libraries that handle most common formats, and try to pass the data you have to see what happens.
Without even knowing the type of the camera, this question is nearly impossible to answer.
If it is a scientific camera, chances are good that it adhers to the IEEE 1394 (aka IIDC or DCAM) standard. I have personally worked with such a camera made by Hamamatsu using this library to interface with the camera.
In my case the camera output was just raw data. The camera itself was monochrome and each pixel had a depth-resolution of 12 bit. Therefore, each pixel intensity was stored as 16-bit unsigned value in the result array. The size of the array was simply width * height * 2 bytes, where width and height are the image dimensions in pixels the factor 2 is for 16-bit per pixel. The width and height were known a-priori from the chosen camera mode.
If you have the dimensions of the result image, try to dump your byte array into a file and load the result either in Python or Matlab and just try to visualize the content. Another possibility is to load this raw file with an image editor such as ImageJ and hope to get anything out from it.
Good luck!
I hope this question's solution will helps you: https://stackoverflow.com/a/3340944/291372
Actually you've got an array of pixels (assume 1 byte per pixel if you camera captires in 8-bit). What you need - is just determine width and height. after that you can try to restore bitmap image from you byte array.
I'm trying to understand building a bmp based on raw data in c++ and I have a few questions.
My bmp can be black and white so I figured that the in the bit per pixel field I should go with 1. However in a lot of guides I see the padding field adds the number of bits to keep 32 bit alignment, meaning my bmp will be the same file size as a 24 bit per pixel bmp.
Is this understanding correct or in some way is the 1 bit per pixel smaller than 24, 32 etc?
Thanks
Monochrome bitmaps are aligned too, but they will not take as much space as 24/32-bpp ones.
A row of 5-pixel wide 24-bit bitmap will take 16 bytes: 5*3=15 for pixels, and 1 byte of padding.
A row of 5-pixel wide 32-bit bitmap will take 20 bytes: 5*4=20 for pixels, no need for padding.
A row of 5-pixel wide monochrome bitmap will take 4 bytes: 1 byte for pixels (it is not possible to use less than a byte, so whole byte is taken but 3 of its 8 bits are not used), and 3 bytes of padding.
So, monochrome bitmap will of course be smaller than 24-bit one.
The answer is already given above (that bitmap rows are aligned/padded to 32-bit boundary), however if you want more information, you might want to read DIBs and Their Uses, the "DIB Header" section - it explains in detail.
Every scanline is DWORD-aligned. The scanline is buffered to alignment; the buffering is not necessarily 0.
The scanlines are stored upside down, with the first scan (scan 0) in memory being the bottommost scan in the image. (See Figure 1.) This is another artifact of Presentation Manager compatibility. GDI automatically inverts the image during the Set and Get operations. Figure 1. (Embedded image showing memory and screen representations.)
This may be waaay to specific for SO, but there seems to be a dearth of info on the sun raster standard. (Even JWZ is frustrated by this!)
Intro: The Sun raster standard says that rows of pixels have padding at the end such that the number of bits in a row is a factor of 16 (i.e. an even number of bytes). For example, if you had a 7-pixel-wide 24-bit image, a row would normally take 7 * 3 = 21 bytes, but sun raster would pad it to 22 bytes so the number of bits is divisible by 16. The code below achieves this for 24-bit images of arbitrary width:
row_byte_length = num_cols * 3;
row_byte_length += width_in_bytes % 2;
Here's my question: both Imagemagick and Gimp follow this rule for 24-bit images, but for 32-bit images it does something weird that I don't understand. Since the bit depth gives 4-byte pixels, any image width would take an even number of bytes per row, which always complies with the "16-bit alignment" rule. But when they compute the row length, they add an extra byte for images with odd widths, making the row length odd (i.e. the number of bits for the row is not divisible by 16). The code below describes what they're doing for 32-bit images:
row_byte_length = num_cols * 4 + num_cols % 2;
Adding one appears to go against the "16-bit alignment" rule as specified by the sun format, and is done with no apparent purpose. However, I'm sure if Gimp and Imagemagick do it this way, I must be misreading the sun raster spec.
Are there any Sun raster experts out there who know why this is done?
Edit
My mistake, Gimp only outputs up to 24 bit Sun raster. Looks like this is only an Imagemagick issue, so probably a bug. I'm labeling this for closure; better to discuss on the ImageMagick forums.
I'd say the image loading code in Gimp and ImageMagick has a bug. Simple as that.
Keep in mind that the SUN-Raster format isn't that widely used. It's very possible that you're one of the first who actually tried to use this format, found out that it doesn't work as expected and not ignored it.
If the spec. sais something along the lines: Regardless of width, the stored scanlines are rounded up to multiples of 16 bits, then there isn't much room for interpretation.
It seems like a mistake to me too. I even wonder if Sun even supports 32-bits RAS files. Basically, a 32-bits image would most likely add an alpha channel as "fourth" colour, to support transparency. But like many image file formats, it's a bit old and others have made adjustments to the format to support 32-bits images. So I think that whomever added the 32-bits support just implemented it wrong and ever since we have to live with that decision.
Compare it with the referer misspelling that has become part of the HTTP standard. :-) A mistake that has become part of a new standard.