2016-03-22 21 views
1

画像処理用のLockBitmapクラスを学習しようとしています。基本的にはx-y座標の色を返します。C#LockBitmap - xy座標からピクセルバイトへの変換

もちろん、この方法はsource.LockBits()Marshal.Copy()/unsafe contextを実行した後にのみ機能します。

public Color GetPixel(int x, int y, Bitmap source) 
{ 
    int Depth = System.Drawing.Bitmap.GetPixelFormatSize(source.PixelFormat); 
    int Width = source.Width; 
    int Height = source.Height; 
    Color clr = Color.Empty; 

    // Get color components count 
    int cCount = Depth/8; 
    int PixelCounts = Width * Height; 
    byte[] Pixels = new byte[cCount * PixelCounts]; 

    // Get start index of the specified pixel 
    int i = ((y * Width) + x) * cCount; 

    byte b = Pixels[i]; 
    byte g = Pixels[i + 1]; 
    byte r = Pixels[i + 2]; 
    byte a = Pixels[i + 3]; // a 
    clr = Color.FromArgb(a, r, g, b); 

    return clr; 
} 
  1. それは常にDepth/8である理由、cCountは何ですか?
  2. int i = ((y * Width) + x) * cCountは、(x、y)座標をPixels[i]に変換する固定式ですか?どうして?
+1

これは非常に単純化されており、単純な32ビットビットマップでは本当に正しく動作します( 'Pixels'は最初の場所にデータを取得しないことは無視してください)。パレット、整列、ビット整列は処理しません(すべてのビットマップが「バイト整列」されているわけではありません)。安全なGDI +メソッドを回避したい場合は、高速なコードの鍵となる少しの研究を行う必要がありますあなたに関係しないエッジケースをしばしば無視していますが、それは最初のエッジケースが何であるかを知り、安全に無視できるかどうかを理解することを意味します。 – Luaan

+0

@Luaan、応答に感謝します。私は本当にこれについてもっと研究したいと思っています。お勧めするチュートリアル/ウェブサイトはありますか?私はどんなキーワードをGoogleと知っていません。 –

+0

事は、すべてこれが*古代*、低レベルのものです。ほとんどの場合、さまざまなソースからまとめなければならないという知識があります。ゲームでさえ、最近のすべてで32ビットARGBを使用しています(よく、HDR:Pに移行しているものは別です)。たとえば、特定のピクセル形式を想定することができれば、すべての複雑さを無視することができます。これは、最も一般的な形式(MSPaintの32ビットは最近のWindowsでは一般的です)を単純に選択する方法です。他の形式から変換するためにGDI +にフォールバックします。 – Luaan

答えて

0
  1. 常に、これはあなたに優れた実装であるかもしれないアウトthis.チェックされていません。

    色情報に8(または16など)バイトが必要であるため、8,16,24,32などとなります。投稿源から

例コード:

// Get start index of the specified pixel 
     int i = ((y * Width) + x) * cCount; 

     if (i > Pixels.Length - cCount) 
      throw new IndexOutOfRangeException(); 

     if (Depth == 32) // For 32 bpp get Red, Green, Blue and Alpha 
     { 
      byte b = Pixels[i]; 
      byte g = Pixels[i + 1]; 
      byte r = Pixels[i + 2]; 
      byte a = Pixels[i + 3]; // a 
      clr = Color.FromArgb(a, r, g, b); 
     } 
     if (Depth == 24) // For 24 bpp get Red, Green and Blue 
     { 
      byte b = Pixels[i]; 
      byte g = Pixels[i + 1]; 
      byte r = Pixels[i + 2]; 
      clr = Color.FromArgb(r, g, b); 
     } 
     if (Depth == 8) 
     // For 8 bpp get color value (Red, Green and Blue values are the same) 
     { 
      byte c = Pixels[i]; 
      clr = Color.FromArgb(c, c, c); 
ビットマップがメモリにアレイとして格納されるため
  • (y *幅)は次元、+ x)は次元のピクセル、* cCountはピクセルあたりのステップです。あなたがオンラインですべてのピクセルを置くかのようにそれの

  • と思いますが(すべてのピクセルはメモリ内のCCOUNTバイトを必要とする)、そして、それは左下で始まり、左上に進み、左、下から2行目を終わります2列目の最上部に移動し、右上に到達するまで続きます。

    +0

    サイトによると、それは常に深さ/ 8です。私は実際にこの色成分が何であるかを知りたいのです。私の理解から、ここでは「深さ」は「bpp」です。だから、なぜcCountは常に 'bpp/8'ですか? –

    +2

    @Liren Depthはビット単位で、バイトをアドレス指定しています。バイトは8ビットです。もちろん、深さが7または2、または14の場合、これは分解されます。 – Luaan

    +0

    @Luaan、私が参照してください!私はちょっと馬鹿だと感じています。 –

    関連する問題