23

我有一个我编写的 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。但是,我开始认为这是我需要做的。

4

2 回答 2

2

老问题。

.NET 在处理图像方面是出了名的差。编解码器是旧的 win32 的,有很多错误。

即使您遵循推荐的 dispose 和/或 using 方法,.NET 也不总是释放读取/写入图像文件时使用的操作系统资源。

于 2020-03-12T04:28:56.300 回答
0

这不是一个完整的答案,因为我无法复制图像。但是您可以尝试使用另一个Bitmap构造函数加载图像:

http://msdn.microsoft.com/en-us/library/0cbhe98f.aspx

这会将您的代码更改为:

Bitmap b = new Bitmap(filename);

因为该构造函数使用一些本机 GDI+ 函数将图像加载到内存中,而不是读取原始字节:

http://dotnetframework.org/default.aspx/4@0/4@0/DEVDIV_TFS/Dev10/Releases/RTMRel/ndp/fx/src/CommonUI/System/Drawing/Bitmap@cs/1305376/Bitmap@cs

可能存在差异,即使问题似乎出在将图像写入磁盘时。

于 2013-10-25T00:10:03.033 回答