Question

Okay, I've created two programs. One that uses GetPixels and another that uses LockBits. My GetPixels program is as follows...

The stripe picture referred is a 200x200 jpgReferred to as stripe.jpg

Stopwatch GetTime = new Stopwatch();

Bitmap img = new Bitmap("stripe.jpg");
GetTime.Start();
for (int i = 0; i < img.Width; i++)
{
  for (int j = 0; j < img.Height; j++)
   {
     Color pixel = img.GetPixel(i, j);
     output += " " + pixel;
   }
}
GetTime.Stop();

Now this one reads out about 20 secs to process this image and output all the pixels. Great, but my LockBits one should, theoretically be faster. My code for the LockBits is...

Bitmap bmp = new Bitmap("stripe.jpg");


Rectangle bmpRec = new Rectangle(0, 0, bmp.Width, bmp.Height); //Creates Rectangle for holding picture

BitmapData bmpData = bmp.LockBits(bmpRec, ImageLockMode.ReadWrite, Pixels); //Gets the Bitmap data

IntPtr Pointer = bmpData.Scan0; //Scans the first line of data

int DataBytes = Math.Abs(bmpData.Stride) * bmp.Height; //Gets array size

byte[] rgbValues = new byte[DataBytes]; //Creates array

string Pix = " ";

Marshal.Copy(Pointer, rgbValues, 0, DataBytes); //Copies of out memory

bmp.UnlockBits(bmpData);



Stopwatch Timer = new Stopwatch();

pictureBox1.Image = bmp;

Timer.Start();
for (int p = 0; p < DataBytes; p++)
{
    Pix += " " + rgbValues[p];
}
Timer.Stop();

and the time on that is 37secs. Now I dont understand why my time is longer for the Lockbits than it is for the GetPixels.

Also my output files don't match up in terms of where they are listed. It is almost as if they are out of order.

This is a big problem to tackle so thank you all in advance for reading and trying to solve my problem.

Was it helpful?

Solution

You have a few problems that I can see. The biggest issue is that your image has a width of 200, but in memory, its stride is 600 (for me - probably similar for you). This means you are writing out a lot more data, because you don't ignore the 400 padding pixels per row.

Other issues:

  1. You're timing string concatenation only. By the time you start your timer, the lockbits stuff has finished.
  2. Your string concatenation would be faster using StringBuilder.
  3. You are locking the bitmap for read/write access, when you only need read. No discernible effect on performance for me, with this image, but still might as well change it to ReadOnly.
  4. Most of your comments are unnecessary at best (// creates array)- some are misleading (//Scans the first line of data - no, it returns a pointer to the data which has already been loaded).

The following code completes in only a few milliseconds on my machine.

Bitmap bmp = new Bitmap(@"d:\stripe.jpg");
//pictureBox1.Image = bmp;

Stopwatch Timer = new Stopwatch();

Rectangle bmpRec = new Rectangle(0, 0, bmp.Width, bmp.Height);
BitmapData bmpData = bmp.LockBits(
    bmpRec, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);
IntPtr Pointer = bmpData.Scan0;
int DataBytes = Math.Abs(bmpData.Stride) * bmp.Height;
byte[] rgbValues = new byte[DataBytes];
Marshal.Copy(Pointer, rgbValues, 0, DataBytes);
bmp.UnlockBits(bmpData);

StringBuilder pix = new StringBuilder(" ");
Timer.Start();
for (int i = 0; i < bmpData.Width; i++)
{
    for (int j = 0; j < bmpData.Height; j++)
    {
        // compute the proper offset into the array for these co-ords
        var pixel = rgbValues[i + j*Math.Abs(bmpData.Stride)];
        pix.Append(" ");
        pix.Append(pixel);
    }
}
Timer.Stop();

Console.WriteLine(Timer.Elapsed);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top