Как решить эту потенциально связанную с удалением проблему перезаписи файла?

Я загружаю растровый файл размером 50x50, а затем заливаю его одним случайным цветом при запуске программы. Затем сохраните результат в тот же файл и назначьте его PictureBox, но столкнулись с проблемами записи файла и «Произошла общая ошибка в GDI+» и т. д.

Как это сделать правильно, чтобы я мог постоянно повторять это (открыть растровое изображение, раскрасить его случайным цветом, сохранить и назначить picturebox.Image)?

РЕДАКТИРОВАТЬ:

  public Form1 ( )
  {
   InitializeComponent ( );

   //Bitmap bmp = new Bitmap ( 50, 50 );
   Bitmap bmp = new Bitmap ( @"C:\temp\pretty.bmp" );

   Graphics g = Graphics.FromImage ( bmp );
   Brush b = new SolidBrush ( Color.Red );
   g.FillRectangle ( b, 0, 0, 49, 49 );
   bmp.Save ( @"C:\temp\pretty.bmp" );

   this.pictureBox1.Image = ( Image ) bmp.Clone ( );
   //bmp.Dispose ( );
  }

person Joan Venge    schedule 25.02.2010    source источник
comment
Объект Graphics управляет растровым изображением после вызова Graphics.FromImage? Если это так, возможно, вам нужно взаимодействовать с растровым изображением через объект Graphics или как-то отделить его от графического объекта, прежде чем вы попытаетесь Save или Dispose?   -  person Scott Smith    schedule 25.02.2010
comment
Спасибо, а как бы вы это сделали?   -  person Joan Venge    schedule 25.02.2010


Ответы (3)


Простая адаптация с правильными usings будет выглядеть так:

private void Form1_Load(object sender, EventArgs e)
{
    Bitmap bmp2;

    using (Bitmap bmp1 = new Bitmap(@"C:\temp\pretty.bmp"))
    {
//Edit: Clone was keeping a link between bmp1 and bmp2 somehow
       // bmp2 = (Bitmap)bmp1.Clone();
       IntPtr hbmp = bmp1.GetHbitmap();
       bmp2 = Bitmap.FromHbitmap(hbmp);     
    }

    using (Graphics g = Graphics.FromImage(bmp2))
    using (Brush b = new SolidBrush(Color.Red))
    {
        g.FillRectangle(b, 0, 0, 49, 49);

        bmp2.Save(@"C:\temp\pretty.bmp");
    }

    this.pictureBox1.Image = bmp2;   
}
person Henk Holterman    schedule 25.02.2010
comment
Спасибо, Хенк. Будет ли такое использование ключевых слов? Каков их эффект в этом случае? Все они принадлежат к одной области? - person Joan Venge; 26.02.2010
comment
@ Джоан, using работает так же, как if(): 1 оператор или несколько операторов в фигурных скобках. Отступ здесь нетипичен, но это общепринятая практика. - person Henk Holterman; 26.02.2010
comment
Спасибо, Хенк. Ты уверен? Я пытался несколько раз, но выдает общую ошибку GDI в bmp2.Save(@C:\temp\pretty.bmp);. - person Joan Venge; 26.02.2010
comment
@Джоан: Извини, ты прав. Я использовал 2 разных имени файла. Clone() явно недостаточно глубок. - person Henk Holterman; 26.02.2010

Когда вы используете конструктор Bitmap, который принимает параметр пути, он сохраняет файл открытым до тех пор, пока вы не удалите файл Bitmap. Вам нужно загрузить растровое изображение из Stream и закрыть Stream, чтобы файл был закрыт. Это должно работать нормально:

public Form1 ( )
{
    InitializeComponent ( );

     Bitmap bmp = null;
     using (Stream stream = File.OpenRead(@"C:\temp\pretty.bmp"))
     {
         bmp = new Bitmap(stream);
     }

     using (Graphics g = Graphics.FromImage ( bmp ))
     using (Brush b = new SolidBrush ( Color.Red ))
     {
         g.FillRectangle ( b, 0, 0, 49, 49 );
     }
     bmp.Save ( @"C:\temp\pretty.bmp" );
     this.pictureBox1.Image = bmp;
}
person Thomas Levesque    schedule 25.02.2010
comment
Вам также необходимо удалить файлы Bitmap, Graphics и Brush. (Если вы не используете SolidBrushes.Black) - person SLaks; 25.02.2010

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

Другой вариант — хранить изображения в потоках памяти, а не в файлах.

person Vlad    schedule 25.02.2010