Click here to Skip to main content
15,898,134 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi all,
I am now optimizing a render engine. I have run into difficulty converting my stored byte array into a Bitmap quickly.

I have a conventional way that is slow but works. It merely goes through all the pixels and uses the Bitmap.SetPixel function
GetAsBitmapSlow
C#
public Bitmap GetAsBitmapSlow()
{
Bitmap ReturnImage = new Bitmap(Width, Height, PixelFormat.Format32bppPArgb);
for(int Y = 0; Y < Height; Y++)
    for (int X = 0; X < Width; X++)
    {
        Color PixelColour = GetPixel(X, Y);
        ReturnImage.SetPixel(X, Y, PixelColour);
    }
    return ReturnImage;
}


GetPixel
C#
public Color GetPixel(int X, int Y)
{
   if (X >= 0 && Y >= 0 && X < Width && Y < Height)
   {
       int PixelLocation = (X + (Width * Y)) * 4;
       return Color.FromArgb(ARGBcollection[PixelLocation], ARGBcollection[PixelLocation + 1], ARGBcollection[PixelLocation + 2], ARGBcollection[PixelLocation + 3]);
    }
    return Color.FromArgb(0, 0, 0, 0);
}
This function works as proven by the function that calls it.



I am now opting for a quicker method. This just doesn't work at all.
GetAsBitmap
C#
public Bitmap GetAsBitmap()
{
    Bitmap ReturnImage = new Bitmap(Width, Height, PixelFormat.Format32bppPArgb);
    BitmapData bmpData = ReturnImage.LockBits(new Rectangle(0, 0, Width, Height), ImageLockMode.ReadWrite, PixelFormat.Format32bppPArgb);
    Marshal.Copy(ARGBcollection, 0, bmpData.Scan0, ARGBcollection.Length);
    ReturnImage.UnlockBits(bmpData);
    return ReturnImage;
}

My speculation is that the Marshal.Copy is something to do with the error. But after a lot of grief I come to you guys :p

Thank you all :) I hope you can shed some light
Posted
Comments
BobJanova 5-Aug-11 11:50am    
Define 'doesn't work at all'. I suspect that the format you are using is 32 bit integers the wrong way around (i.e. B, G, R, A in the byte stream), so you would get a miscoloured image and transparency based on the blue channel. Is that what you see?
Thomas.D Williams 5-Aug-11 17:44pm    
The problem was that the image would just show as black the same as the picture box.

The problem came down to a small little problem. Its still not perfect but it now works. When I changed:
C#
int PixelLocation = (X + (Width * Y)) * 4;

to
C#
int PixelLocation = (X + (Stride * Y)) * 4;

the application would work as expected. The 2 previous answers led me to look more carefully at the values stored across the byte[] array only to notice it was writting the R in A values

Thank you for your help :)

P.S my new solution locks bits then unlocks them once all processing is complete
 
Share this answer
 
I think Shameel has the right idea. You may have to implement a typeconverter that supports the required conversion.

Otherwise you can always try System.Windows.Media.Imaging.WriteableBitmap.WritePixels Method (Int32Rect, Array, Int32, Int32)

or

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


Best regards
Espen Harlinn
 
Share this answer
 
Comments
Thomas.D Williams 5-Aug-11 11:50am    
I tried this in a solution a while back, that had the same exception. 'Parameter is not valid'
Espen Harlinn 5-Aug-11 12:20pm    
Image.FromStream(ms) only works if the byte array contains the image representation in a valid image format (bmp, png, jpeg etc).

WriteableBitmap.WritePixels on the other hand expects the array to be formatted according to on of the PixelFormat properties of the System.Windows.Media.PixelFormats class - as specified in the constructor of the WriteableBitmap.
C#
TypeConverter tc = TypeDescriptor.GetConverter(typeof(Bitmap));
Bitmap bitmap1 = (Bitmap)tc.ConvertFrom(byteArray);
 
Share this answer
 
Comments
Thomas.D Williams 5-Aug-11 11:17am    
Thanks for the quick reply, however this doesn't work. It just throws an exception on the second line 'Parameter is not valid'
[no name] 5-Aug-11 11:24am    
can you show your code? The parameter on the second line is supposed to be a byte[].
Thomas.D Williams 5-Aug-11 11:49am    
TypeConverter tc = TypeDescriptor.GetConverter(typeof(Bitmap));
Bitmap bitmap1 = (Bitmap)tc.ConvertFrom(ARGBcollection);

where ARGBcollection is the same byte[] that the slow function uses
Espen Harlinn 5-Aug-11 11:18am    
Very elegant - my 5

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900