184

Can anybody suggest how I can convert an image to a byte array and vice versa?

I'm developing a WPF application and using a stream reader.

ASh
  • 34,632
  • 9
  • 60
  • 82
Shashank
  • 6,117
  • 20
  • 51
  • 72

12 Answers12

243

Sample code to change an image into a 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 and Byte Array to Image Converter Class

Pranay Rana
  • 175,020
  • 35
  • 237
  • 263
  • 13
    instead of `System.Drawing.Imaging.ImageFormat.Gif`, you can use `imageIn.RawFormat` – S.Serpooshan Nov 26 '16 at 12:31
  • 1
    This does not seem to be repeatable, or at least after a couple times of converting, strange GDI+ errors start to occur. The `ImageConverter` solution found below seems to avoid these errors. – Dave Cousineau Apr 21 '17 at 22:43
  • Might be better to use png, nowaday. – Nyerguds Mar 18 '18 at 20:11
  • On a side note: This might contain additional meta data you don't want to have ;-) To get rid of the metadata you might want to create a _new Bitmap_ and pass the _Image_ to it like `(new Bitmap(imageIn)).Save(ms, imageIn.RawFormat);`. – Markus Safar Apr 06 '20 at 22:07
  • Note that the using is unecessary for the MemoryStream .You can return and use the MemoryStream in the same way as the array. – Hoddmimes Nov 05 '20 at 13:43
73

For Converting an Image object to byte[] you can do as follows:

public static byte[] converterDemo(Image x)
{
    ImageConverter _imageConverter = new ImageConverter();
    byte[] xByte = (byte[])_imageConverter.ConvertTo(x, typeof(byte[]));
    return xByte;
}
AR5HAM
  • 1,220
  • 11
  • 19
  • 4
    Perfect Answer!.... no need to define the "image file extension", exactly what i was looking for. – Bravo Sep 03 '13 at 06:12
  • 2
    On a side note: This might contain additional meta data you don't want to have ;-) To get rid of the metadata you might want to create a _new Bitmap_ and pass the _Image_ to it like `.ConvertTo(new Bitmap(x), typeof(byte[]));`. – Markus Safar Apr 06 '20 at 22:03
  • 1
    For me Visual Studio is not recognizing the type ImageConverter. Is there an import statement that is needed to use this? – SendETHToThisAddress Jun 01 '20 at 07:34
  • @technoman23 The `ImageConverter` is part of `System.Drawing` namespace. – AR5HAM Sep 24 '20 at 19:49
  • 3
    So, um, what does that actually convert the image to? What's inside those bytes? – Nyerguds Oct 26 '20 at 22:21
  • The byte array is a binary representation of the image. Look up (de)serialization. Not sure what are you confused about. – AR5HAM Feb 14 '21 at 06:04
  • Nyerguds, the format of the binary output for this function depends on the format of the input. In this case if you're unsure then write the bytes to file and inspect the format. The ImageConverter is a bit confusing and ambiguous because the input data is of type 'object'. – DAG Nov 15 '21 at 15:43
  • I bet this won't work with a multipage TIFF file – radrow Apr 01 '22 at 09:11
  • @radrow this does work on multipage TIFF file as well. That being said, there are other OSS libs you can use that are specifically written for TIFFs. – AR5HAM Dec 30 '22 at 20:00
44

Another way to get Byte array from image path is

byte[] imgdata = System.IO.File.ReadAllBytes(HttpContext.Current.Server.MapPath(path));
Neelam
  • 1,028
  • 12
  • 25
  • 5
    Their question is tagged WPF (so no reason to think it's running in a server and include a MapPath) AND shows they already have the image (no reason to read it from disk, not even assume it's on disk to begin with). I'm sorry but your reply seems completely irrelevant to the question – Ronan Thibaudau Jan 05 '20 at 18:42
27

Here's what I'm currently using. Some of the other techniques I've tried have been non-optimal because they changed the bit depth of the pixels (24-bit vs. 32-bit) or ignored the image's resolution (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 to 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 to 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: To get the Image from a jpg or png file you should read the file into a byte array using File.ReadAllBytes():

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

This avoids problems related to Bitmap wanting its source stream to be kept open, and some suggested workarounds to that problem that result in the source file being kept locked.

RenniePet
  • 11,420
  • 7
  • 80
  • 106
  • During testing of this I would take the resulting bitmap and turn it back into a byte array using: `ImageConverter _imageConverter = new ImageConverter(); lock(SourceImage) { return (byte[])_imageConverter.ConvertTo(SourceImage, typeof(byte[])); }` Where it would intermittently result in arrays of 2 different sizes. This would normally happen after about 100 iterations, But when I obtain the bitmap using `new Bitmap(SourceFileName);` and then run it through that code it works fine. – Moon Jan 25 '16 at 01:10
  • @Don: Don't really have any good ideas. Is it consistent which images don't result in the same output as input? Have you tried to examine the output when it is not as expected to see why it is different? Or maybe it doesn't really matter, and one can just accept that "things happen". – RenniePet Jan 25 '16 at 12:30
  • 1
    It was consistently happening. Never found the cause though. I have a feeling it might have had something to do with a 4K byte boundary in memory allocation. But that could easily be wrong. I switched to using a MemoryStream with a BinaryFormatter and I was able to become very consistent as tested with over 250 different test images of varying formats and sizes, looped over 1000 times for verification. Thank you for the reply. – Moon Jan 25 '16 at 13:59
20

try this:

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;
}
Alexander
  • 2,320
  • 2
  • 25
  • 33
anishMarokey
  • 11,279
  • 2
  • 34
  • 47
  • imageToByteArray(System.Drawing.Image imageIn) imageIn is image path or anything else how we can pass image in this – Shashank Sep 27 '10 at 06:02
  • This is what I do anytime I need to convert an image to a byte array or back. – Alex Essilfie Sep 27 '10 at 07:59
  • You forgot to close the memorystream...btw this is copied straight from: [link](http://www.codeproject.com/KB/recipes/ImageConverter.aspx) – Qwerty01 Feb 01 '12 at 02:58
  • 1
    @Qwerty01 Calling Dispose won't clean up the memory used by `MemoryStream` any faster, at least in the current implementation. In fact, if you close it, you won't be able to use the `Image` afterwards, you'll get a GDI error. – Saeb Amini Nov 06 '15 at 21:43
15

You can use File.ReadAllBytes() method to read any file into byte array. To write byte array into file, just use File.WriteAllBytes() method.

Hope this helps.

You can find more information and sample code here.

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Shekhar
  • 11,438
  • 36
  • 130
  • 186
8

If you don't reference the imageBytes to carry bytes in the stream, the method won't return anything. Make sure you reference 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
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
6

Do you only want the pixels or the whole image (including headers) as an byte array?

For pixels: Use the CopyPixels method on Bitmap. Something like:

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); 
Lasse Espeholt
  • 17,622
  • 5
  • 63
  • 99
3

Code:

using System.IO;

byte[] img = File.ReadAllBytes(openFileDialog1.FileName);
Irvin Dominin
  • 30,819
  • 9
  • 77
  • 111
Md Shahriar
  • 2,072
  • 22
  • 11
  • 1
    Only works if he is reading a file (and even then he gets the formatted/compressed bytes, not the raw ones unless its a BMP) – BradleyDotNET Jan 08 '17 at 21:24
1

This is Code for converting the image of any type(for example PNG, JPG, JPEG) to 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
    }
1

To be convert the image to byte array.The code is give below.

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

To be convert the Byte array to Image.The code is given below.The code is handle A Generic error occurred in GDI+ in 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();
    }
}
Ciarán Bruen
  • 5,221
  • 13
  • 59
  • 69
Bibin
  • 492
  • 5
  • 11
-4

This code retrieves first 100 rows from table in SQLSERVER 2012 and saves a picture per row as a file on local disk

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

    }

please note: Directory with NewFolder name should exist in C:\

Rodrigo Caballero
  • 1,090
  • 1
  • 15
  • 27
Reza
  • 283
  • 3
  • 11