0

好的,我已经创建了两个程序。一个使用GetPixels,另一个使用LockBits。我的 GetPixels 程序如下...

所指的条纹图片为 200x200 jpg简称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();

现在这个读取大约 20 秒来处理这个图像并输出所有像素。太好了,但是理论上我的 LockBits 应该更快。我的 LockBits 代码是...

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();

时间是37秒。现在我不明白为什么我的 Lockbits 时间比 GetPixels 长。

此外,我的输出文件的列出位置也不匹配。就好像它们出了问题一样。

这是一个需要解决的大问题,所以提前感谢大家阅读并尝试解决我的问题。

4

1 回答 1

1

你有一些我可以看到的问题。最大的问题是您的图像宽度为 200,但在内存中,它的步幅为 600(对我来说 - 对您来说可能类似)。这意味着您要写出更多数据,因为您不会忽略每行 400 个填充像素。

其他问题:

  1. 您只计时字符串连接。当您启动计时器时,lockbits 的东西已经完成了。
  2. 使用 StringBuilder,您的字符串连接会更快。
  3. 当您只需要读取时,您正在锁定位图以进行读/写访问。这张图片对我来说对性能没有明显影响,但还是不妨将其更改为 ReadOnly。
  4. 您的大多数评论充其量是不必要的(// creates array)-有些具有误导性(//Scans the first line of data-不,它返回一个指向已加载数据的指针)。

以下代码在我的机器上只需几毫秒即可完成。

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);
于 2014-05-05T04:20:48.383 回答