Comment convertir une image en tableau d'octets


127

Quelqu'un peut-il suggérer comment je peux convertir une image en un tableau d'octets et vice versa?

Je développe une application WPF et j'utilise un lecteur de flux.

Réponses:


176

Exemple de code pour transformer une image en tableau d'octets

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

Classe C # Image to Byte Array et Byte Array to Image Converter


12
au lieu de System.Drawing.Imaging.ImageFormat.Gif, vous pouvez utiliserimageIn.RawFormat
S.Serpooshan

1
Cela ne semble pas être répétable, ou du moins après quelques conversions, d'étranges erreurs GDI + commencent à se produire. La ImageConvertersolution trouvée ci-dessous semble éviter ces erreurs.
Dave Cousineau

Il vaudrait peut-être mieux utiliser png, de nos jours.
Nyerguds

Sur une note latérale: cela peut contenir des métadonnées supplémentaires que vous ne voulez pas avoir ;-) Pour vous débarrasser des métadonnées, vous voudrez peut-être créer un nouveau Bitmap et lui transmettre l' image comme (new Bitmap(imageIn)).Save(ms, imageIn.RawFormat);.
Markus Safar le

56

Pour convertir un objet Image en, byte[]vous pouvez procéder comme suit:

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

4
Réponse parfaite! .... pas besoin de définir "l'extension de fichier image", exactement ce que je cherchais.
Bravo le

1
Sur une note latérale: cela peut contenir des métadonnées supplémentaires que vous ne voulez pas avoir ;-) Pour vous débarrasser des métadonnées, vous voudrez peut-être créer un nouveau Bitmap et lui transmettre l' image comme .ConvertTo(new Bitmap(x), typeof(byte[]));.
Markus Safar le

1
Pour moi, Visual Studio ne reconnaît pas le type ImageConverter. Une instruction d'importation est-elle nécessaire pour l'utiliser?
technoman23

32

Une autre façon d'obtenir un tableau d'octets à partir du chemin de l'image est

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

Leur question est étiquetée WPF (donc aucune raison de penser qu'elle s'exécute sur un serveur et inclut un MapPath) ET montre qu'ils ont déjà l'image (aucune raison de la lire à partir du disque, pas même de supposer qu'elle est sur le disque pour commencer). Je suis désolé mais votre réponse semble totalement hors de propos à la question
Ronan Thibaudau

19

Voici ce que j'utilise actuellement. Certaines des autres techniques que j'ai essayées n'ont pas été optimales car elles ont changé la profondeur de bits des pixels (24 bits contre 32 bits) ou ont ignoré la résolution de l'image (dpi).

  // 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();

Image en tableau d'octets:

  /// <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();
     }
  }

Tableau d'octets en image:

  /// <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;
  }

Edit: Pour obtenir l'image à partir d'un fichier jpg ou png, vous devez lire le fichier dans un tableau d'octets en utilisant File.ReadAllBytes ():

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

Cela évite les problèmes liés au fait que Bitmap souhaite que son flux source reste ouvert, et certaines solutions de contournement suggérées à ce problème entraînant le maintien du fichier source verrouillé.


Pendant le test de cela, je prendrais le bitmap résultant et le transformerais en un tableau d'octets en utilisant: ImageConverter _imageConverter = new ImageConverter(); lock(SourceImage) { return (byte[])_imageConverter.ConvertTo(SourceImage, typeof(byte[])); } Où cela donnerait par intermittence des tableaux de 2 tailles différentes. Cela se produirait normalement après environ 100 itérations, mais lorsque j'obtiens le bitmap en utilisant new Bitmap(SourceFileName);puis l'exécute à travers ce code, cela fonctionne bien.
Don

@Don: Je n'ai pas vraiment de bonnes idées. Est-ce cohérent quelles images ne donnent pas la même sortie que l'entrée? Avez-vous essayé d'examiner la sortie quand elle n'est pas comme prévu pour voir pourquoi elle est différente? Ou peut-être que cela n'a pas vraiment d'importance, et on peut simplement accepter que "les choses arrivent".
RenniePet

Cela se passait constamment. Jamais trouvé la cause cependant. J'ai le sentiment que cela pourrait avoir quelque chose à voir avec une limite de 4K octets dans l'allocation de mémoire. Mais cela pourrait facilement être faux. Je suis passé à l'utilisation d'un MemoryStream avec un BinaryFormatter et j'ai pu devenir très cohérent comme testé avec plus de 250 images de test différentes de différents formats et tailles, bouclées plus de 1000 fois pour vérification. Merci pour la réponse.
Don

17

essaye ça:

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 est le chemin de l'image ou quoi que ce soit d'autre comment nous pouvons transmettre l'image dans ce
Shashank

C'est ce que je fais chaque fois que j'ai besoin de convertir une image en tableau d'octets ou inversement.
Alex Essilfie

Vous avez oublié de fermer le flux de mémoire ... btw ceci est copié directement à partir de: lien
Qwerty01

1
@ Qwerty01 L'appel de Dispose ne nettoiera pas la mémoire utilisée MemoryStreamplus rapidement, du moins dans l'implémentation actuelle. En fait, si vous le fermez, vous ne pourrez plus l'utiliser par la Imagesuite, vous obtiendrez une erreur GDI.
Saeb Amini

14

Vous pouvez utiliser la File.ReadAllBytes()méthode pour lire n'importe quel fichier dans un tableau d'octets. Pour écrire un tableau d'octets dans un fichier, utilisez simplement la File.WriteAllBytes()méthode.

J'espère que cela t'aides.

Vous pouvez trouver plus d'informations et un exemple de code ici .


Juste une remarque: cela peut contenir des métadonnées supplémentaires que vous ne voulez pas avoir ;-)
Markus Safar

1
Peut être. J'ai écrit cette réponse il y a 10 ans, j'étais plus fraîche / noob à l'époque.
Shekhar

5

Voulez-vous uniquement les pixels ou l'image entière (y compris les en-têtes) sous forme de tableau d'octets?

Pour les pixels: utilisez la CopyPixelsméthode sur Bitmap. Quelque chose comme:

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
Ne fonctionne que s'il lit un fichier (et même dans ce cas, il obtient les octets formatés / compressés, pas les octets bruts sauf si c'est un BMP)
BradleyDotNET

3

Si vous ne référencez pas les imageBytes pour transporter des octets dans le flux, la méthode ne retournera rien. Assurez-vous de référencer imageBytes = m.ToArray ();

    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] Si vous ne voyez toujours pas l'image dans le navigateur, j'ai écrit une étape de dépannage détaillée

résolu! -iis-ne-servant-css, -images-et-javascript


1

Ceci est le code pour convertir l'image de tout type (par exemple PNG, JPG, JPEG) en tableau d'octets

   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
    }

Juste une remarque: cela peut contenir des métadonnées supplémentaires que vous ne voulez pas avoir ;-)
Markus Safar

0

Pour convertir l'image en tableau d'octets, le code est donné ci-dessous.

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

Pour être convertir le tableau d'octets en image.Le code est donné ci-dessous.Le code est géré A Generic error occurred in GDI+dans Image Save.

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

Ce code récupère les 100 premières lignes de la table dans SQLSERVER 2012 et enregistre une image par ligne en tant que fichier sur le disque local

 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();
               }

    }

Veuillez noter: le répertoire avec le nom NewFolder doit exister dans C: \


3
Vous avez répondu à la mauvaise question ... Eh bien, j'espère ^ _ ^
JiBéDoublevé
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.