我想把这个问题放在前面,我只是在玩和学习。我不想使用本机内置方法或外部库来完成这个问题。我也不想以一种更优化的方式来完成它,而这种方式肯定是可以实现的,并在其他类似的问题中描述过。我只想了解我看到了什么,以及为什么当我手动解码头文件时。
简短版本:我试图从二进制格式读取PNG
头字节。我似乎总是得到一个值8的位深度,但文件的windows属性显示不同的值(如32,24)。
我还检查了online tool / website显示位深度为8的相同PNG。所以我不认为这是我的代码,我只是不知道windows从哪里得到它,也不知道我应该如何匹配它。
从Windows查看的示例文件显示32位深度,如下所示:
这是我的示例代码(来自LinqPad,但很容易转移到程序)
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;
});
}
以上的输出为:
1197
883
8
6
0
0
0
1条答案
按热度按时间xtfmy6hx1#
Windows文件属性中显示的BitDepth与PNG格式的位深度不同。
Windows显示的是每像素的总位数(在您的情况下为32,假设您有一个4通道RGBA图像)。
正如您在WikiPedia PNG page中所看到的,PNG头在
width
和height
之后有2个相关字段:即,从PNG的Angular 来看,位深度是单个通道的位数。
您需要将其乘以通道数(基于颜色类型),以获得每像素的总位数,如Windows文件属性中所示。
更新:
您在评论中提到,您的案例中的颜色类型为6。根据means的规格:
每个像素是一个R、G、B三元组,后跟一个Alpha样本。
这意味着您有4个通道,每个通道有8位,因此每个像素的总位数为32,如Windows文件属性中所报告的。