Navid Ahmadi
Navid Ahmadi

Reputation: 13

LibPNG: smallest way to store 9-bit grayscale images

Which one produces the smallest 9-bit depth grayscale images using LibPNG?

  1. 16 bit Grayscale
  2. 8 bit GrayScale with alpha, having the 9th bit stored as alpha
  3. Any other suggestion?

Also, from documentation it looks like in 8bit GRAY_ALPHA, alpha is 8 bit as well. Is it possible to have 8 bits of gray with only one bit of alpha?

Upvotes: 0

Views: 357

Answers (2)

leonbloy
leonbloy

Reputation: 76026

Which one produces the smallest 9-bit depth grayscale images using LibPNG?

16 bit Grayscale

8 bit GrayScale with alpha, having the 9th bit stored as alpha

The byte raw layout of both formats is very similar: G2-G1 G2-G1 ... in one case (most significant byte of each 16-bit value first), G-A G-A ... in the other. Because the filtering/prediction is done at the byte level, this means that little or no difference is to be expected between two alternatives. Because 16 bit Grayscale is in your scenario more natural, I'd opt for it. If you go the other route, I'd suggest to experiment putting the most significant bit or the least significant bit on the alpha channel.

Also, from documentation it looks like in 8bit GRAY_ALPHA, alpha is 8 bit as well. Is it possible to have 8 bits of gray with only one bit of alpha

No. But 1 bit of alpha would mean totally opaque/totally transparent, hence you could opt for add a TRNS chunk to declare a special color as totally transparent (as pointed out in other answer, this would disallow the use of that colour)

Upvotes: 0

Glenn Randers-Pehrson
Glenn Randers-Pehrson

Reputation: 12465

If all 256 possible gray levels are present (or are potentially present), you'll have to use 16-bit G8A8 pixels. But if one or more gray levels is not present, you can use that spare level for transparency, and use 8-bit indexed pixels or grayscale plus a tRNS chunk to identify the transparent value.

Libpng doesn't provide a way of checking for whether a spare level is available or not, so you have to do it in your application. ImageMagick, for example, does that for you:

$ pngcheck -v rgba32.png im_opt.png
File: rgba32.png (178 bytes)
  chunk IHDR at offset 0x0000c, length 13
    64 x 64 image, 32-bit RGB+alpha, non-interlaced
  chunk IDAT at offset 0x00025, length 121
    zlib: deflated, 32K window, maximum compression
  chunk IEND at offset 0x000aa, length 0

$ magick rgba32.png im_optimized.png

$ pngcheck -v im_optimized.png
  File: im_optimized.png (260 bytes)
  chunk IHDR at offset 0x0000c, length 13
    64 x 64 image, 8-bit grayscale, non-interlaced
  chunk tRNS at offset 0x00025, length 2
    gray = 0x00ff
  chunk IDAT at offset 0x00033, length 189
    zlib: deflated, 8K window, maximum compression
  chunk IEND at offset 0x000fc, length 0

There is no G8A1 format defined in the PNG specification. But the alpha channel, being all 0's or 255's, compresses very well, so it's nothing to worry about. Note that in this test case (a simple white-to-black gradient), the 32-bit RGBA file is actually smaller than the "optimized" 8-bit grayscale+tRNS

Upvotes: 1

Related Questions