nothings / stb

stb single-file public domain libraries for C/C++
https://twitter.com/nothings
Other
25.99k stars 7.67k forks source link

Read single channel greyscale bmp or png format image returns 3-channel image data #1501

Closed simpo-lei closed 1 year ago

simpo-lei commented 1 year ago

Attached zip has two greyscale images of bmp and png formats, and it looks like below. image

The images are typical greyscale 8bpp single channel image. When the image is loaded with _stbiload it is expected to get image data with single channel. However, what I get is 3-channel image with correct width and height. Each channel has the same contents.

Surprisingly, jpg format works fine. That is to say, loading single channel grayscale image in .jpg format actually gives me a single channel data.

For computer vision or industrial image processing, we still use grayscale image very often and single channel data is wanted.

simpo-lei commented 1 year ago

I tried unsigned char* data = stbi_load(filePath, &width, &height, &channels, 0); and unsigned char* data = stbi_load(filePath, &width, &height, &channels, 1);

And results were the same.

nothings commented 1 year ago

The PNG file you linked is a 3-color file. E.g. if I open it in photoshop, it opens as RGB, not as grayscale. If the image is saved as RGB, then stb_image will see it as RGB; we don't scan the color data to determine if it's grayscale or not.

There is no attached ZIP, but as I understand it there's no such thing as a grayscale BMP; it's either RGB or paletted, and we always treat paletted images as RGB.

The second function should have worked. Are you sure it didn't work? If it works, it will load the data as grayscale 1 channel, but the value of "channels" will be the number of channels in the file (3) even if it loads as 1 channel. This is the documented behavior so you know that the original had more channels than you asked for.

simpo-lei commented 1 year ago

test-one-channel-greyscale.zip Thanks nothings! I attached the zip file again and hopefully it works this time. Below is what I get when open the greyscale bmp file with IrfanView. image

I guess the conventions of our businesses are quite different. For the image shown above, I expect that the returned data has a size of width height, not width height * 3 as R, G, and B components of any pixel have the same value.

I also supposed that unsigned char* data = stbi_load(filePath, &width, &height, &channels, 1); should work. Probably I did something wrong, and I will test again.

Thanks for your kind comment.

simpo-lei commented 1 year ago

I just tested with unsigned char* data = stbi_load(filePath, &width, &height, &channels, 1); and found out why it was failed. In this case, the returned data does have just on channel which was created by combing RGB channels. However, the channels was still 3 and I used it directly. On the other hand I supposed that value of channel should be 1, which apparently is wrong.

Anyway, glad to know that the code works fine. And the issue can be closed.

nothings commented 1 year ago

Like I said, the greyscale BMP file is probably 8-bit paletted, which means each pixels is 8 bits choosing from 256 palette entries, where each palette entry is 24-bits RGB. The palette happens to only contain grayscale colors, but it's still considered an RGB file. I can say this without checking the BMP because there is no BMP grayscale file format.

Files are normally classified without looking at the actual pixels by only consulting the metadata, and the metadata for both of these files says they're RGB. This is true regardless of what business you're in.