Reputation: 111
I have a USB videocamera that spits out 640x480 image data frames that I'd like to put in a winforms pictureBox. When I map the data onto the pictureBox using SetPixel the image looks fine, but SetPixel is crushingly slow, so I tried this instead:
void CreateBitmap()
{
int width = bitmap.Width;
int height = bitmap.Height;
int n = 0;
// copy normalized data into 1D array
lock (imageDataLocker)
{
for (int i = 0; i < width; ++i)
{
for (int j = 0; j < height; ++j)
{
Color c = Colorizer.GetColor(imageData[i, j]);
rgbValues[n] = c.R;
rgbValues[n + 1] = c.G;
rgbValues[n + 2] = c.B;
n += 3;
}
}
}
// Copy image data into the bitmap
Rectangle rect = new Rectangle(0, 0, width, height);
BitmapData bitmapData = bitmap.LockBits(rect, ImageLockMode.WriteOnly, bitmap.PixelFormat);
IntPtr ptr = bitmapData.Scan0;
int bytes = rgbValues.Length;
System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
bitmap.UnlockBits(bitmapData);
}
Where rgbValues is a 1D byte array containing 3 bytes per pixel, imageData is a 2D int array supplied by the camera, and bitmap has a 24bppRgb format. I don't get any errors with this, but when I assign the bitmap to the BackgroundImage of my pictureBox there is a strange banding effect:
What am I missing here?
Upvotes: 0
Views: 563
Reputation: 323
First of all, I think your outer loop should be j=0; j
I tested this with this simple pattern which makes a bitmap with the left half blue and the right half black.
Bitmap bm = new Bitmap(16, 16, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
BitmapData bitmapData = bm.LockBits(new Rectangle(0,0,16,16), ImageLockMode.WriteOnly, bm.PixelFormat);
IntPtr ptr = bitmapData.Scan0;
byte[] rgbValues = new byte[16 * 16 * 3];
int b = 0;
for (int y = 0; y < bm.Height; y++)
{
for (int x = 0; x < bm.Width; x++)
{
if (x < 7)
{
rgbValues[b++] = 255; // BLUE, not red!
rgbValues[b++] = 0; // g
rgbValues[b++] = 0; // r
}
else
{
rgbValues[b++] = 0; // r
rgbValues[b++] = 0; // g
rgbValues[b++] = 0; // b
}
}
}
int bytes = rgbValues.Length;
System.Runtime.InteropServices.Marshal.Copy(rgbValues, 0, ptr, bytes);
bm.UnlockBits(bitmapData);
pictureBox1.Image = bm;
}
Also, note that the first byte you write should be the BLUE component, then green, then red.
Upvotes: 1