加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – 从内存中显示RGBA图像

发布时间:2020-12-15 08:24:31 所属栏目:百科 来源:网络整理
导读:我有一个包含RGBA编码图像的C#字节数组.在 WPF中显示此图像的最佳方法是什么? 一种选择是从字节数组创建一个BitmapSource并将其附加到Image控件.但是,创建一个BitmapSource需要一个用于RGBA32的PixelFormat,这在Windows中似乎不可用. byte[] buffer = new b
我有一个包含RGBA编码图像的C#字节数组.在 WPF中显示此图像的最佳方法是什么?

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

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

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

解决方法

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

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

var buffer = new byte[] { 25,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,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;
            }
        }
    }
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读