FPell
Messages postés2Date d'inscriptionmercredi 7 avril 2004StatutMembreDernière intervention11 novembre 2008
-
10 nov. 2008 à 02:20
olibara
Messages postés666Date d'inscriptiondimanche 16 décembre 2007StatutMembreDernière intervention11 mars 2010
-
11 nov. 2008 à 22:30
J'ai un programme qui sert à modifier une image et ajouter du texte dessus et il supporte l'opération annuler.
Mais quand je clone l'image originale (pour pouvoir annuler ensuite), quand je fais Graphics.FromImage pour modifier l'image, j'ai une exception OutOfMemoryException qui est lancée.
Notez que je fait Graphics.FromImage à partir de l'image originale, et non pas à partir de la copie (clone).
Voici un code très simplifié qui montre le bogue que j'ai :
using System;
using System.Drawing;
using System.Windows.Forms;
using System.IO;
namespace TestImage
{
/// <summary>
/// Description résumée de Form1.
/// </summary>
public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Button btnLoad;
private System.Windows.Forms.OpenFileDialog openFileDialog1;
/// <summary>
/// Variable nécessaire au concepteur.
/// </summary>
private System.ComponentModel.Container components = null;
public Form1()
{
//
// Requis pour la prise en charge du Concepteur Windows Forms
//
InitializeComponent();
//
// TODO : ajoutez le code du constructeur après l'appel à InitializeComponent
//
}
/// <summary>
/// Nettoyage des ressources utilisées.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Code généré par le Concepteur Windows Form
/// <summary>
/// Méthode requise pour la prise en charge du concepteur - ne modifiez pas
/// le contenu de cette méthode avec l'éditeur de code.
/// </summary>
private void InitializeComponent()
{
this.btnLoad = new System.Windows.Forms.Button();
this.openFileDialog1 = new System.Windows.Forms.OpenFileDialog();
this.SuspendLayout();
//
// btnLoad
//
this.btnLoad.Anchor = System.Windows.Forms.AnchorStyles.None;
this.btnLoad.Location = new System.Drawing.Point(72, 128);
this.btnLoad.Name = "btnLoad";
this.btnLoad.Size = new System.Drawing.Size(152, 23);
this.btnLoad.TabIndex = 0;
this.btnLoad.Text = "Load And Clone Image";
this.btnLoad.Click += new System.EventHandler(this.btnLoad_Click);
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(292, 273);
this.Controls.Add(this.btnLoad);
this.Name = "Form1";
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// Point d'entrée principal de l'application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void btnLoad_Click(object sender, System.EventArgs e)
{
openFileDialog1.ShowDialog(this);
String strFileName = openFileDialog1.FileName;
if (strFileName.Length > 0)
CloneAndGetGraphicsFromOriginalImage(strFileName);
}
private void CloneAndGetGraphicsFromOriginalImage(String strFileName)
{
FileStream stream = File.Open(strFileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
Image OriginalImage = Image.FromStream(stream);
stream.Close();
//Si j'enlève cette ligne-ci, tout fonctionnerait bien (mais dans ma vrai application j'en ai de besoin pour permettre d'annuler)
Image imgClone = (Image)(OriginalImage.Clone()); // Avec cette ligne, la ligne suivante va lancer un OutOfMemoryException
Graphics g = Graphics.FromImage(OriginalImage); // <-- Lance un OutOfMemoryException, quand l'image a été cloné.
g.DrawString("test", DefaultFont, new SolidBrush(Color.Black), 0, 0);
this.BackgroundImage = OriginalImage;
}
}
}
FPell
Messages postés2Date d'inscriptionmercredi 7 avril 2004StatutMembreDernière intervention11 novembre 2008 11 nov. 2008 à 01:35
Merci beaucoup, en effet ça fonctionne très bien avec
Image OriginalImage = Image.FromStream(stream, true);
Le dernier paramètre True semble important quand on ferme le stream.
olibara
Messages postés666Date d'inscriptiondimanche 16 décembre 2007StatutMembreDernière intervention11 mars 20105 11 nov. 2008 à 22:30
Tres intéressant !
J'avais un problème similaire !
Il semble en effet que la gestion du buffer image reponde a des regles un peu floues
J'avais remarqué que pour exploiter les property items il fallait
1- Soit les lires AVANT la fermeture du fichier
2- Soit en lire un qulquonque avant de fermer le fichier
3- Si une des ces deux operations a été faites il restent consistant APRES la fermeture SINON ca pete !
Mais ton post vient de me faire découvrir les option complementaires de la methode FromStream qui vont forcer le lock du buffer data
FromStream(stream,bool,bool);
Creates an Image from the specified data stream, optionally using embedded color management information and validating the image data.