
| A question that pops up all the time
is:
"I want to open an image file and then save that same file in a different format or back to the same filename after making modifications and I keep getting A generic error occurred in GDI" This problem arises because GDI+ tries to be IO efficient by reading in only the headers of an image, so that you can see its width, height, colour depth etc. It leaves the file open and locked so that it can go get the actual bits when you want to look at them. The file remains locked even after you've read all the bits in, for the lifetime of the Image object in fact, and therefore you cannot write back to that file with a modified version of the image. To have access to the file for writing, you must dispose of the original image, which makes it difficult to save it afterwards. The trick is to do the following:
The following application combines a file-format converter with a picture time-stamper that shows off this technique.
The following listing shows how. All the hard work is done in the button2_click handler. using
System; using
System.IO; using
System.Drawing; using
System.Drawing.Imaging; using
System.Collections; using
System.ComponentModel; using
System.Windows.Forms; using
System.Data; namespace
FormatConvertor { ///
<summary> ///
Summary description for Form1. ///
</summary> public class
Form1 : System.Windows.Forms.Form { private
System.Windows.Forms.Button button1; private
System.Windows.Forms.ComboBox comboBox1; private
System.Windows.Forms.Button button2; private
System.Windows.Forms.Label label1; private
System.Windows.Forms.CheckBox checkBox1; ///
<summary> ///
Required designer variable. ///
</summary> private
System.ComponentModel.Container components = null; public
Form1() { // //
Required for Windows Form Designer support // InitializeComponent(); // //
TODO: Add any constructor code after InitializeComponent call // } ///
<summary> ///
Clean up any resources being used. ///
</summary> protected
override void
Dispose( bool disposing ) { if(
disposing ) { if
(components != null) { components.Dispose(); } } base.Dispose(
disposing ); }
#region
Windows Form Designer generated code ///
<summary> ///
Required method for Designer support - do not modify ///
the contents of this method with the code editor. ///
</summary> private
void InitializeComponent() { this.button1
= new System.Windows.Forms.Button(); this.comboBox1
= new System.Windows.Forms.ComboBox(); this.button2
= new System.Windows.Forms.Button(); this.label1
= new System.Windows.Forms.Label(); this.checkBox1
= new System.Windows.Forms.CheckBox(); this.SuspendLayout(); //
//
button1 //
this.button1.Location
= new System.Drawing.Point(8, 24); this.button1.Name
= "button1"; this.button1.TabIndex
= 0; this.button1.Text
= "Choose files"; this.button1.Click
+= new System.EventHandler(this.button1_Click); //
//
comboBox1 //
this.comboBox1.Items.AddRange(new
object[] { "GIF", "JPG", "JPEG", "BMP", "PNG"}); this.comboBox1.Location
= new System.Drawing.Point(96, 24); this.comboBox1.Name
= "comboBox1"; this.comboBox1.Size
= new System.Drawing.Size(121, 21); this.comboBox1.TabIndex
= 1; //
//
button2 //
this.button2.Location
= new System.Drawing.Point(232, 24); this.button2.Name
= "button2"; this.button2.TabIndex
= 0; this.button2.Text
= "Convert"; this.button2.Click
+= new System.EventHandler(this.button2_Click); //
//
label1 //
this.label1.Location
= new System.Drawing.Point(96, 8); this.label1.Name
= "label1"; this.label1.Size
= new System.Drawing.Size(100, 16); this.label1.TabIndex
= 2; this.label1.Text
= "Output format"; //
//
checkBox1 //
this.checkBox1.Location
= new System.Drawing.Point(8, 64); this.checkBox1.Name
= "checkBox1"; this.checkBox1.Size
= new System.Drawing.Size(208, 24); this.checkBox1.TabIndex
= 3; this.checkBox1.Text
= "Time stamp the image."; //
//
Form1 //
this.AutoScaleBaseSize
= new System.Drawing.Size(5, 13); this.ClientSize
= new System.Drawing.Size(312, 93); this.Controls.AddRange(new
System.Windows.Forms.Control[] { this.checkBox1, this.label1, this.comboBox1, this.button1, this.button2}); this.FormBorderStyle
= System.Windows.Forms.FormBorderStyle.FixedDialog; this.Name
= "Form1"; this.Text
= "Image Format Converter"; this.ResumeLayout(false); }
#endregion ///
<summary> ///
The main entry point for the application. ///
</summary> [STAThread] static
void Main() { Application.Run(new
Form1()); } string[]
names; bool
chosen=false; private
void button1_Click(object
sender, System.EventArgs e) { OpenFileDialog
dlg = new OpenFileDialog(); dlg.Filter="Image
files (*.jpg,*.jpeg,*.bmp,*.gif,*.png)|*.BMP;*.PNG;*.JPG;*.JPEG;*.PNG"; dlg.Multiselect=true; if(dlg.ShowDialog()==DialogResult.OK) { chosen=true; names=dlg.FileNames; } } private
void button2_Click(object
sender, System.EventArgs e) { if(chosen
&& this.comboBox1.Text!="") { chosen=false; foreach(string
s in names) {
//open the file Image i = Image.FromFile(s);
//create temporary Image t=new Bitmap(i.Width,i.Height);
//get graphics Graphics g=Graphics.FromImage(t);
//copy original g.DrawImage(i,0,0);
//close original i.Dispose(); if(this.checkBox1.Checked==true) {
//draw on temporary Font
f = new Font("Verdana",30); g.DrawString(DateTime.Now.ToShortDateString()+":"+DateTime.Now.ToShortTimeString(), f, Brushes.Red, 10,10,
StringFormat.GenericTypographic); f.Dispose(); } g.Dispose(); ImageFormat
fmt = ImageFormat.Bmp; switch(this.comboBox1.Text) { case
"JPG": case
"JPEG": fmt=ImageFormat.Jpeg; break; case
"GIF": fmt=ImageFormat.Gif; break; case
"PNG": fmt=ImageFormat.Png; break; }
//save the file. Even if its the same filename t.Save(Path.GetFileNameWithoutExtension(s)+"."+this.comboBox1.Text,fmt); } } } } } Back to the GDI+ FAQ Copyright Robert W. Powell 2003. All rights reserved.
|