locked
Fastest method to convert bitmap object to byte array RRS feed

  • Question

  • Hello,

    We have a high volume transaction based webservice. There is a need to convert the inmemory bitmap object into byte array. Can anyone please suggest best way to do it. Couple of ways that I can think of are:

    1. Using the TypeDescriptor

    byte[] bytes = (byte[])TypeDescriptor.GetConverter(bmp).ConvertTo(bmp, typeof(byte[]));

    2. Using the Memory Stream 

    MemoryStream ms = new MemoryStream();
    // Save to memory using the Jpeg format
    bmp.Save (ms, ImageFormat.Jpeg);
    // read to end
    byte[] bmpBytes = ms.GetBuffer();
    bmp.Dispose();
    ms.Close();
    

    Please suggest the best way from above or any new one as per performance.

    Thanks.

    Aman.

    Thursday, July 8, 2010 7:55 AM

All replies

  • Hi,

    Thanks for your post.

    In my experience, Bitmap.LockBits Method (http://msdn.microsoft.com/en-us/library/5ey6h79d.aspx) is the key concept in this condition. For example:

      private byte[] GetRGBValues(Bitmap bmp)
      {
    
       // Lock the bitmap's bits. 
       Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height);
       System.Drawing.Imaging.BitmapData bmpData =
        bmp.LockBits(rect, System.Drawing.Imaging.ImageLockMode.ReadOnly,
        bmp.PixelFormat);
    
       // Get the address of the first line.
       IntPtr ptr = bmpData.Scan0;
    
       // Declare an array to hold the bytes of the bitmap.
       int bytes = bmpData.Stride * bmp.Height;
       byte[] rgbValues = new byte[bytes];
    
       // Copy the RGB values into the array.
       System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);bmp.UnlockBits(bmpData);
    
       return rgbValues;
      }

    Hope this helps.

    Sincerely,

    Yasser


    LEARN HOW WPF IS FLEXIBLE IN PRESENTATION DURING A QUICK SIMPLE WALKTHROUGH:
    Walkthrough: Displaying multi column ComboBox by using Windows Presentation Foundation (WPF) data templating
    Thursday, July 8, 2010 8:21 AM
  • But what about the methods that I mentioned earlier. Which will give the best performance. I believe locking the bitmap in memory just to convert it to byte array when I dont want to manipulate any of its data will be time consuming. Is this correct. Please comment.
    Thursday, July 8, 2010 9:29 AM
  • Actually, you should compare their performance using Stopwatch component (http://msdn.microsoft.com/en-us/library/system.diagnostics.stopwatch.aspx) instead of guessing.

    I'm going to investigate if it's possible to avoid copying data (i.e. System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes);) and return current original data which will improve performance.

    Regards,

    Yasser


    LEARN HOW WPF IS FLEXIBLE IN PRESENTATION DURING A QUICK SIMPLE WALKTHROUGH:
    Walkthrough: Displaying multi column ComboBox by using Windows Presentation Foundation (WPF) data templating
    Thursday, July 8, 2010 10:02 AM
  • If you have an uncompressed bitmap in memory and you want a JPEG compressed byte[], you'll have to save the bitmap to a stream.  That'll take all of the time.
    Thursday, July 8, 2010 5:58 PM
  • Hello,

    We have a high volume transaction based webservice. There is a need to convert the inmemory bitmap object into byte array. Can anyone please suggest best way to do it. Couple of ways that I can think of are:

    1. Using the TypeDescriptor

    byte[] bytes = (byte[])TypeDescriptor.GetConverter(bmp).ConvertTo(bmp, typeof(byte[]));
    
    

    2. Using the Memory Stream 

    MemoryStream ms = new MemoryStream();
    
    // Save to memory using the Jpeg format
    
    bmp.Save (ms, ImageFormat.Jpeg);
    
    // read to end
    
    byte[] bmpBytes = ms.GetBuffer();
    
    bmp.Dispose();
    
    ms.Close();
    
    
    
    

    Please suggest the best way from above or any new one as per performance.

    Thanks.

    Aman.


    What class/type is the variable "bmp" ? without knowing this it's hard to say much.

    Cap'n

     

    • Proposed as answer by Ilikems Thursday, January 4, 2018 6:05 AM
    Thursday, July 8, 2010 6:55 PM
  • But what about the methods that I mentioned earlier. Which will give the best performance. I believe locking the bitmap in memory just to convert it to byte array when I dont want to manipulate any of its data will be time consuming. Is this correct. Please comment.

    Method 1 will do some tests, then will use the same kind of code as method 2, using the original type of the bitmap.

    If the original type is jpg, I'd go with Method 2. If it isn't, you're comparing apples and oranges.

    Friday, July 9, 2010 12:49 AM
  • I have the image in the gif format.
    Friday, July 9, 2010 12:18 PM
  • "I have the image in the gif format."

    How does anything you have posted before relate to what you have now?  If you have an image in a gif format, it has to be in a file or a stream.  Either way you have a byte[].  What's your question now?

    Friday, July 9, 2010 1:39 PM
  • That is very true that I have the Gif image. This Gif has been created using the Bitmap class object. The question that I had earlier and now is that whats the fastest way to get the bytes from this bitmap object.

    Thanks for your anticipation in advance.

    Aman.

    Wednesday, July 14, 2010 3:56 PM
  • That is very true that I have the Gif image. This Gif has been created using the Bitmap class object. The question that I had earlier and now is that whats the fastest way to get the bytes from this bitmap object.


    A gif only exists as an arry of bytes.  If your gif is in a file, use File.ReadAllBytes to get the bytes in a memory array.  If it's in a stream, use ToArray to change the representation of the stream to an array. 

    What do you mean "fastest way to get the bytes from this bitmap object."?  Have you saved the bitmap to a gif or do you still have a bitmap?  If you still have the bitmap and want a gif in a byte array, save the bitmap to a stream using the gif encoder and use the stream or its array representation.

    Wednesday, July 14, 2010 5:23 PM
  • i like it!!

    it is fastest way ,,

    first i use

    using(ms)

    {

    ms.ToArray(); 

    }

    now

    ms.GetBuffer() <-- i can save 50ms 

    thank you

    • Edited by Ilikems Thursday, January 4, 2018 6:07 AM
    Thursday, January 4, 2018 6:04 AM
  • i like it!!

    it is fastest way ,,

    first i use

    using(ms)

    {

    ms.ToArray(); 

    }

    now

    ms.GetBuffer() <-- i can save 50ms 

    thank you


    But note that according to documentation GetBuffer returns an array which might contain more bytes that is required for image. (Some of the bytes are unused). You should also check ms.Length or ms.Position to get the correct number of bytes.



    • Edited by Viorel_MVP Thursday, January 4, 2018 6:29 AM
    Thursday, January 4, 2018 6:26 AM