我想在WinRT应用中获取每个像素的RGB值。我可以访问包含PixelData
的字节数组,但我不知道如何使用它,那么如何从字节数组中提取RGB信息?
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 :(得分:1)
由于您有RGB图像,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]
答案 1 :(得分:1)
由于Marshal类在WinRT上不可用 - 最有效的方法是使用SafeMemoryMappedViewHandle(SafeBuffer)。
此方法还可以处理具有多字节组件的像素格式,而无需使用BinaryReader并逐个组件读取(每个组件16位的RGBA16)。使用解码器的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上的某些等效操作。