OutOfMemoryException quand je fait Graphics.FromImage

Résolu
FPell Messages postés 2 Date d'inscription mercredi 7 avril 2004 Statut Membre Dernière intervention 11 novembre 2008 - 10 nov. 2008 à 02:20
olibara Messages postés 666 Date d'inscription dimanche 16 décembre 2007 Statut Membre Dernière intervention 11 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;

}

}

}

4 réponses

xmox667 Messages postés 357 Date d'inscription jeudi 8 juin 2006 Statut Membre Dernière intervention 26 décembre 2011 4
10 nov. 2008 à 14:40
Salut,
Moi j'utilise ceci pour charger mes images:

 public Bitmap ImageFromFile(string filename)
        {
            FileStream Stream = File.Open(filename , FileMode.Open);
            Bitmap Image = new Bitmap(Stream,true);
            Stream.Close();
            return Image;           
        }
A+
3
FPell Messages postés 2 Date d'inscription mercredi 7 avril 2004 Statut Membre Dernière intervention 11 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.
3
olibara Messages postés 666 Date d'inscription dimanche 16 décembre 2007 Statut Membre Dernière intervention 11 mars 2010 6
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.
3
Lutinore Messages postés 3246 Date d'inscription lundi 25 avril 2005 Statut Membre Dernière intervention 27 octobre 2012 41
10 nov. 2008 à 12:43
Salut, ne ferme pas le stream ou utilise une autre méthode pour charger l'image.
0
Rejoignez-nous