2012-12-18 2 views
1

에서 픽셀의 RGB 값을 얻기 위해 어떻게 WinRT 응용 프로그램의 각 픽셀의 RGB 값을 얻기 위해 노력하고 있어요. PixelData을 포함하는 바이트 배열에 액세스 할 수 있지만 바이트 배열에서 RGB 정보를 추출하려면 어떻게해야합니까? 만약 RGB 이미지를 가지므로는 WinRT

var bd = await Windows.Graphics.Imaging.BitmapDecoder.CreateAsync(stream); 
var pd = await bd.GetPixelDataAsync(); 
var tempBuffer = pd.DetachPixelData(); 
var PixelMatrix = new byte[bd.PixelWidth, bd.PixelHeight]; 
// how do I get the RGB value for PixelMatrix[0,0]? 
+0

당신은 PixelMatrix'에 세 개의 값을 저장할 필요가 [0, 0]': R, G, 및 B를 따라서'PixelMatrix'는 다른 방식으로 선언 될 필요가있다. 또는 3 바이트를 더 큰 단위로 패킹 할 수 있습니다.이 경우 복잡한 문제를 처리하고 싶은지 확실하지 않습니다. – mmgp

답변

1

tempBuffer[k + 0]tempBuffer[k + 1]은 녹색 채널 인 적색 채널이며 tempBuffer[k + 2]tempBuffer은 1D 배열 청색 채널이다. 모든 픽셀 이상 반복 된 경우, 이에 대한 의사 코드는 다음과 같습니다

for i = 0 to height - 1 
    for j = 0 to width - 1 
     k = (i * width + j) * 3 
     r, g, b = tempBuffer[k + 0], tempBuffer[k + 1], tempBuffer[k + 2] 
+0

감사 다른 인코딩 방법에도 동일하게 적용됩니까? 예를 들어 bgra8에서 첫 번째 바이트는 파란색으로 두 번째 녹색을 포함합니까 ... – Yohannes

+0

이 경우 4 채널이 있으므로이 경우 4를 곱해야합니다. 위의 코드가 임의의 수의 채널에 사용할 수 있도록 채널 수를 얻는 것이 좋습니다. 이제이 경우의 두 번째 문제는 BGRA가 RGBA와는 다른 순서이므로 분명히 얻은 채널에 대한 관찰이 정확하다는 것입니다. 내가 너라면 배열의 최종 순서가 항상 같아 지도록 BGRA에서 RGBA 로의 매핑을 수행 할 것입니다. – mmgp

+0

다른 픽셀 형식의 코드를 변경해야합니다. 아래의 방법은 WinRT 메서드로 블록 복사를 내부적으로 사용하기 때문에 훨씬 더 효율적입니다. 또한이 메디드는 픽셀이 다중 바이트 구성 요소 (예 : float)로 구성되어 있으면 일종의 BinaryReader를 사용해야합니다. – Ani

1

육군 원수 클래스는 WinRT에서 사용할 수 없습니다 때문에 - 진행하는 가장 성능이 좋은 방법은 SafeMemoryMappedViewHandle (SafeBuffer)를 사용하는 것 .

이 방법은 또한 BinaryReader를 사용을 필요로하고 (성분 당 16 비트 RGBA16) 성분으로 성분을 읽지 않고 멀티 바이트있는 PixelFormats 컴포넌트를 처리 할 수있다. 디코더의 BitmapPixelFormat 속성을 사용하여 픽셀 형식을 확인하고 적절히 선언 된 구조를 사용하십시오.

// declare more of these appropriately laid 
    // out structures for different pixel formats 
    struct RGBA16 
    { 
     public uint R; 
     public uint G; 
     public uint B; 
     public uint A; 
    } 

    struct RGBA8 
    { 
     public byte R; 
     public byte G; 
     public byte B; 
     public byte A; 
    } 

    struct BRGA8 
    { 
     public byte B; 
     public byte G; 
     public byte R; 
     public byte A; 
    } 
    ... 

    var handle = GCHandle.Alloc(tempBuffer /* the raw byte[] */, GCHandleType.Pinned); 
    try 
    { 
     var ptr = handle.AddrOfPinnedObject(); 
     var safeBuffer = new SafeMemoryMappedViewHandle(true /* I believe DetachPixelData returns a copy? false otherwise */) 
     safeBuffer.SetHandle(ptr); 

     #if STREAM_PROCESSING 
      // pixel by pixel 
      int offset = 0; 
      for (int i = 0; i < width * height; i++) 
      { 
       var pixel = safeBuffer.Read<RGBA16>(offset); 
       offset += RGB24bpp.Size; 
      } 
     #else 
      // Read it all in at once - this makes a copy 
      var pixels = new RGBA16[width * height]; 
      safeBuffer.ReadArray<RGBA16>(0, pixels, 0, width * height); 
     #endif 
    } 
    finally 
    { 
     safeBuffer.Dispose(); 
     handle.Free; 
    } 

주 :이 방법은 또한 Marshal.PtrToStructure WinRT 또는 일부 그러한 등가가 필요한 작업을 대체 할 수있다. 세 밴드와 함께 이미지를 갖고 있기 때문에

+0

마샬 (Marshal) 클래스없이 WinRT를 사용하여 멀티 바이트 구성 요소 기반 픽셀 형식을 효율적으로 읽어야하는 사람들을 위해 여기에 두십시오. – Ani