Donnerstag, 28. Oktober 2010

Bild in byte - Array speichern

Um mit C# ein Bild (Image) in ein byte - Array zu konvertieren, speichern wir das Bild zuerst in einen Stream und kopieren den Inhalt dieses Streams dann in ein byte - Array.
Prinzipiell kann jeder Streamtyp dazu verwendet werden, am einfachsten ist jedoch die Verwendung eines MemoryStreams, welcher lediglich temporär Daten in den Arbeitsspeicher schreibt bzw. daraus liest.
Ein Bild vom Typ Image kann über die Methode Save() in den als 1. Parameter spezifizierten Stream geschrieben werden, als 2. Parameter kann das Format angegeben werden, in welchem das Bild gespeichert werden soll (also z.B. Gif oder Bmp).
Der folgende Beispielcode speichert den Inhalt der pictureBox auf dem Formular in einem byte - Array:

            MemoryStream TempStream = new MemoryStream();
            byte[] ImageInBytes;

            pictureBox1.Image.Save(TempStream, System.Drawing.Imaging.ImageFormat.Gif);
            ImageInBytes = TempStream.ToArray();

Kommentare:

  1. irgendwie kommt da bei mir immer ein allgemeiner gdi+ fehler -.-

    AntwortenLöschen
  2. Hi,
    ja der Fehler ist ätzend, ich habe über diesen einen eigenen Post geschrieben siehe http://csharp-tricks.blogspot.com/ .
    Ich könnte wetten, du lädst das Bild vorher aus einer Datei und willst es dann in den Stream speichern? Dann ist der nächste Post deine Erklärung, ansonsten kannst du ja mal den Quellcode posten.

    AntwortenLöschen
  3. jap das war mein Fehler -.-
    thx für die schnelle Hilfe!

    AntwortenLöschen
  4. Salü zusammen

    Habe auf der Suche nach meinem Problem diesen Blog gefunden. Weiss jemand warum ich einen MemoryOverflow bekomme in folgendem Code, und wie ich das verhindern kann?

    Dim bildPfad As String
    bildPfad = "D:/testimage/THIERSHEIM.jpg"
    Bild2 = New Bitmap(bildPfad)

    Das Bild ist unter folgendem Link zu finden:
    http://de.academic.ru/pictures/dewiki/84/THIERSHEIM.jpg


    Vielen Dank für Hinweise jeglicher Art.

    AntwortenLöschen
  5. Salü,
    hm MemoryOverflow deutet ja auf einen Speicherüberlauf hin, wie groß ist das Bild? Habs runtergeladen, ca. 4 MB, stimmt das? Das sollte ja jeder PC eigentlich schaffen ...
    Wie lautet denn der Fehler genau?
    Bei mir funktioniert das C# Pendant zu deinem VB Code ohne Probleme:

    String bildPfad;
    bildPfad = @"C:\Users\User\Desktop\THIERSHEIM.jpg";
    Bitmap Bild2 = new Bitmap(bildPfad);

    Wo wird Bild2 bei dir deklariert?
    Lg

    AntwortenLöschen
  6. Hallo, vielen Dank für Deine Infos. Ja, rund 4MB Bild. Meine Problemstellung war bereits sehr vereinfacht und führte in meinem System zum Speicherüberlauf.
    In Wirklichkeit lese ich das Bild über einen MemoryStream auf eine Image Klasse (sourceImage).

    sourceImage = CType(Bitmap.FromStream(uxRadUpload.UploadedFiles(0).InputStream, True, False), Bitmap) '<-- Fehlerhafte Zeile, jetzt neu ValidateImageDate=false geht ohne Memory Overflow.

    Ich habe mittlerweile einen Weg zugetragen bekommen. ValidateImageDate=false bei der Konvertierung und dann wird das Bild nicht entkomprimiert. Somit gibt es auch keinen Memory Overflow. Das 4 MB Bild wird beim entkomprimieren einige hundert MB gross. Das sprengt den Webserver obwohl dieser 4GB Ram hat.

    Nun habe ich das Problem allerdings an einer anderen Stelle.
    Gleiches Bild will ich von VicLib in ein PNG konvertieren lassen.
    Der Codeabschnitt ist:
    Case ImageFormat.Jpeg
    Dim jinfo As vicwin.JpegData
    rcode = vicwin.jpeginfofrombuffer (inbuff, jinfo)
    If (rcode = vicwin.NO_ERROR) Then
    rcode = vicwin.allocimage(srcimg, jinfo.width, jinfo.length, jinfo.vbitcount) '<-- produziert rcode -14
    If (rcode = vicwin.NO_ERROR) Then
    rcode = vicwin.loadjpgfrombuffer (inbuff, srcimg)
    End If
    End If

    Dabei endet er mit rcode=-14 was wiederum Insulficent Memory ist.

    An der Zeile
    rcode = vicwin.allocimage(srcimg, jinfo.width, jinfo.length, jinfo.vbitcount)
    kann ich ja wohl nicht viel rumschrauben, da dies aus der VicLib.dll kommt.

    Spannend ist auch, dass dieses Problem sowohl auf einer Maschine mit 2GB Ram (mein Entwicklungssystem) als auch auf dem Server mit 4GB Ram auftaucht.

    Hat jemand eine Idee?
    Kennt jemand ein deutschsprachiges Forum für VicLib?
    Seit herzlich gegrüsst

    AntwortenLöschen
  7. (Wieso) - braucht denn der Stream bzw. das Array gar keine Größenangabe?

    AntwortenLöschen
  8. Weil er das Array automatisch vergrößert (nat. mit umkopieren des gesamten bisherigen Bytearrays, aber es funktioniert). Du kannst dem Memorystream im Konstruktor aber eine Größenangabe angeben, die er dann als Startwert nimmt.

    AntwortenLöschen