วิธีแก้ปัญหาที่อาจกำจัดปัญหาการเขียนทับไฟล์ที่เกี่ยวข้องนี้

ฉันกำลังโหลดไฟล์บิตแมปขนาด 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
@Joan, 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