2009年1月3日土曜日

GetPixelが遅い

画像からRGBの各要素を取り出すことがあったのですが、異常に遅かったのでいろいろ比較してみました。

1280×800のBitmapからすべてのピクセルからRGBの各要素を取り出すまでの時間を比較してみました。
(CPU:Core2DuoT7200/Memory:4GB)

手法 時間
GetPixel 1.8356103
GetPixel2 1.5895904
LockBits 0.0062316
unsafe 0.0024599

※GetPixel2はWidthとHeightを一時変数に代入し、高速化を図ったもの

こうしてみると、WidthプロパティとHeigtプロパティにアクセスするだけで結構時間がかかることがよくわかります。あと、LockBitsとunsafeの時間の違いはMarshalCopyの処理時間なのかな?

(以下ソースコード)
GetPixel

  1. for (int i = 0; i < bitmap.Width; i++)  
  2. {  
  3.     for (int j = 0; j < bitmap.Height; j++)  
  4.     {  
  5.         var color = bitmap.GetPixel(i, j);  
  6.         int r = color.R;  
  7.         int g = color.G;  
  8.         int b = color.B;  
  9.     }  
  10. }  


GetPixel

  1. int width = bitmap.Width;  
  2. int height = bitmap.Height;  
  3. for (int i = 0; i < width; i++)  
  4. {  
  5.     for (int j = 0; j < height; j++)  
  6.     {  
  7.         var color = bitmap.GetPixel(i, j);  
  8.         int r = color.R;  
  9.         int g = color.G;  
  10.         int b = color.B;  
  11.     }  
  12. }  



LockBits

  1. BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),  
  2.                                         ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);  
  3. int width = bitmapData.Width;  
  4. int height = bitmapData.Height;  
  5.   
  6. byte[] bytes = new byte[bitmapData.Stride * bitmapData.Height];  
  7. Marshal.Copy(bitmapData.Scan0, bytes, 0, bytes.Length);  
  8. int index = 0;  
  9. int nResidual = bitmapData.Stride - width * 3;  
  10.   
  11. for (int i = 0; i < height; i++)  
  12. {  
  13.     for (int j = 0; j < width; j++)  
  14.     {  
  15.         int r = bytes[index + 2];  
  16.         int g = bytes[index + 1];  
  17.         int b = bytes[index];  
  18.   
  19.         index += 3;  
  20.     }  
  21.     index += nResidual;  
  22. }  
  23. bitmap.UnlockBits(bitmapData);  



unsafe

  1. BitmapData bitmapData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height),  
  2.                                         ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);  
  3.   
  4. int width = bitmapData.Width;  
  5. int height = bitmapData.Height;  
  6. int nResidual = bitmapData.Stride - width * 3;  
  7.   
  8. unsafe  
  9. {  
  10.     byte* p = (byte*)(void*)bitmapData.Scan0;  
  11.   
  12.     for (int y = 0; y < height; ++y)  
  13.     {  
  14.         for (int x = 0; x < width; ++x)  
  15.         {  
  16.             int r = p[2];  
  17.             int g = p[1];  
  18.             int b = p[0];  
  19.             p += 3;  
  20.         }  
  21.         p += nResidual;  
  22.     }  
  23. }  
  24. bitmap.UnlockBits(bitmapData);  

0 件のコメント: