2011-10-14 7 views
3

내가 Lockbits를 사용하여 그레이 스케일 이미지를 쓰기 위해 노력하고있어, 내 현재 코드가 보이는사용 LockBits 이상한 이미지

/// <summary> 
/// Save the content of the FrameProc out to a bitmap 
/// </summary> 
public void Save(string path) 
{ 
    Bitmap bmp = new Bitmap(this.size.Width, this.size.Height 
          ,PixelFormat.Format32bppRgb); 
    var data = bmp.LockBits(this.size, ImageLockMode.WriteOnly, bmp.PixelFormat); 

    unsafe 
    { 
     for (int y = 0; y < this.size.Height; y++) 
     { 
      byte* row = (byte*)data.Scan0 + (y * data.Stride); 
      for (int x = 0; x < this.size.Width; x++) 
      { 
       byte value = (byte)this.buffer[y, x]; 
       row[x*Bits+r] = value; 
       row[x*Bits+g] = value; 
       row[x*Bits+b] = value; 
      } 
     } 
    } 

    bmp.UnlockBits(data); 
    bmp.Save(path, ImageFormat.Bmp); 
} 

입니다 생성 어디에서받는 이미지가 정확하지 그러나

/// <summary> 
/// The amount of Bytes per pixel in the image 
/// </summary> 
private const int Bits = 4; 

/// <summary> 
/// Image components 
/// </summary> 
private const int a=3, r = 2, g = 1, b = 0; 

:

Broken image http://i52.tinypic.com/2e4vsxz.jpg

은 어쩌면 이것은 내가 읽을 수있어 얼마나 관련이있다 그들을 들여 보내? 그래서 여기

public FrameProc(Bitmap bmp) 
    { 
     this.size=new Rectangle(new Point(0,0), bmp.Size); 
     var data = bmp.LockBits(this.size 
           ,ImageLockMode.ReadOnly 
           ,bmp.PixelFormat); 
     this.buffer = new Matrix(this.size.Height, this.size.Width); 

     unsafe 
     { 
      for (int y = 0; y < this.size.Height; y++) 
      { 
       byte* row = (byte*)data.Scan0 + (y * data.Stride); 
       for (int x = 0; x < this.size.Width; x++) 
       { 
        this.buffer[y,x] = 0.299*row[x*Bytes+r] 
            + 0.587*row[x*Bytes+g] 
            + 0.114*row[x*Bytes+b]; 
       } 
      } 
     } 

     bmp.UnlockBits(data); 
    } 
+1

나는 이미지의 선택이 모든 사람의 취향에 맞을 지 확신하지 못합니다. – spender

답변

4

에서 촬영 될 수 있습니다 - 정확히처럼 보입니다. 각 픽셀이 4 바이트가 아니라 3 바이트로 선언 된 것처럼 - 그리고 예상대로 -. (참고 : 당신이 그것을 비트라고 부르지 만 그것은 잘못입니다 - 그것은 비트가 아니라 바이트입니다).

I이 중 어느 한 실험 것 :

  • 변화 4 내지 3 바이트 Format32bppArgb에 Format32bppRgb에서
  • 변경 및 4 3 바이트에서 255
  • 변화 알파 기입

    : 및 Format32bppRgb에서 Format24bppRgb
  • 에서
나는 또한 (미안, 나 자신을 도울 수) 성능을 약간 루프를 다시 작성 것이다

for (int x = 0; x < this.size.Width; x++, row += Bits) 
       { 
        byte value = (byte)this.buffer[y, x]; 
        row[r] = value; 
        row[g] = value; 
        row[b] = value; 
       } 

고정 키워드를 사용하여 this.buffer에 대한 포인터를 얻으면 속도는 더 빨라 졌습니까? 예, 성능 문제는 없지만 언급 할 수는 없습니다.

+0

해당 루프 한 번에 3 바이트를 스킵 (skyp)하면, 이미지는 구멍으로 끝날 것입니다. Row는 this.buffer보다 3 배 더 커야합니다. 버퍼는 Y 만 보유하고 RGBx 값을 행하기 때문입니다. – Phyx

+0

예 - 각 라운드에서 불필요한 x * 비트 곱셈을하는 대신 행을 증가시킵니다. 저를 믿으십시오, 나는 영상 처리를하고 .LockBita * 많이 *. 하지만 Format32bppRgb 형식을 사용 해보지 않았습니다. –

+0

아 맞아, 내가 x = + 비트, – Phyx

1

이 기능을 사용하여 실제로 그 코드입니다 :

public Bitmap MakeGrayscale(Bitmap original) 
{ 
    unsafe 
    { 
     //create an empty bitmap the same size as original 
     Bitmap newBitmap = new Bitmap(original.Width, original.Height); 

     //lock the original bitmap in memory 
     BitmapData originalData = original.LockBits(
     new Rectangle(0, 0, original.Width, original.Height), 
     ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb); 

     //lock the new bitmap in memory 
     BitmapData newData = newBitmap.LockBits(
     new Rectangle(0, 0, original.Width, original.Height), 
     ImageLockMode.WriteOnly, PixelFormat.Format24bppRgb); 

     //set the number of bytes per pixel 
     // here is set to 3 because I use an Image with 24bpp 
     int pixelSize = 3; 

     for (int y = 0; y < original.Height; y++) 
     { 
     //get the data from the original image 
     byte* oRow = (byte*)originalData.Scan0 + (y * originalData.Stride); 

     //get the data from the new image 
     byte* nRow = (byte*)newData.Scan0 + (y * newData.Stride); 

     for (int x = 0; x < original.Width; x++) 
     { 
      //create the grayscale version 
      byte grayScale = 
       (byte)((oRow[x * pixelSize] * .11) + //B 
       (oRow[x * pixelSize + 1] * .59) + //G 
       (oRow[x * pixelSize + 2] * .3)); //R 

      //set the new image's pixel to the grayscale version 
      nRow[x * pixelSize] = grayScale; //B 
      nRow[x * pixelSize + 1] = grayScale; //G 
      nRow[x * pixelSize + 2] = grayScale; //R 
     } 
     } 

     //unlock the bitmaps 
     newBitmap.UnlockBits(newData); 
     original.UnlockBits(originalData); 

     return newBitmap; 
    } 
} 

소스 및 (뒤에 이론) 다른 흥미로운 예 당신이 얻고있는 결과로부터 here

+0

내가하려는 것은 이미지를 그레이 스케일로 변환하는 것이 아닙니다. 저는 그레이 스케일로 변환하는 것이 첫 번째 단계 일 때 이미지의 byteof 이미지를 처리하고 있습니다. 따라서 ColorMatrix에서 처리 할 수없는 작업을 수행해야합니다. – Phyx

+0

@Phyx : 링크에서 나는 내 대답에 게시 된 'LockBits'를 사용하여 _MakeGrayScale_ 함수를 찾았습니다. – Marco

+0

@Phyx : 해당 링크에있는 함수를 작성하여 답변을 편집했습니다. – Marco