2013-10-10 44 views
14

我有一个C#/。NET程序,我写的是从磁盘.NET Image.Save偶尔会生成一个PNG一个坏IDAT块

Bitmap b = Bitmap.FromStream(new MemoryStream(File.ReadAllBytes(filename))) as Bitmap; 

负载PNG图像对他们进行一些变换(旋转,缩放,阿尔法),然后用基础上变换不同的文件名保存生成的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

做你的图像大小/行步幅有所不同?如果对于被破坏的图像有独特的东西(宽度,高度,步幅,格式),你是否能够缩小范围? – Chris

+1

我认为你将不得不更多地隔离问题。如果您使用C#立即读回您保存的每个文件,您是否可以重新编制错误?如果是这样,你需要追踪导致这幅破碎图像的精确环境并从那里开始。 –

+0

@Chris图像尺寸和行跨度都在光谱范围内。它们都是Format32bppArgb。我没有发现任何关于失败的PNG的独特之处。 –

回答

0

这是不是一个真正的完整的答案,因为我无法重现的图像。但你可以尝试加载使用Bitmap构造的另一个形象:

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

这将改变你的代码:

Bitmap b = new Bitmap(filename); 

因为它们的构造使用了一些机GDI +功能加载图像进入内存,而不是读取原始字节:

http://dotnetframework.org/default.aspx/[email protected]/[email protected]/DEVDIV_TFS/Dev10/Releases/RTMRel/ndp/fx/src/CommonUI/System/Drawing/[email protected]/1305376/[email protected]

即使问题出现在将映像写入磁盘时,也可能有所不同。

+0

感谢您的输入。但是,我试过其他位图构造函数,但没有运气。我特别选择了FromStream版本,因为其他人可以让文件句柄比我想要的时间更长。 –