Как сохранить отредактированный System.Drawing.Bitmap в тот же файл - PullRequest
0 голосов
/ 02 мая 2020

Я занимаюсь разработкой простого графического c приложения: загрузите изображение, отредактируйте его и сохраните. Я пробовал разные способы, и все они как-то терпели неудачу.

Сначала я попытался загрузить растровое изображение следующим образом:

imageFromName = new Bitmap(FileName1);

и сохранить его следующим образом:

imageFromName.Save(FileName1);

но в GDI + возникла ошибка «Generi c». исключение. Кроме того, в этот момент проводник windows не позволил мне удалить файл, поэтому я подумал, что проблема заключалась в том, что объект imageFromName оставил файл открытым и не позволил перезаписать его, поэтому я изменил код например:

imageFromName = new Bitmap(FileName1);
imageCloned = (Bitmap)imageFromName.Clone();
imageFromName.Dispose();
imageCloned.Save(FileName1);

Программа продолжает выдавать одно и то же исключение в imageCloned.Save (FileName1) Поэтому я искал справку по Stackoverflow и увидел несколько похожих вопросов с ответами, которые советовали проверить, имеет ли приложение разрешение на запись. Поэтому я изменил код, чтобы проверить его следующим образом:

imageFromName = new Bitmap(FileName1);
imageFromName.Save(FileName2);

В этом случае программа не выдавала никаких исключений при сохранении файла, но я все еще не мог изменить исходный файл и все еще не мог ' удалить его с помощью Windows Explorer. Он просто создал для меня копию файла.

Поэтому я подумал о загрузке растрового изображения альтернативным способом и изменил код следующим образом:

 try
 {
       System.IO.FileStream fs = new System.IO.FileStream(FileName1, System.IO.FileMode.Open);
       imageFromStream = new System.Drawing.Bitmap(fs);
       fs.Close();
 }
 catch (Exception ex)
 {
       Console.WriteLine("Error loading Bitmap.", ex);
 }

В этом случае приложение сделало не выбрасывайте никаких исключений, и растровое изображение может быть хорошо видно в PictureBox. Кроме того, Explorer позволил мне удалить файл. Однако при сохранении файла с imageFromStream.Save (imageFromStream) он продолжал генерировать для меня исключение.

Разница на этот раз в том, что метод Save (), несмотря на создание исключения, перезаписывает исходный файл, вместо этого генерируя Вместо этого 54-байтовый файл с информацией заголовка.

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

Я прочитал официальную документацию Microsoft по методу System.Drawing.Bitmap.Save () и не нашел никаких ограничений. Но я бы сказал, что у него есть проблемы с определенными пиксельными форматами.

Однако я бы не хотел ограничивать мое приложение 32-битными файлами, тогда:

1-Какой самый лучший способ сохранить изображение объекта System.Drawing.Bitmap в файл 24bpp?

2-Есть ли еще какие-то ограничения на System.Drawing.Bitmap.Save (), о которых я должен знать?

1 Ответ

0 голосов
/ 02 мая 2020

При инициализации объекта Bitmap из изображения, хранящегося на жестком диске, он создает блокировку для базового файла изображения. Из-за блокировки при попытке сохранить измененное растровое изображение выдает эту ошибку.

Существует два способа решения этой проблемы

  • Вместо перезаписи файла сохраните новый файл с именем, отличным от исходного файла
  • Только при удалении объекта Bitmap базовая блокировка файла будет удалена. После снятия блокировки вы можете перезаписать файл. Если вам необходимо перезаписать существующий файл, создайте отдельный растровый объект из существующего растрового объекта. Теперь удалите старый растровый объект, который снимет блокировку файла изображения. Go вперед и внесите необходимые изменения в новый растровый объект и сохраните новый растровый объект с исходным именем файла изображения.

Лучший способ сохранить изображение в файле 24bpp - использовать PixelFormat.Format24bppRgb для нового растрового объекта.

Вот пример:

using Bitmap imageCopy = null;
using(var imageFromName = new Bitmap(FileName1))
{
    // you can modify your image here
    ...
    // Before this block ends we need to copy Bitmap
    imageCopy = new Bitmap(imageFromName); // or imageFromName.Clone with expected format
}

imageCopy.Save(FileName1);

Другой способ - прочитать изображение мгновенно без блокировки файловой системы при редактировании:

using(var ms = new MemoryStream(File.ReadAllBytes(FileName1))
using(var image = new Bitmap(ms))
{
    // you can modify your image here
    ...
    image.Save(FileName1); 
}
...