Home > OS >  Manually reading the BitDepth of a PNG header not matching Windows Properties values
Manually reading the BitDepth of a PNG header not matching Windows Properties values

Time:11-13

I would like to prefix this question that I am just playing around and learning. I don't want to use the native built in methods or an external library to accomplish the problem. Nor do I want to do it in a more optimal way as is certainly achievable and described in other similar questions. I just want to understand what I'm seeing and why when I manually decode the header.

Short version: I am trying to read a PNG header bytes from binary format. I always seem to get a value of 8 for the bit depth but windows properties of the file shows different values (e.g. 32, 24).

I have also checked the same PNG with an windows png properties

This is my sample code (from LinqPad but easy to transfer to program)

var rawFileStream = new System.IO.FileStream("c:\\temp\\test2.png", FileMode.Open);
var buffer = new char[4].ToList();
    
while (!IsHeaderInBuffer())
{
    ReadIntoBuffer();
}
    
var width = BitConverter.ToInt32(ReadNBytesAsLittleEndian(4)).Dump();
var height = BitConverter.ToInt32(ReadNBytesAsLittleEndian(4)).Dump();
var bitdepth = ReadSingle().Dump();
var colorType = ReadSingle().Dump();
var compression = ReadSingle().Dump();
var filter = ReadSingle().Dump();
var interlace = ReadSingle().Dump();
    
int ReadSingle()
{
    return rawFileStream.ReadByte();
}
    
byte[] ReadNBytesAsLittleEndian(int n) 
{
    var result = new byte[n];
    for (int i = 0; i < n; i  )
    {
        var b = rawFileStream.ReadByte();
        result[n - i - 1] = (byte)b;
    }
    
    return result;
}
    
void ReadIntoBuffer() 
{
    buffer.Remove(buffer.First());
    buffer.Add((char)rawFileStream.ReadByte());
}
    
bool IsHeaderInBuffer()
{
    var enumerator = "IHDR".GetEnumerator();
   
    return buffer.All(x =>
    {
        enumerator.MoveNext();
        return x == enumerator.Current;
    });
}

The output of the above being:

1197
883
8
6
0
0
0

CodePudding user response:

The BitDepth shown in the Windows file properties, is not the same as the bit depth from the point of view of the PNG format.

Windows is showing the total number of bits per pixel (32 in your case, assuming you have an 4 channel RGBA image).

As you can see in the WikiPedia PNG page, the PNG header has 2 relevant fields after the width and height:

  • bit depth (1 byte, values 1, 2, 4, 8, or 16)
  • color type (1 byte, values 0, 2, 3, 4, or 6)

I.e. bit depth from the PNG point of view is the number of bits for a single channel.

You need to multiply it by the number of channels (based on the color type) in order to get the total number of bits per pixel, as shown in Windows file properties.


Update:
You mentioned in the comment that the color type in your case is 6. According to the specification this means:

Each pixel is an R,G,B triple, followed by an alpha sample.

This means you have 4 channels, each with 8 bit, so the total number of bits per pixel is 32, as reported in the Windows file properties.

  • Related