在深入研究WIC的细节之前,您可以考虑将字节交换封装在一个简单的自定义BitmapSource中,如下所示。它需要RGBA字节数组并交换覆盖的CopyPixels
方法中的像素字节以生成PBGRA缓冲区。
你可以简单地通过提供RGBA缓冲区和位图宽度一样
var buffer = new byte[] { 25, 166, 0, 255, 90, 0, 120, 255 };
var bitmapSource = new RgbaBitmapSource(buffer, 2);
这里是实现创建这个定制的BitmapSource的一个实例:
public class RgbaBitmapSource : BitmapSource
{
private byte[] rgbaBuffer;
private int pixelWidth;
private int pixelHeight;
public RgbaBitmapSource(byte[] rgbaBuffer, int pixelWidth)
{
this.rgbaBuffer = rgbaBuffer;
this.pixelWidth = pixelWidth;
this.pixelHeight = rgbaBuffer.Length/(4 * pixelWidth);
}
public override void CopyPixels(
Int32Rect sourceRect, Array pixels, int stride, int offset)
{
for (int y = sourceRect.Y; y < sourceRect.Y + sourceRect.Height; y++)
{
for (int x = sourceRect.X; x < sourceRect.X + sourceRect.Width; x++)
{
int i = stride * y + 4 * x;
byte a = rgbaBuffer[i + 3];
byte r = (byte)(rgbaBuffer[i] * a/256); // pre-multiplied R
byte g = (byte)(rgbaBuffer[i + 1] * a/256); // pre-multiplied G
byte b = (byte)(rgbaBuffer[i + 2] * a/256); // pre-multiplied B
pixels.SetValue(b, i + offset);
pixels.SetValue(g, i + offset + 1);
pixels.SetValue(r, i + offset + 2);
pixels.SetValue(a, i + offset + 3);
}
}
}
protected override Freezable CreateInstanceCore()
{
return new RgbaBitmapSource(rgbaBuffer, pixelWidth);
}
public override event EventHandler<DownloadProgressEventArgs> DownloadProgress;
public override event EventHandler DownloadCompleted;
public override event EventHandler<ExceptionEventArgs> DownloadFailed;
public override event EventHandler<ExceptionEventArgs> DecodeFailed;
public override double DpiX
{
get { return 96; }
}
public override double DpiY
{
get { return 96; }
}
public override PixelFormat Format
{
get { return PixelFormats.Pbgra32; }
}
public override int PixelWidth
{
get { return pixelWidth; }
}
public override int PixelHeight
{
get { return pixelHeight; }
}
public override double Width
{
get { return pixelWidth; }
}
public override double Height
{
get { return pixelHeight; }
}
}
正如在评论中指出,您可以通过执行不安全的复制操作来提高性能,如下所示:
unsafe public override void CopyPixels(
Int32Rect sourceRect, Array pixels, int stride, int offset)
{
fixed (byte* source = rgbaBuffer, destination = (byte[])pixels)
{
byte* dstPtr = destination + offset;
for (int y = sourceRect.Y; y < sourceRect.Y + sourceRect.Height; y++)
{
for (int x = sourceRect.X; x < sourceRect.X + sourceRect.Width; x++)
{
byte* srcPtr = source + stride * y + 4 * x;
byte a = *(srcPtr + 3);
*(dstPtr++) = (byte)(*(srcPtr + 2) * a/256); // pre-multiplied B
*(dstPtr++) = (byte)(*(srcPtr + 1) * a/256); // pre-multiplied G
*(dstPtr++) = (byte)(*srcPtr * a/256); // pre-multiplied R
*(dstPtr++) = a;
}
}
}
}
'PixelFormats.Pbgra32'仍然交换红色和蓝色像素,所以这是行不通的。 – Jippe
对不起,我没有仔细阅读。你读过[这个问题](http://social.msdn.microsoft.com/Forums/en-US/5c6ad447-2027-4685-9ab2-62d418695a07/why-rgba32-in-pixelformats-is-not-supported) ? – Clemens
我做了,看起来好像名字为'GUID_WICPixelFormat32bppRGBA'的格式原生支持。但是,我该如何利用它呢? – Jippe