Подтвердить что ты не робот

.NET Image.Save иногда генерирует PNG с плохой частью IDAT

У меня есть утилита С#/. NET, которую я написал, загружает изображения PNG с диска

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

выполняет несколько преобразований на них (вращение, масштабирование, альфа), а затем сохраняет полученные изображения PNG обратно на диск с разными именами файлов на основе примененных преобразований

b.Save(outputName, ImageFormat.Png);

Я успешно написал тысячи PNG с помощью утилиты. Однако иногда один из PNG не загружается в отдельной программе, которая использует libpng. В этой программе libpng дает ошибку "Слишком много найденных IDAT"

Взгляд в файл PNG показывает фрагмент IDAT-мошенника в конце файла непосредственно перед блоком IEND. Один такой фрагмент 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. Тем не менее, я хотел бы использовать решение С#/.NET, которое я могу легко добавить в свою оригинальную программу. В идеале я бы хотел получить решение, которое не требует от меня повторного открытия PNG в виде двоичного файла; проверьте наличие плохой части IDAT; и перезаписать PNG. Тем не менее, я начинаю думать, что мне нужно будет делать.

4b9b3361

Ответ 1

Это не полный ответ, так как я не могу воспроизвести изображение. Но вы можете попробовать загрузить изображение с помощью другого конструктора 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]

Там может быть разница, хотя проблема заключается в записи образа на диск.