imagensimagepalettergbansbitmapimagerep

How to convert 256 colors palettized RGBA image data to NSImage


I'm a newbie developer and I need your help with something that is probably trivial for you.

I have an image data in this pixel format: 256 colors palettized RGBA. It comes from FFmpeg (PIX_FMT_PAL8) and it's explained this way:

PIX_FMT_RGB32 is handled in an endian-specific manner. An RGBA color is put together as:

(A << 24) | (R << 16) | (G << 8) | B

This is stored as BGRA on little-endian CPU architectures and ARGB on big-endian CPUs.

When the pixel format is palettized RGB (PIX_FMT_PAL8), the palettized image data is stored in AVFrame.data[0].

The palette is transported in AVFrame.data[1], is 1024 bytes long (256 4-byte entries) and is formatted the same as in PIX_FMT_RGB32 described above (i.e., it is also endian-specific). Note also that the individual RGB palette components stored in AVFrame.data[1] should be in the range 0..255.

AVFrame struct contains uint8_t *data[4] and int linesize[4] and they are described simply with:

  • uint8_t *data[4] = pointer to the picture planes
  • four components are given, that's all.
  • the last component is alpha
  • int linesize[4] = number of bytes per line

I have the AVFrame struct with all the needed data but I don't know how to handle it. I need to create a NSImage from this image data.

How can I do this?


Solution

  • In case of a palettized image, the pixels contain a one byte value, which is an index into the palette. The palette has 256 entries.

    Pixels are stored starting at address AVFrame.data[0]; the palette is stored starting at address AVFrame.data[1].

    So to get the 4 bytes pixel value for the pixel at (X, Y), you can use first:

    uint8_t Index= AVFrame.data[0][X + AVFrame.linesize[0] * Y];
    

    to get the index into the palette, and then

    int RGBA= ((int*)AVFrame.data[1])[Index];
    

    to get the RGBA encoded value.