Reputation: 7938
What are the tools/standards/file formats by which I can visualize my image pixel buffer on which each pixel has 3
bits?
My Language is Go.
An image pixel buffer is created on which each pixel has only 3
bits of data. Having saved it as a PNG file with header info of bit depth set to 3
, I cannot visualize it:
But when the PNG file header info for bit depth is set to 4
, I can be previewed, although I'm not sure if the preview is actually correct or wrong:
The change that I'm making is just the header info for bit depth, that's all. My code is in Golang:
// Set bit depth and color type.
e.tmp[8] = 3 // Preview is not possible.
e.tmp[8] = 4 // Preview is possible.
e.tmp[9] = ctGrayscale
According to Wikipedia we have:
The standard allows indexed color PNGs to have 1, 2, 4 or 8 bits per pixel; grayscale images with no alpha channel may have 1, 2, 4, 8 or 16 bits per pixel. Everything else uses a bit depth per channel of either 8 or 16.
Upvotes: 0
Views: 125
Reputation: 7938
Have you tried to pad the 3 bits into a minimum of 8 bits?
Eventually, to test and visualize the correctness of the 3-bit pixel buffer, I followed the @ih8ie8 comment above.
// To visualize 3 bit depth, we pad the 3 bits into 8 bits.
// Then save as 8-bit gray PNG file.
func Pad3bitTo8bit(pix3bit []uint8) []uint8 {
pix8bit := make([]uint8, 0, (len(pix3bit)<<3)/3)
var color uint8
var kolor uint8
for i := 0; i < len(pix3bit); i++ {
switch i % 3 {
case 0:
color = pix3bit[i] & 0b11100000
color <<= 0
pix8bit = append(pix8bit, color)
color = pix3bit[i] & 0b00011100
color <<= 3
pix8bit = append(pix8bit, color)
color = pix3bit[i] & 0b00000011
kolor = pix3bit[i+1] & 0b10000000
color = (color << 6) | (kolor >> 2)
pix8bit = append(pix8bit, color)
case 1:
color = pix3bit[i] & 0b01110000
color <<= 1
pix8bit = append(pix8bit, color)
color = pix3bit[i] & 0b00001110
color <<= 4
pix8bit = append(pix8bit, color)
color = pix3bit[i] & 0b00000001
kolor = pix3bit[i+1] & 0b11000000
color = (color << 7) | (kolor >> 1)
pix8bit = append(pix8bit, color)
case 2:
color = pix3bit[i] & 0b00111000
color <<= 2
pix8bit = append(pix8bit, color)
color = pix3bit[i] & 0b00000111
color <<= 5
pix8bit = append(pix8bit, color)
default:
log.Fatalln("Code shouldn't reach here.")
}
}
return pix8bit
}
This image might clarify the above procedure:
Then save as a gray 8-bit PNG file:
// PNG specification doesn't recognize 3 bit depth at all.
// To visualize 3 bit depth, we pad the 3 bits into 8 bits.
pix8bit := Pad3bitTo8bit(*pix)
// Save as 8-bit gray PNG file.
img.SavePNG(tt.name+"-gray-3bit--padded-to-8bit.png", &image.Gray{
Pix: pix8bit,
Rect: rect,
Stride: 1 * rect.Dx(), // For 8-bit pixels.
})
Upvotes: -1
Reputation: 112169
Having saved it as a PNG file with header info of bit depth set to 3
No, you did not. As you note yourself at the end of your question, there is no such thing. PNG supports 1, 2, 4, 8, and 16 bits per pixel. Whatever you saved is not a valid PNG file, and whatever you were using to view it rightfully rejected it.
You will need to use at least four bits per pixel with PNG. I am not aware of an image format that represents the uncompressed data as three bits per pixel. The uncompressed representation should not matter, as it is transient. Either you store it as compressed, where PNG compression will use approximately three bits per pixel in the compressed data anyway, if only eight values out of the 16 are used. Or you store it in memory as one byte, eight bits, per pixel, in order to deliver it to whatever will display it on the screen.
I just tried PNG compression with random 3-bit values in 4-bit pixels. The compressed data portion is 3.03 bits per pixel.
Upvotes: 3