2009-07-20 8 views
1

Hier ist mein Code zum Serialisieren, Deserialisieren und Speichern eines Bildes im Dateisystem. Ich habe mir viele Beispiele für Serialisierung/Deserialisierung angeschaut und möchte nur ein paar Rückmeldungen erhalten, da ich sicher bin, dass mein Code verbessert werden kann. Jede Rückmeldung wird sehr geschätzt. Ich weiß, dass dies ein häufiges Problem ist, und hoffentlich wird diese Frage in Zukunft eine gute Ressource für andere sein.Feedback zu Code zum Serialisieren, Deserialisieren und Speichern von Bildern

Dies ist der überarbeitete Code mit Empfehlungen:

private void Form1_Load(object sender, EventArgs e) 
    { 
     RunTest(); 
    } 

    private void RunTest() 
    { 
     byte[] jpgba = ConvertFileToByteArray("D:\\Images\\Image01.jpg"); 
     using (Image jpgimg = ConvertByteArrayToImage(jpgba)) 
     { 
      SaveImageToFileSystem(jpgimg, "D:\\Images\\Image01_Copy.jpg"); 
     } 

     byte[] pngba = ConvertFileToByteArray("D:\\Images\\Image02.png"); 
     using (Image pngimg = ConvertByteArrayToImage(pngba)) 
     { 
      SaveImageToFileSystem(pngimg, "D:\\Images\\Image02_Copy.png"); 
     } 

     byte[] gifba = ConvertFileToByteArray("D:\\Images\\Image03.gif"); 
     using (Image gifimg = ConvertByteArrayToImage(gifba)) 
     { 
      SaveImageToFileSystem(gifimg, "D:\\Images\\Image03_Copy.gif"); 
     } 

     MessageBox.Show("Test Complete"); 
     this.Close(); 
    } 

    private static byte[] ConvertFileToByteArray(String FilePath) 
    { 
     return File.ReadAllBytes(FilePath); 
    } 

    private static Image ConvertByteArrayToImage(byte[] ImageByteArray) 
    { 
     using (MemoryStream ms = new MemoryStream(ImageByteArray)) 
     { 
      return Image.FromStream(ms); 
     } 
    } 

    private static void SaveImageToFileSystem(Image ImageObject, string FilePath) 
    { 
     // ImageObject.Save(FilePath, ImageObject.RawFormat); 
     // This method only works with .png files. 

     // This method works with .jpg, .png and .gif 
     // Need to copy image before saving. 
     using (Image img = new Bitmap(ImageObject.Width, ImageObject.Height)) 
     { 
      using (Graphics tg = Graphics.FromImage(img)) 
      { 
       tg.DrawImage(ImageObject, 0, 0); 
      } 
      img.Save(FilePath, img.RawFormat); 
     } 
     return; 
    } 
+0

meine größte Empfehlung wäre, das "using" -Muster zu verwenden. –

+0

Danke allen! Mit dem Stellen dieser Frage habe ich erkannt, wie wichtig es ist, Code unter Kollegen zu diskutieren und zu teilen. Ich muss viel lernen und die Community hinter dieser Seite war eine fantastische Ressource. Ich habe jetzt ein paar ernsthafte Re-Factoring zu tun! – Tim

Antwort

3

Was ich aus kurzem Blick sehen habe:

Streams in gewickelt werden soll, mit (...) Mustern, in Ihrem Falls während der Verarbeitung eine Ausnahme auftritt, wird Dispose() nicht aufgerufen.

using (FileStream fs = new FileStream(FilePath, FileMode.Open)) 
{ 
    // Another small optimization, removed unnecessary variable 
    byte[] iba = new byte[(int)fs.Length]; 
    fs.Read(iba, 0, iba.Length); 
} 

Sie sollten nur Ausnahmen abfangen, die Sie erwarten. In SerializeImage ist dies beispielsweise IOException. Das Einfangen aller Ausnahmen ist sehr schlecht.

} 
catch (IOException ex) 
{ 

Image.FromStream Methode hängt von Strom, wenn Sie also zugrunde liegenden Stream schließen und Bild Sie unvorhersehbares Verhalten empfangen können (gut, in den meisten Fällen wird dies funktionieren, aber manchmal treten Fehler). Sie müssen also eine Bildkopie erstellen und sie zurückgeben.

using (MemoryStream ms = new MemoryStream(ImageByteArray)) 
{ 
    using (Image img = Image.FromStream(ms)) 
    { 
     return new Bitmap(img); 
    } 
} 

Sie sind nicht angeordnet tg Grafikobjekt und img Objekt in Saveimage-Methode (aber angeordnete Imageobject, siehe nächster Absatz). Und im Allgemeinen sehe ich keine Notwendigkeit in einer solchen Logik, rufen Sie einfach ImageObject.Save (..., ImageFormat.Png) auf, wenn Sie die Bildkonservierungsqualität speichern möchten.

In der gleichen Methode (SaveImage) sind Sie ImageObject Parameter angeordnet. Dies ist auch eine schlechte Praxis in den meisten Fällen, betrachten Sie dieses Bild außerhalb der Worker-Methode mit mit (...) Muster.

1

Hier ist ein bisschen mehr.

private void RunTest() 
{ 
    // byte array that can be stored in DB 
    byte[] iba; 

    // image object to display in picturebox or used to save to file system. 

    iba = ReadImage("D:\\Images\\Image01.jpg"); 
    using (Image img = DeserializeImage(iba)) 
    { 
     SaveImage(img, "D:\\Images\\Image01_Copy.jpg"); 
    } 

    iba = ReadImage("D:\\Images\\Image02.png"); 
    using (Image img1 = DeserializeImage(iba)) 
    { 
     SaveImage(img1, "D:\\Images\\Image02_Copy.png"); 
    } 

    iba = ReadImage("D:\\Images\\Image03.gif"); 
    using (var img2 = DeserializeImage(iba)) 
    { 
     SaveImage(img2, "D:\\Images\\Image03_Copy.gif"); 
    } 

    MessageBox.Show("Test Complete"); 
} 

private static byte[] ReadImage(String filePath) 
{ 
    // This seems to be the easiest way to serialize an image file 
    // however it would be good to take a image object as an argument 
    // in this method. 
    using (var fs = new FileStream(filePath, FileMode.Open)) 
    { 
     Int32 fslength = Convert.ToInt32(fs.Length); 
     var iba = new byte[fslength]; 
     fs.Read(iba, 0, fslength); 
     return iba; 
    } 
} 

private static Image DeserializeImage(byte[] imageByteArray) 
{ 
    using (var ms = new MemoryStream(imageByteArray)) 
    { 
     return Image.FromStream(ms); 
    } 
} 

private static void SaveImage(Image imageObject, string filePath) 
{ 
    // I could only get this method to work for .png files. 
    // imageObject.Save(filePath, imageObject.RawFormat); 

    // This method works with .jpg, .png and .gif 
    // Need to copy image before saving. 
    using (Image img = new Bitmap(imageObject.Width, imageObject.Height)) 
    { 
     using (Graphics tg = Graphics.FromImage(img)) 
     { 
      tg.DrawImage(imageObject, 0, 0); 
     } 

     img.Save(filePath, img.RawFormat); 
    } 

    return; 
} 

Hinweis, was Sie Serialisieren genannt nur die Bytes liest in Serialisieren ist, was Sie tun, wenn Sie speichern.

Ich habe alle Try/Catch-Blöcke los. Das Beste, was sie für Sie tun, ist, Ihnen zu sagen, ob das Problem beim Lesen, Speichern oder Deserialisieren aufgetreten ist. Sie können dies aus der Stack-Spur, die Sie zerstört haben, ermitteln, indem Sie nur ex.Message anzeigen.

Sie haben auch bei einer ernsten Ausnahme null zurückgegeben und Fehler propagiert.

Abgesehen davon stimme ich mit allem Schiedsrichter sagte.

+0

Wie wäre es mit: 'private byte [] ReadImage (Zeichenfolge filePath) {return File.ReadAllBytes (filePath); } ' – LukeH

+0

Noch besser. Ich konnte mich nicht erinnern, dass es eines gibt. Bessere Idee, da auf jeden Fall nichts mit dem Stream gemacht wird. –

0

Wie John Saunder sagt, Serialisierung und Deserialisierung sind mehr als nur das Lesen der Rohdaten aus einer Datei. Siehe Wiki auf Serialization

Für Bilder in .net, brauchen Sie nichts mehr als die vorgesehenen Rahmen Methoden (die meiste Zeit)

So Laden eine Bilddatei (De-Serialisierung) in .net ist.

using System.Drawing.Image; 

Image test; 

test = Image.FromFile(@"C:\myfile.jpg") 
test = Image.FromStream(myStream); // or you can load from an existing stream 

Ebenso Speichern des Bildes (Serialisierung) ist:

test.Save(@"C:\anotherFile.jpg", System.Drawing.Imaging.ImageFormat.Jpeg); 

Dies sind die Grundlagen des Ladens sind und ein Bild in .net zu speichern. Wenn Sie ein spezifischeres Szenario haben, stellen Sie eine andere Frage.

Verwandte Themen