2

I'm using WIC (Windows Imaging Component) to decode image files and get access to the pixel data. I'm trying to figure out the pixel order (i.e., bottom-up or top-down).

I use IWICImagingFactory::CreateDecoderFromFileName to create the decoder from which I grab the (first) frame (IWICBitmapFrameDecode). With the frame, I use GetPixelFormat and GetSize to compute a buffer size, and finally I use CopyPixels to get the decoded pixel data into my buffer.

This works fine with a variety of JPEG files, giving me pixel rows in top-down sequence, and the pixels are in BGRX order (GUID_WICPixelFormat32bppBGR).

When I try with GIF files, however, the pixel rows come in bottom-up sequence. The reported pixel format is RGBA (GUID_WICPixelFormat32bppRGBA), but the ground truth shows the channel order is BGRA (with the blue in the low byte of each 32-bit pixel, just like JPEG).

My primary question: Is there a way for me to query the top-down/bottom-up orientation of the pixel data?

I found a similar question that asked about rotation when using JPEG sources, and the answer was to query the EXIF data to know whether the image was rotated. But EXIF isn't used with GIF. So I'm wondering whether I'm supposed to assume that pixels are always bottom-up, except for ones that do have an EXIF orientation that says otherwise. Update 6/25/2020 Nope, the JPEG orientation is neutral and the GIF has no orientation information, yet MS Paint and other programs can open the files in the correct orientation.

My secondary question: What's up with the incorrect channel order (RGB/BGR) from the GIF decoder?

Not only that, the WIC documentation says that the GIF decoder should return indexes into a color table (GUID_WICPixelFormat8bppIndexed) rather than actual pixel values. Is it possible some software on my machine installed its own buggy GIF decoder that supersedes the one that comes with Windows 10?

Adrian McCarthy
  • 45,555
  • 16
  • 123
  • 175
  • You should ask two distinct questions. For the first one, are you looking for this: https://stackoverflow.com/a/60112084/403671 – Simon Mourier Jun 24 '20 at 06:22
  • @Simon Mourier: I raised the second question here only because (1) it might be related to the primary issue, and (2) to include all of the relevant information about what I've tried and learned so far. To put that information in a separate question would seem to lower the chance of getting a decent response to the first. This isn't my first SO rodeo. – Adrian McCarthy Jun 24 '20 at 20:59

1 Answers1

0

To query photo orientation for formats that support it you should use System.Photo.Orientation photo metadata policy (or one of file format specific metadata query paths) using IWICMetadataQueryReader interface.

As for GetPixelFormat() reporting "incorrect" pixel format, it is right there in the Remarks section:

The pixel format returned by this method is not necessarily the pixel format the image is stored as. The codec may perform a format conversion from the storage pixel format to an output pixel format.

Native byte order of image bitmaps under Windows is BGRA, so that is what you are getting from the decoder. If you want image in a different format you need to use IWICImagingFactory::CreateFormatConverter() to create a format converter and convert the image data before copying.

Finally, GIF doesn't have orientation metadata because it is always encoded from top to bottom. Most likely reason you are getting a vertically inverted image is because you are reading it directly from the decoder -- try calling CopyPixels() on the converter instead.

Igor Levicki
  • 1,017
  • 10
  • 17
  • System.Photo.Orientation is a good pointer in the right direction, so thanks for that. With regard to GetPixelFormat, I understand that it may not be the same as the stored order, but, for some images, it doesn't match what the decoder outputs. I _am_ using CopyPixels (as I indicated in the question), yet some images are inverted and others are not. It's still quite puzzling. – Adrian McCarthy Oct 07 '20 at 23:35
  • You are using CopyPixels, but are you using it on the converter or on the frame? – Igor Levicki Nov 04 '20 at 13:26
  • I'm calling CopyPixels on the frame. I'm not using a converter at all. My code can handle any pixel format and orientation as long as it knows what it is. But what I'm getting back does not match what GetPixelFormat (on the frame) says I should be getting. Furthermore, in the case of GIF, the reported pixel format is not the ones the documentation claims it should be, nor is it the format the pixels I actually receive are in. – Adrian McCarthy Nov 04 '20 at 22:48
  • That is exactly the reason why using converter is suggested -- so you can be sure you will always get the same output format you requested regardless of the decoder specifics. – Igor Levicki Nov 15 '20 at 13:02