2011-11-12 6 views
19

비트 맵 (System.Drawing.Bitmap)에서 모든 바이트 값을 가져 오려고합니다. 그러므로 나는 바이트를 잠그고 복사 :PixelFormat.Format32bppArgb의 바이트 순서가 잘못되었습니다.

public static byte[] GetPixels(Bitmap bitmap){ 
    if(bitmap-PixelFormat.Equals(PixelFormat.Format32.bppArgb)){ 
     var argbData = new byte[bitmap.Width*bitmap.Height*4]; 
     var bd = bitmap.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.ReadOnly, bitmap.PixelFormat); 
     System.Runtime.InteropServices.Marshal.Copy(bd.Scan0, argbData, 0, bitmap.Width * bitmap.Height * 4); 
     bitmap.UnlockBits(bd); 
    } 
} 

은 내가 포토샵에서 만든 픽셀 (빨강, 녹색, 파랑, 흰색)와 매우 간단한 2 × PNG 이미지와 함께이 이미지를 테스트했다. 때문에 형식의, 나는 argbData 내에서 다음 값 예상 :

255 255 0 0 255 0 255 0 
255 0  0 255 255 255 255 255 

을하지만 내가 가지고 :

0  0 255 255  0 255 0 255 
255 0 0 255 255 255 255 255 

을 그러나 이것은 BGRA 형식입니다. 바이트가 왜 바뀌는 지 아는 사람이 있습니까? 그런데 아래 그림과 같이 Image.Source에 직접 이미지를 사용하면 이미지가 올바르게 표시됩니다. 내 잘못은 뭐니?

<Image Source="D:/tmp/test2.png"/> 

답변

33

픽셀 데이터 ARGB 알파 1 바이트 볼 ... 메모리 RGBA 저장된다 AFAIK , 빨간색은 1, 녹색은 1, 파란색은 1입니다. 알파는 가장 중요한 바이트이고 파란색은 가장 중요하지 않은 바이트입니다. 너의 것 및 다른 많은 것 같이 little-endian 기계에, 작은 끝은 첫째로 저장된다 그래서 바이트 순서는 bb gg rr aa이다. 따라서 0 0 255 255는 파란색 = 0, 녹색 = 0, 빨간색 = 255, 알파 = 255와 같습니다. 빨간색입니다.

정수가 리틀 엔디안으로 저장되기 때문에 bd.Scan0을 int * (포인터에 정수로) 변환하면 엔디안 순서 세부 정보가 사라집니다.

+4

Excelent! 이 컴퓨터 아키텍처에서 데이터가 저장되는 바이트 순서 ("endianness")는 [BitConverter.IsLittleEndian] (http://msdn.microsoft.com/en-us/library/system)을 통해 확인할 수 있습니다. .bitconverter.islittleendian.aspx) 필드. – DmitryG

+1

'BitConverter.IsLittleEndian'에 대한 좋은 지적이긴하지만, @ HansPassant의 엔디안에 대한 언급은 정말로 가치 있다고 생각합니다. 이것은 엔디안을 고려하지 말아야 할 곳입니다. [Here 's] (http://commandcenter.blogspot.com.au/2012/04/byte-order-fallacy.html)이 주제에 대한 훌륭한 기사입니다. – Jonno

2

그것은 기술적 COLORREF (사방 윈도우 GDI에서 사용/GDI +)에 기초하며 그 http://msdn.microsoft.com/en-us/library/dd183449%28VS.85%29.aspx

+0

페이지를 이해하면 그 때마다 준비된 RGB를 의미하므로 실제 byteorder가 아닙니다. 항상 BGR을 의미합니까? 아니면 이것을 나타내는 깃발이 있습니까? – 0xBADF00D

+1

@hichaeretaqua GDI를 사용할 때 내가 모은 것에서부터 항상 BGR/BGRA를 얻는다. – Yahia

0

Bpp32Argb 픽셀 형식. byte-by-byte 액세스가 필요하지 않습니다.

안전하지 않은 컨텍스트에서 Trun Scan0에서 Int32 포인터로 이동합니다.

unsafe 
{ 
    var ptr=(int*)bmData.Scan0; 
} 

첫 번째 픽셀의 색상 채널에 액세스하려면 다음과 같은 비트 작동을 수행 할 수 있습니다.

그리고 바이트 순서를 신경 쓸 필요가 없습니다. Color.ToArgb() 쉽게 int을 반환과

var a=(ptr[0] & 0xFF000000)>>24; 
var r=(ptr[0] & 0x00FF0000)>>16; 
var g=(ptr[0] & 0x0000FF00)>>8; 
var b=(ptr[0] & 0x000000FF); 

은 BTW 당신은 ​​작업 할 수 있습니다.

+0

대답은 이미 언급되었지만 불행히도 일부 상황에서는 안전하지 않은 코드를 사용하십시오. 예를 들어, 안전하지 않은 코드를 허용하지 않는 여러 회사에서 일했습니다. – 0xBADF00D

관련 문제