如何通过 BitmapImage 中的字节将像素写入 WriteableBitmap?

How to write pixels in WriteableBitmap by bytes from BitmapImage?

目标是存储许多相同大小的图像的字节并将它们绘制在 WriteableBitmap 中以创建高性能视频。

我尝试了下一个代码:

    public MainWindow()
    {
        InitializeComponent();

        Method();
    }

    private void Method()
    {
        BitmapImage bi = new BitmapImage(new Uri(@"Image.png", UriKind.Relative));
        int pw = bi.PixelWidth;
        int ph = bi.PixelHeight;

        WriteableBitmap wb = new WriteableBitmap(
            pw,
            ph,
            96,
            96,
            PixelFormats.Bgra32,
            null);

        byte[] data;
        PngBitmapEncoder encoder = new PngBitmapEncoder();
        encoder.Frames.Add(BitmapFrame.Create(bi));
        using (MemoryStream ms = new MemoryStream())
        {
            encoder.Save(ms);
            data = ms.ToArray();
        }

        int stride = 4 * pw;

        wb.Lock();
        wb.WritePixels(new Int32Rect(0, 0, pw, ph), data, 4 * pw, 0);
        wb.Unlock();
    }

错误:

Exception thrown: 'System.Windows.Markup.XamlParseException' in PresentationFramework.dll Additional information: 'The invocation of the constructor on type 'WpfApplication2.MainWindow' that matches the specified binding constraints threw an exception.' Line number '6' and line position '9'. If there is a handler for this exception, the program may be safely continued.

如果我在 UserControl 中放置相同的代码,它会给出下一个错误:

An unhandled exception of type 'System.ArgumentException' occurred in PresentationCore.dll Additional information: Buffer size is not sufficient.

你应该使用 CopyPixels。

MainWindow.xaml:

<Grid>
    <Image x:Name="image"></Image>
</Grid>

MainWindow.xaml.cs:

    private void Method()
    {
        BitmapImage bi = new BitmapImage(new Uri(@"Image.png", UriKind.Relative));

        int stride = bi.PixelWidth * (bi.Format.BitsPerPixel + 7) / 8;
        byte[] data = new byte[stride * bi.PixelHeight];

        bi.CopyPixels(data, stride, 0);

        WriteableBitmap wb = new WriteableBitmap(
            bi.PixelWidth,
            bi.PixelHeight,
            bi.DpiX, bi.DpiY,
            bi.Format, null);

        wb.WritePixels(
            new Int32Rect(0, 0, bi.PixelWidth, bi.PixelHeight),
            data, stride, 0);

        image.Source = wb; // an Image class instance from XAML.
    }