0

さて、私は2つのプログラムを作成しました。を使用するGetPixelsものと使用するものLockBits。私のGetPixelsプログラムは次のとおりです...

参照されているストライプの写真は 200x200 jpg ですstrip.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秒です。GetPixels よりも Lockbits の方が時間がかかる理由がわかりません。

また、私の出力ファイルは、リストされている場所に関して一致しません。あたかもそれらが順不同であるかのようです。

これは取り組むべき大きな問題なので、私の問題を読んで解決しようとしてくれてありがとう。

4

1 に答える 1

1

私が見ることができるいくつかの問題があります。最大の問題は、画像の幅が 200 であることですが、メモリ内ではそのストライドは 600 です (私にとっては - おそらくあなたにとっても同様です)。これは、行ごとに 400 のパディング ピクセルを無視しないため、より多くのデータを書き出すことを意味します。

その他の問題:

  1. 文字列連結のみのタイミングを取っています。タイマーを開始するまでに、ロックビットの処理は完了しています。
  2. StringBuilder を使用すると、文字列の連結が高速になります。
  3. 読み取りのみが必要な場合に、読み取り/書き込みアクセス用にビットマップをロックしています。この画像では、パフォーマンスに目に見える影響はありませんが、それでも読み取り専用に変更することはできます。
  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 に答える