我有一个C#/ .NET实用程序我写的从磁盘加载PNG图像
Bitmap b = Bitmap.FromStream(new MemoryStream(File.ReadAllBytes(filename))) as Bitmap;
对它们执行多次转换(旋转,缩放,alpha),然后根据应用的转换将生成的PNG图像保存回具有不同文件名的磁盘
b.Save(outputName, ImageFormat.Png);
我使用该实用程序成功编写了数千个PNG。但是,偶尔有一个PNG无法加载到使用libpng的单独程序中。在该程序中,libpng给出错误“找到太多IDAT”
查看PNG文件会在IEND块之前的文件末尾显示“流氓”IDAT块。一个这样的IDAT块(以及下面的IEND块)在十六进制编辑器中看起来像这样。这些是文件中的最后24个字节。
IDAT: 0x00 0x00 0xFF 0xF4 0x49 0x44 0x41 0x54 0x35 0xAF 0x06 0x1E
IEND: 0x00 0x00 0x00 0x00 0x49 0x45 0x4e 0x44 0xAE 0x42 0x60 0x82
IDAT块长度显示为0xFFF4。但是,很明显,IDAT块中没有那么多字节(甚至文件也没有。)
还有其他人遇到过这个问题吗?我可以用以下几种方法之一解决问题。我可以手动编辑PNG文件以删除最后一个IDAT块(或将其大小设置为0.)我可以运行修复损坏的PNG的辅助程序。但是,我想要一个C#/ .NET解决方案,我可以轻松地将其添加到我的原始程序中。理想情况下,我想要一个不需要我重新打开PNG作为二进制文件的解决方案;检查IDAT坏块;并重写PNG。但是,我开始认为这就是我需要做的事情。
答案 0 :(得分:1)
老问题。
.NET众所周知在处理图像方面很差。编解码器是较旧的win32编解码器,其中包含许多错误。
即使您遵循建议的处理方式和/或使用方法,.NET也不总是释放读取/写入图像文件时使用的OS资源。
答案 1 :(得分:0)
这不是一个完整的答案,因为我无法重现图像。但您可以尝试使用Bitmap
构造函数中的另一个加载图像:
http://msdn.microsoft.com/en-us/library/0cbhe98f.aspx
哪会将您的代码更改为:
Bitmap b = new Bitmap(filename);
因为该构造函数使用一些本机GDI +函数将图像加载到内存中,而不是读取原始字节:
可能存在差异,即使问题似乎是在将图像写入磁盘时。