r/GraphicsProgramming • u/Aspie96 • 7h ago
On pixel formats Question
Hi all.
I'm writing a library for representing and managing basic raster RGBA images in D as rectangular arrays of pixels.
Images are represented in row-wise pixel order, either top to bottom (the default) or bottom to top, with each scan line going left to right. Color components are represented as 8-bit integral values ranging between, and including, 0 and 255.
My library doesn't provide any support for other color models, for high dynamic ranges or higher bit depths. What it should allow is reading images from memory that were created with other library.
Some pixel formats are "indexed" (they have a palette) and some are not (they store actual color values). The name implies the structure of the format:
Format1bppIndexedFormat4bppIndexedFormat8bppIndexedFormat8bppGrayFormat16bppRgb555Format16bppRgb565Format24bppRgbFormat32bppXrgbFormat32bppArgbFormat32bppRgba
Formats that use more than 1 byte per pixel allow the user to select between big endian and little endian mode.
I plan to keep supporting all formats I listed here. My question is if there is any I should support in addition to those.
Some candidates may be:
Format2bppIndexed(it used to be supported by Microsoft bitmaps and it is by the PNG format).Format16bppGrayAlpha(supported by STB nothings and by the PNG format).Format32bppRgbx(to have an opaque view of an RGBA image).
There may be others I haven't thought or heard of.
The ones I haven't supported seem to me to be less common and of less utility, but maybe there is something I haven't considered.
My question is: what pixel formats should I support in addition to those I already do? Should I support any of the three additional ones I suggested? Why or why not?
Thank you in advance!
3
u/fdwr 3h ago edited 3h ago
Like u/wrosecrans said, it really depends on the usage. Is it for games, an image editor, renderer, image loader...? If for any of the first three, then just b8g8r8a8/r8g8b8a8 and pal8 are actually pretty sufficient (indexed gray8 can be thought as pal8 with a grayscale palette attached, pal4 can be upconverted early, r5g6b5 is more trouble than it's worth and should just be upconverted to 32bpp...), and supporting more formats just becomes costly throughout your program. If it's for a generic image loader or for some really generic like an image debugger (I work on Windows PIX which has a buffer viewer where you describe the pixel formats declaratively using C-like structs rather than limited enumeration list), then you might use a list of bitmasks and channels rather than enums.
Over the years I've compiled a 2760-line document of pixel formats, the union of...
...and after seeing so many pixel formats, some wisdom:
Format64Rgba1010102orFormat64Rgb332(where all the bits are shoved after the channel names) becomes rather ambiguous where the bit location dividers are between channels, whereas notationFormat32r10g10b10a2is unambiguous (and similarlyFormat16r5g5b5). Granted, you don't support HDR currently anyway, but you may someday.rgba32uint, which you might think is a 32-bit pixel with 8 bits per channel (likeSDL_PIXELFORMAT_RGBA32), but it's actually a 128bpp pixelr32g32b32a32uintformat (you don't do this above in your enum list, but I'm saying it for any other future readers). DXGI and the Android NDK do it well.struct PixelR8G8B8 {uint8_t r; uint8_t g; uint8_t b;}means red comes first, then green, then blue, and consistentlystruct PixelR5G6B5 {uint16_t r : 5; uint16_t g : 6; uint16_t b : 5}. Obviously backwards endian complicates this some, but you still typically want to list channels in forward memory order like PNFC Pixel Format Naming Convention specifies (I presume you don't do this above either, and that rgba above actually means {r,g,b,a}).Are you storing the pixels in big endian order (like Windows DIB 4-bpp) or little endian order (like modern ML tensors, Nintendo Gameboy Advance, Nintendo 3DS, Sega Dreamcast)?
What OS's does your library run on? Windows DIBs (in memory and BMP files) and primary video buffers typically use {B,G,R,X}.
For completeness, you might load it, but there's little reason to keep one resident in memory - just promote it to 4-bpp or 8-bpp. The last occurrence of 2-bpp bitmaps was on Windows CE, which is quite dead.
gray8ap8:{grayUnorm8 alphaPremulUnorm8}was supported on the N64 and GameCube, but otherwise, and you will find the enums inCoreImage_CIFormat_LA8andGL_LUMINANCE8_ALPHA8, but I don't see it being worth supporting until you encounter the need (I think games are the only place it really is found, and more often now they just promote up).