Click here to Skip to main content
15,888,190 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.

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
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.
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
 

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