gpt4 book ai didi

c# - 显示内存中的 RGBA 图像

转载 作者:太空狗 更新时间:2023-10-29 20:04:43 25 4
gpt4 key购买 nike

我有一个包含 RGBA 编码图像的 C# 字节数组。在 WPF 中显示此图像的最佳方式是什么?

一个选项是从字节数组创建一个 BitmapSource 并将其附加到一个图像控件。但是,创建 BitmapSource 需要 RGBA32 的 PixelFormat,这在 Windows 中似乎不可用。

byte[] buffer = new byte[] { 25, 166, 0, 255, 90, 0, 120, 255 };
BitmapSource.Create(2, 1, 96d, 96d, PixelFormats.Bgra32, null, buffer, 4 * 2);

我绝对不想交换字节数组中的像素。

最佳答案

在深入研究 WIC 的细节之前,您可以考虑将字节交换封装在一个简单的自定义 BitmapSource 中,如下所示。它采用 RGBA 字节数组并在覆盖的 CopyPixels 方法中交换像素字节以生成 PBGRA 缓冲区。

您可以通过提供 RGBA 缓冲区和位图宽度来简单地创建此自定义 BitmapSource 的实例

var buffer = new byte[] { 25, 166, 0, 255, 90, 0, 120, 255 };
var bitmapSource = new RgbaBitmapSource(buffer, 2);

实现如下:

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;
}
}
}
}

关于c# - 显示内存中的 RGBA 图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21428272/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com