[...] Just use the Bitmap constructor that takes an Image as an
argument, and ..NET will do the copying for you automatically (added
bonus: no Graphics instance at all, never mind one you need to dispose
![Smile :) :)](/styles/default/custom/smilies/smile.gif)
).
Hi Pete,
I had tried this before, but it will throw GDI+ exception
Image image3 = new Bitmap(image2);
...
image3.Save(filename2, ImageFormat.Jpeg);
Did you dispose "image2" before trying to save over its file?
I've used that exact technique before, so I know it works in the general
case. If you're seeing an exception, either you've left something out, or
there's something unique about your specific scenario.
[...]
This is my first take, but the strange thing is the GDI+ keeps the file
locked. Here is my code.
string filename1 = "D:\\Temp\\output1.jpg";
string filename2 = "D:\\Temp\\output2.jpg";
Image image1 = Image.FromFile(filename1);
using (FileStream stream = new FileStream(filename2, FileMode.Open,
FileAccess.Read, FileShare.ReadWrite))
{
using (Image image2 = Image.FromStream(stream))
{
PropertyItem property = image1.GetPropertyItem(271);
property.Id = 40092;
image2.SetPropertyItem(property);
image2.Save(filename2);
}
}
Am I missing something?
In that specific example, I don't see anything obviously wrong. Assuming
that there's nothing important in the code you left out, we're either back
to some issue with the PropertyItem itself, or an OS/.NET version
difference.
I'm testing on Windows 7 RTM, .NET 3.5 SP1. I've included a
concise-but-complete code example below that demonstrates the use of
FileShare.ReadWrite to successfully modify and save over the original
file, without the need for an in-memory copy. You should be able to use
that without any additional effort to see whether you see a locking issue
on your configuration; if not, then there's something about the specific
usage your code has that's causing problems, rather than a general failure
with a locked file (and even in that latter case, it would be some sort of
version-specific issue, as I don't have any locking issues with the code
I'm posting).
Pete
using System;
using System.Windows.Forms;
using System.Drawing;
using System.IO;
namespace TestImageFileShareMode
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
public class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// For deleting temp file before exiting
private string _strDelete;
protected override void OnFormClosed(FormClosedEventArgs e)
{
if (_strDelete != null)
{
File.Delete(_strDelete);
}
base.OnFormClosed(e);
}
private void button1_Click(object sender, EventArgs e)
{
using (OpenFileDialog ofn = new OpenFileDialog())
{
ofn.Multiselect = false;
if (ofn.ShowDialog() == DialogResult.OK)
{
string strTemp = Path.GetTempFileName();
try
{
// Verify the original file is actually an image
file before bothering
// with processing
using (Image imgOriginal =
Image.FromFile(ofn.FileName)) { }
// Make a copy that we can write over later
File.Copy(ofn.FileName, strTemp, true);
// Load image from copy, modify it, and save it
using (FileStream stream = new FileStream(strTemp,
FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
using (Image imgOriginal =
Image.FromStream(stream))
{
using (Graphics gfx =
Graphics.FromImage(imgOriginal))
using (Font font = new
Font(FontFamily.GenericSansSerif, 18, FontStyle.Bold))
using (Brush brush = new SolidBrush(Color.Red))
{
gfx.DrawString("This is a test", font,
brush, new PointF());
}
imgOriginal.Save(strTemp);
}
// Update our GUI to display the modified image
(for
// verification purposes...not critical to the
example)
pictureBox1.ImageLocation = strTemp;
// Clean up previous temp file, reset to current
one
if (_strDelete != null)
{
File.Delete(_strDelete);
}
_strDelete = strTemp;
}
catch (Exception exc)
{
MessageBox.Show(string.Format("Failed: \"{0}\"",
exc.Message));
File.Delete(strTemp);
}
}
}
}
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be
disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (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.panel1 = new System.Windows.Forms.Panel();
this.pictureBox1 = new System.Windows.Forms.PictureBox();
this.panel1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(13, 13);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 0;
this.button1.Text = "button1";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new
System.EventHandler(this.button1_Click);
//
// panel1
//
this.panel1.Anchor =
((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top
| System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.panel1.AutoScroll = true;
this.panel1.Controls.Add(this.pictureBox1);
this.panel1.Location = new System.Drawing.Point(13, 43);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(513, 342);
this.panel1.TabIndex = 1;
//
// pictureBox1
//
this.pictureBox1.Location = new System.Drawing.Point(4, 4);
this.pictureBox1.Name = "pictureBox1";
this.pictureBox1.Size = new System.Drawing.Size(506, 335);
this.pictureBox1.SizeMode =
System.Windows.Forms.PictureBoxSizeMode.AutoSize;
this.pictureBox1.TabIndex = 0;
this.pictureBox1.TabStop = false;
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(538, 397);
this.Controls.Add(this.panel1);
this.Controls.Add(this.button1);
this.Name = "Form1";
this.Text = "Form1";
this.panel1.ResumeLayout(false);
this.panel1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.PictureBox pictureBox1;
}
}