So konvertieren Sie ein Bild in ein Byte-Array


125

Kann jemand vorschlagen, wie ich ein Bild in ein Byte-Array konvertieren kann und umgekehrt?

Ich entwickle eine WPF-Anwendung und verwende einen Stream-Reader.

Antworten:


174

Beispielcode zum Ändern eines Bildes in ein Byte-Array

public byte[] ImageToByteArray(System.Drawing.Image imageIn)
{
   using (var ms = new MemoryStream())
   {
      imageIn.Save(ms,imageIn.RawFormat);
      return  ms.ToArray();
   }
}

C # Image to Byte Array und Byte Array to Image Converter Klasse


12
stattdessen System.Drawing.Imaging.ImageFormat.Gifkönnen Sie verwendenimageIn.RawFormat
S.Serpooshan

1
Dies scheint nicht wiederholbar zu sein, oder zumindest nach ein paar Konvertierungen treten merkwürdige GDI + -Fehler auf. Die ImageConverterunten stehende Lösung scheint diese Fehler zu vermeiden.
Dave Cousineau

Könnte heutzutage besser sein, png zu verwenden.
Nyerguds

Nebenbei bemerkt: Dies könnte zusätzliche Metadaten enthalten, die Sie nicht haben möchten ;-) Um die Metadaten zu entfernen, möchten Sie möglicherweise eine neue Bitmap erstellen und das Bild wie folgt an sie übergeben (new Bitmap(imageIn)).Save(ms, imageIn.RawFormat);.
Markus Safar

56

Zum Konvertieren eines Bildobjekts in byte[]können Sie wie folgt vorgehen:

public static byte[] converterDemo(Image x)
{
    ImageConverter _imageConverter = new ImageConverter();
    byte[] xByte = (byte[])_imageConverter.ConvertTo(x, typeof(byte[]));
    return xByte;
}

4
Perfekte Antwort! .... keine Notwendigkeit, die "Bilddateierweiterung" zu definieren, genau das, wonach ich gesucht habe.
Bravo

1
Nebenbei bemerkt: Dies könnte zusätzliche Metadaten enthalten, die Sie nicht haben möchten ;-) Um die Metadaten zu entfernen, möchten Sie möglicherweise eine neue Bitmap erstellen und das Bild wie folgt an sie übergeben .ConvertTo(new Bitmap(x), typeof(byte[]));.
Markus Safar

1
Für mich erkennt Visual Studio den Typ ImageConverter nicht. Gibt es eine Importanweisung, die benötigt wird, um dies zu verwenden?
technoman23

32

Eine andere Möglichkeit, das Byte-Array vom Bildpfad abzurufen, ist

byte[] imgdata = System.IO.File.ReadAllBytes(HttpContext.Current.Server.MapPath(path));

Ihre Frage ist mit WPF gekennzeichnet (also kein Grund zu der Annahme, dass sie auf einem Server ausgeführt wird und einen MapPath enthält) UND zeigt, dass sie das Image bereits haben (kein Grund, es von der Festplatte zu lesen, nicht einmal davon auszugehen, dass es sich zunächst auf der Festplatte befindet). Es tut mir leid, aber Ihre Antwort scheint für die Frage völlig irrelevant zu sein
Ronan Thibaudau

18

Folgendes verwende ich derzeit. Einige der anderen Techniken, die ich ausprobiert habe, waren nicht optimal, da sie die Bittiefe der Pixel (24-Bit gegenüber 32-Bit) geändert oder die Bildauflösung (dpi) ignoriert haben.

  // ImageConverter object used to convert byte arrays containing JPEG or PNG file images into 
  //  Bitmap objects. This is static and only gets instantiated once.
  private static readonly ImageConverter _imageConverter = new ImageConverter();

Bild-zu-Byte-Array:

  /// <summary>
  /// Method to "convert" an Image object into a byte array, formatted in PNG file format, which 
  /// provides lossless compression. This can be used together with the GetImageFromByteArray() 
  /// method to provide a kind of serialization / deserialization. 
  /// </summary>
  /// <param name="theImage">Image object, must be convertable to PNG format</param>
  /// <returns>byte array image of a PNG file containing the image</returns>
  public static byte[] CopyImageToByteArray(Image theImage)
  {
     using (MemoryStream memoryStream = new MemoryStream())
     {
        theImage.Save(memoryStream, ImageFormat.Png);
        return memoryStream.ToArray();
     }
  }

Byte-Array zu Bild:

  /// <summary>
  /// Method that uses the ImageConverter object in .Net Framework to convert a byte array, 
  /// presumably containing a JPEG or PNG file image, into a Bitmap object, which can also be 
  /// used as an Image object.
  /// </summary>
  /// <param name="byteArray">byte array containing JPEG or PNG file image or similar</param>
  /// <returns>Bitmap object if it works, else exception is thrown</returns>
  public static Bitmap GetImageFromByteArray(byte[] byteArray)
  {
     Bitmap bm = (Bitmap)_imageConverter.ConvertFrom(byteArray);

     if (bm != null && (bm.HorizontalResolution != (int)bm.HorizontalResolution ||
                        bm.VerticalResolution != (int)bm.VerticalResolution))
     {
        // Correct a strange glitch that has been observed in the test program when converting 
        //  from a PNG file image created by CopyImageToByteArray() - the dpi value "drifts" 
        //  slightly away from the nominal integer value
        bm.SetResolution((int)(bm.HorizontalResolution + 0.5f), 
                         (int)(bm.VerticalResolution + 0.5f));
     }

     return bm;
  }

Bearbeiten: Um das Bild aus einer JPG- oder PNG-Datei zu erhalten, sollten Sie die Datei mit File.ReadAllBytes () in ein Byte-Array einlesen:

 Bitmap newBitmap = GetImageFromByteArray(File.ReadAllBytes(fileName));

Dadurch werden Probleme im Zusammenhang mit Bitmap vermieden, bei denen der Quelldatenstrom geöffnet bleiben soll, und es werden einige Problemumgehungen für dieses Problem vorgeschlagen, die dazu führen, dass die Quelldatei gesperrt bleibt.


Während des Testens würde ich die resultierende Bitmap nehmen und sie wieder in ein Byte-Array umwandeln, indem ich: ImageConverter _imageConverter = new ImageConverter(); lock(SourceImage) { return (byte[])_imageConverter.ConvertTo(SourceImage, typeof(byte[])); } wo es zeitweise zu Arrays von 2 verschiedenen Größen führen würde. Dies würde normalerweise nach ungefähr 100 Iterationen passieren, aber wenn ich die Bitmap mit erhalte new Bitmap(SourceFileName);und sie dann durch diesen Code laufen lasse, funktioniert sie einwandfrei.
Don

@ Don: Hab eigentlich keine guten Ideen. Ist es konsistent, welche Bilder nicht zur gleichen Ausgabe wie die Eingabe führen? Haben Sie versucht, die Ausgabe zu untersuchen, wenn sie nicht den Erwartungen entspricht, um festzustellen, warum sie anders ist? Oder vielleicht spielt es keine Rolle, und man kann einfach akzeptieren, dass "Dinge passieren".
RenniePet

Es geschah konsequent. Ich habe die Ursache jedoch nie gefunden. Ich habe das Gefühl, dass dies möglicherweise mit einer 4-KByte-Grenze bei der Speicherzuweisung zu tun hat. Das könnte aber leicht falsch sein. Ich habe auf die Verwendung eines MemoryStream mit einem BinaryFormatter umgestellt und konnte sehr konsistent werden, da ich mit über 250 verschiedenen Testbildern unterschiedlicher Formate und Größen getestet habe, die zur Überprüfung über 1000-mal wiederholt wurden. Danke für Ihre Antwort.
Don

17

Versuche dies:

public byte[] imageToByteArray(System.Drawing.Image imageIn)
{
    MemoryStream ms = new MemoryStream();
    imageIn.Save(ms,System.Drawing.Imaging.ImageFormat.Gif);
    return ms.ToArray();
}

public Image byteArrayToImage(byte[] byteArrayIn)
{
    MemoryStream ms = new MemoryStream(byteArrayIn);
    Image returnImage = Image.FromStream(ms);
    return returnImage;
}

imageToByteArray (System.Drawing.Image imageIn) imageIn ist ein Bildpfad oder irgendetwas anderes, wie wir ein Bild in diesem übergeben können
Shashank

Dies ist das, was ich immer dann mache, wenn ich ein Bild in ein Byte-Array oder zurück konvertieren muss.
Alex Essilfie

Sie haben vergessen, den Memorystream zu schließen ... Übrigens wird dies direkt kopiert von: link
Qwerty01

1
@ Qwerty01 Calling Dispose bereinigt den von MemoryStreamschneller verwendeten Speicher zumindest in der aktuellen Implementierung nicht schneller. Wenn Sie es schließen, können Sie es anschließend nicht mehr verwenden. Es Imagewird ein GDI-Fehler angezeigt.
Saeb Amini

14

Mit der File.ReadAllBytes()Methode können Sie jede Datei in ein Byte-Array einlesen. Verwenden Sie einfach die File.WriteAllBytes()Methode, um ein Byte-Array in eine Datei zu schreiben .

Hoffe das hilft.

Weitere Informationen und Beispielcode finden Sie hier .


Nur eine Randnotiz: Dies könnte zusätzliche Metadaten enthalten, die Sie nicht haben möchten ;-)
Markus Safar

1
Vielleicht. Ich habe diese Antwort vor 10 Jahren geschrieben, ich war damals frischer / noob.
Shekhar

5

Möchten Sie nur die Pixel oder das gesamte Bild (einschließlich der Überschriften) als Byte-Array?

Für Pixel: Verwenden Sie die CopyPixelsMethode in Bitmap. Etwas wie:

var bitmap = new BitmapImage(uri);

//Pixel array
byte[] pixels = new byte[width * height * 4]; //account for stride if necessary and whether the image is 32 bit, 16 bit etc.

bitmap.CopyPixels(..size, pixels, fullStride, 0); 

3

Code:

using System.IO;

byte[] img = File.ReadAllBytes(openFileDialog1.FileName);

1
Funktioniert nur, wenn er eine Datei liest (und selbst dann erhält er die formatierten / komprimierten Bytes, nicht die rohen, es sei denn, es ist ein BMP)
BradleyDotNET

3

Wenn Sie nicht auf die imageBytes verweisen, um Bytes im Stream zu übertragen, gibt die Methode nichts zurück. Stellen Sie sicher, dass Sie auf imageBytes = m.ToArray () verweisen.

    public static byte[] SerializeImage() {
        MemoryStream m;
        string PicPath = pathToImage";

        byte[] imageBytes;
        using (Image image = Image.FromFile(PicPath)) {

            using ( m = new MemoryStream()) {

                image.Save(m, image.RawFormat);
                imageBytes = new byte[m.Length];
               //Very Important    
               imageBytes = m.ToArray();

            }//end using
        }//end using

        return imageBytes;
    }//SerializeImage

[NB] Wenn Sie das Bild im Browser immer noch nicht sehen, habe ich einen detaillierten Schritt zur Fehlerbehebung geschrieben

gelöst! -iis-nicht-dienen-CSS, -Bilder-und-Javascript


1

Dies ist ein Code zum Konvertieren des Bilds eines beliebigen Typs (z. B. PNG, JPG, JPEG) in ein Byte-Array

   public static byte[] imageConversion(string imageName){            


        //Initialize a file stream to read the image file
        FileStream fs = new FileStream(imageName, FileMode.Open, FileAccess.Read);

        //Initialize a byte array with size of stream
        byte[] imgByteArr = new byte[fs.Length];

        //Read data from the file stream and put into the byte array
        fs.Read(imgByteArr, 0, Convert.ToInt32(fs.Length));

        //Close a file stream
        fs.Close();

        return imageByteArr
    }

Nur eine Randnotiz: Dies könnte zusätzliche Metadaten enthalten, die Sie nicht haben möchten ;-)
Markus Safar

0

Um das Bild in ein Byte-Array zu konvertieren. Der Code ist unten angegeben.

public byte[] ImageToByteArray(System.Drawing.Image images)
{
   using (var _memorystream = new MemoryStream())
   {
      images.Save(_memorystream ,images.RawFormat);
      return  _memorystream .ToArray();
   }
}

Um das Byte-Array A Generic error occurred in GDI+in Image zu konvertieren. Der Code ist unten angegeben. Der Code wird in Image Save behandelt.

public void SaveImage(string base64String, string filepath)
{
    // image convert to base64string is base64String 
    //File path is which path to save the image.
    var bytess = Convert.FromBase64String(base64String);
    using (var imageFile = new FileStream(filepath, FileMode.Create))
    {
        imageFile.Write(bytess, 0, bytess.Length);
        imageFile.Flush();
    }
}

-2

Dieser Code ruft die ersten 100 Zeilen aus der Tabelle in SQLSERVER 2012 ab und speichert ein Bild pro Zeile als Datei auf der lokalen Festplatte

 public void SavePicture()
    {
        SqlConnection con = new SqlConnection("Data Source=localhost;Integrated security=true;database=databasename");
        SqlDataAdapter da = new SqlDataAdapter("select top 100 [Name] ,[Picture] From tablename", con);
        SqlCommandBuilder MyCB = new SqlCommandBuilder(da);
        DataSet ds = new DataSet("tablename");
        byte[] MyData = new byte[0];
        da.Fill(ds, "tablename");
        DataTable table = ds.Tables["tablename"];
           for (int i = 0; i < table.Rows.Count;i++ )               
               {
                DataRow myRow;
                myRow = ds.Tables["tablename"].Rows[i];
                MyData = (byte[])myRow["Picture"];
                int ArraySize = new int();
                ArraySize = MyData.GetUpperBound(0);
                FileStream fs = new FileStream(@"C:\NewFolder\" + myRow["Name"].ToString() + ".jpg", FileMode.OpenOrCreate, FileAccess.Write);
                fs.Write(MyData, 0, ArraySize);
                fs.Close();
               }

    }

Bitte beachten Sie: Das Verzeichnis mit dem Namen NewFolder sollte in C: \ vorhanden sein


3
Sie haben die falsche Frage beantwortet ... Nun, ich hoffe ^ _ ^
JiBéDoublevé
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.