Как найти причину ошибки Generic GDI + при сохранении изображения?

Имея код, который работает веками при загрузке и хранении изображений, я обнаружил, что у меня есть одно изображение, которое нарушает этот код:

const string i1Path = @"c:\my\i1.jpg"; const string i2Path = @"c:\my\i2.jpg"; var i = Image.FromFile(i1Path); i.Save(i2Path, ImageFormat.Jpeg); 

Исключение составляет:

Возникло событие System.Runtime.InteropServices.ExternalException

Общая ошибка произошла в GDI +.

в System.Drawing.Image.Save (String filename, кодировщик ImageCodecInfo, EncoderParameters encoderParams)
в System.Drawing.Image.Save (String filename, формат ImageFormat)
в …

Насколько я вижу, в изображении нет ничего особенного. Он имеет размер около 250 пикселей и может быть открыт, например, Windows Image Viewer или Paint.NET:

введите описание изображения здесь

(Так как изображение выше, после загрузки в Stack Overflow больше не приводит к ошибке, я поместил исходное изображение здесь )

Я обнаружил, что при вызове метода Save файл образа назначения создается с нулевыми байтами.

Я действительно не знаю, что вызывает ошибку.

Мои вопросы:

  • Можете ли вы придумать какую-либо особую вещь, которая помешала бы .NET сохранить изображение?
  • Есть ли способ (помимо панировки) сузить подобные ошибки?

В то время как я все еще не выяснил причину того, что именно вызвало ошибку при сохранении изображения, я нашел обходное решение:

 const string i1Path = @"c:\my\i1.jpg"; const string i2Path = @"c:\my\i2.jpg"; var i = Image.FromFile(i1Path); var i2 = new Bitmap(i); i2.Save(i2Path, ImageFormat.Jpeg); 

Т.е. путем копирования изображения внутри экземпляра Bitmap и сохранения этого изображения вместо исходного изображения ошибка исчезла.

Я предполагаю, что, скопировав его, ошибочные части, вызванные сбоем первоначального вызова Save , удаляются или нормализуются, что позволяет успешно завершить операцию сохранения.

сохраненное изображение i2.jpg

Интересно, что у сохраненного изображения есть меньший файл на диске (16 kB), чем его исходный источник (26 kB).

Прежде всего убедитесь, что желаемая папка имеет разрешения на чтение / запись. Изменение разрешений решило эту проблему для меня.

Решение здесь, вы должны удалить объект изображения, чтобы освободить память на сервере. Попробуйте использовать инструкцию using . Убедитесь, что каталог назначения на сервере существует.

мое решение состояло в том, чтобы написать, написать временный контент (File.WriteAllText) непосредственно перед сохранением файла

Вот код:

 var i = Image.FromFile(i1Path); File.WriteAllText(i2Path, "empty"); // <---- magic goes here i.Save(i2Path, ImageFormat.Jpeg); 

Пожалуйста, дайте мне знать

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

Следуя тому, что было сказано в этом сообщении в блоге (предполагая, что вы немецкий на картинке, которую вы связали в своем вопросе), можно найти возможное решение. Также принятый ответ этого вопроса указывает, что это связано с тем, что файл изображения, который вы пытаетесь сохранить, заблокирован.

РЕДАКТИРОВАТЬ
Для Ulysses Alves из связанной записи в блоге: если вы загружаете изображение с помощью Image.FromFile() оно остается заблокированным до его удаления. Это предотвращает вызовы Save() .

 pictureBox1.Image = Image.FromFile("C:\\test\\test1.jpg"); pictureBox1.Image.Save("C:\\test\\test2.jpg"); 

Вышеприведенный код вызывает ошибку.

Чтобы заставить его работать, вам нужно скопировать изображение. Следующий код работает:

 pictureBox1.Image = Image.FromFile("C:\\test\\test1.jpg"); Image copy = pictureBox1.Image; copy.Save("C:\\test\\test2.jpg") 

Открыть в программе

 const string i1Path = @"c:\my\i1.jpg"; const string i2Path = @"c:\my\i2.jpg"; var i = Image.FromFile(i1Path); i.Save(i2Path, ImageFormat.Jpeg); i.Dispose(); 
Давайте будем гением компьютера.