none
Conversion WebControls.Image en Drawing.Image RRS feed

  • Question

  • Bonjour, dans une application web que je developpe, je génère une image à la volé dans une page web, que je passe à ImageUrl d'un objet WebControls.Image présent dans ma page Default.aspx.

     

    Dans la même page, j'ai un bouton VersPDF qui doit prendre le contenu de mon WebControls.Image et générer un fichier PDF, le problème qui se pose est que la méthode ToPDF que j'utilise peut avoir en paramètres soit un objet Drawing.Image ou un string contenant le chemin physique de l'image (à ignorer puisque on ne veux pas enregistrer l'image dans le serveur, ni chez le client).

     

    Ce qui m'a poussé à ecrire le code 2 fois, dans la 1ere page dans le Form_Load et dans la 2eme page dans VersPDF_Click:

    Form_Load(object sender, EventArgs e)

    {

    Image monImage;

    // Connexion à la base de données

    Connexion();

    DataSet myDataSet = new DataSet("monDataSet");

    // Declaration du DataAdapter et du DataTable

    OleDbDataAdapter myAdapter;

    string Requete = "SELECT Code, Tx1 FROM Table3";

    myAdapter = new OleDbDataAdapter(Requete, myConnection);

    myAdapter.Fill(myDataSet, "Table3");

    // Génération de l'image contenant un graphique de type BarChart

    BarChart bc = new BarChart(myDataSet, "mon BarChart", "Période", "Taux", 600, 500,

    chemin, new Pen(Brushes.Gray), new Font("Verdana", 8), Brushes.Black, Brushes.White);

    monImage = bc.GenerateChart();

    monImage.Save(Response.OutputStream, ImageFormat.Jpeg);

    // Libération des ressources utilisées par bc

    bc.Dispose();

    // Déconnexion de la base de données

    Deconnexion();

    }

     

    le même code a été repris dans le VersPDF_Click

    protected void Button1_Click(object sender, EventArgs e)

    {

    string Requete = "SELECT Code, Tx1 FROM Table3";

    myAdapter = new OleDbDataAdapter(Requete, myConnection);

    myAdapter.Fill(myDataSet, "Table3");

    BarChart bc = new BarChart(myDataSet, "mon BarChart", "Période", "Taux", 600, 500,

    chemin, new Pen(Brushes.Gray), new Font("Verdana", 8), Brushes.Black, Brushes.White);

    monImage = bc.GenerateChart();

    PDF myPdf = new PDF("Titre", "Auteur");

    myPdf.ToPdf(monImage, path + "D:\\Webform.pdf");

    }

     

    pour éviter à retaper le code 2 fois, y aurait il un moyen de convertir un objet WebControls.Image en Drawing.Image, n'importe quelle suggestion sera la bienvenue

     

    merci d'avance

    jeudi 4 octobre 2007 00:10

Réponses

  • Bonjour,

     

    La classe System.Drawing.Image s'appuyant sur GDI+, il n'est pas recommandé de mettre en cache l'objet image généré par la méthode GenerateChart.

     

    A mon avis la seule solution qui tienne la route est de faire une sérialization binaire de l'objet image dans un tableau d'octets, puis de mettre en cache ce tableau d'octets soit dans l'objet Session soit dans l'objet Cache.

     

    Le code suivant devrait vous montrer comment faire :

     

    Extrait de code

    private System.Drawing.Image GetImageFromDataSource()
        {

             System.Drawing.Image myImage = System.Drawing.Image.FromFile(@"c:\temp\test.bmp");

     

             // On met l'image en cache

            

            // On instancie un sérialiseur binaire
            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter mySerializer = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();


            // On effectue la sérialisation

            System.IO.MemoryStream myStream = new System.IO.MemoryStream();

            mySerializer.Serialize(myStream,myImage);

     

            //On génère un tableau de bytes à partir du stream
            byte[] myByteArray = myStream.ToArray();

            // on finalise le stream;
            myStream.Close();
            myStream.Dispose();
            myStream = null;

     

            // on met l'image en cache
            Session["myImage"] = myByteArray;
            return myImage;
        }

     

     

    private System.Drawing.Image GetImageFromCache()
        {
            // on tente de récupérer l'image du cache
            System.Object myObject = Session["myImage"];
            if (myObject == null)
            {
                return GetImageFromDataSource();
            }

            // Ok, l'image ets bien en cache : il faut désérialiser

            byte[] myImageAsByteArray = (byte[])myObject;
            System.IO.MemoryStream myStream = new System.IO.MemoryStream();
            myStream.Write(myImageAsByteArray, 0, myImageAsByteArray.Length);
            myStream.Position = 0;

            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter mySerializer = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();


            System.Drawing.Image myImage = (System.Drawing.Image) mySerializer.Deserialize(myStream);
           
            myStream.Close();
            myStream.Dispose();
            myStream = null;

            return myImage; 
            }

     

     

    protected void Page_Load(object sender, EventArgs e)
        {

            System.Drawing.Image myImage = GetImageFromCache();

            // code de test, juste pour vérifier que la désérialisation a fonctionnée
            myImage.Save(@"c:\temp\titi.bmp");


            myImage.Save(Response.OutputStream, ImageFormat.Jpeg);
            myImage.Dispose();

        }

     

     

     

     

     

     

     

     

     

     

    vendredi 5 octobre 2007 19:07

Toutes les réponses

  • Bonjour,

     

    La classe System.Drawing.Image s'appuyant sur GDI+, il n'est pas recommandé de mettre en cache l'objet image généré par la méthode GenerateChart.

     

    A mon avis la seule solution qui tienne la route est de faire une sérialization binaire de l'objet image dans un tableau d'octets, puis de mettre en cache ce tableau d'octets soit dans l'objet Session soit dans l'objet Cache.

     

    Le code suivant devrait vous montrer comment faire :

     

    Extrait de code

    private System.Drawing.Image GetImageFromDataSource()
        {

             System.Drawing.Image myImage = System.Drawing.Image.FromFile(@"c:\temp\test.bmp");

     

             // On met l'image en cache

            

            // On instancie un sérialiseur binaire
            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter mySerializer = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();


            // On effectue la sérialisation

            System.IO.MemoryStream myStream = new System.IO.MemoryStream();

            mySerializer.Serialize(myStream,myImage);

     

            //On génère un tableau de bytes à partir du stream
            byte[] myByteArray = myStream.ToArray();

            // on finalise le stream;
            myStream.Close();
            myStream.Dispose();
            myStream = null;

     

            // on met l'image en cache
            Session["myImage"] = myByteArray;
            return myImage;
        }

     

     

    private System.Drawing.Image GetImageFromCache()
        {
            // on tente de récupérer l'image du cache
            System.Object myObject = Session["myImage"];
            if (myObject == null)
            {
                return GetImageFromDataSource();
            }

            // Ok, l'image ets bien en cache : il faut désérialiser

            byte[] myImageAsByteArray = (byte[])myObject;
            System.IO.MemoryStream myStream = new System.IO.MemoryStream();
            myStream.Write(myImageAsByteArray, 0, myImageAsByteArray.Length);
            myStream.Position = 0;

            System.Runtime.Serialization.Formatters.Binary.BinaryFormatter mySerializer = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();


            System.Drawing.Image myImage = (System.Drawing.Image) mySerializer.Deserialize(myStream);
           
            myStream.Close();
            myStream.Dispose();
            myStream = null;

            return myImage; 
            }

     

     

    protected void Page_Load(object sender, EventArgs e)
        {

            System.Drawing.Image myImage = GetImageFromCache();

            // code de test, juste pour vérifier que la désérialisation a fonctionnée
            myImage.Save(@"c:\temp\titi.bmp");


            myImage.Save(Response.OutputStream, ImageFormat.Jpeg);
            myImage.Dispose();

        }

     

     

     

     

     

     

     

     

     

     

    vendredi 5 octobre 2007 19:07
  • Merci pour votre réponse, je vais étudier votre code et je vous tiendrai au courant.

    vendredi 5 octobre 2007 19:41