You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

将字节数组转为Bitmap后调用EndInit()时出现System.NotSupportedException异常

问题分析与解决方案

核心错误原因

  1. 像素数组大小计算错误:你用_originalImage.PixelWidth * stride计算总字节数,正确的应该是_originalImage.PixelHeight * stride——总像素行数是图像高度,每行字节数是stride,总大小是行数×每行字节数。
  2. 像素格式处理错误:WPF的BitmapImage默认采用BGRA格式(每个像素占4字节:蓝、绿、红、透明度),你的循环按3字节步长处理,跳过了透明度通道,同时循环边界计算错误,会导致部分像素未处理或越界。
  3. BitmapImage的使用误区:BitmapImage需要读取编码后的图像数据流(如PNG、JPG格式),但你直接把原始像素字节数组写入MemoryStream,这不是标准图像格式,所以初始化时会抛出异常。

修正后的代码

1. 修正ApplyFilter_Click方法的像素数组大小计算

private async void ApplyFilter_Click(object sender, RoutedEventArgs e)
{
    int stride = _originalImage.PixelWidth * 4; 
    // 修正:总大小 = 高度 × 每行字节数
    long size = _originalImage.PixelHeight * stride; 
    byte[] originalPixels = new byte[size];
    _originalImage.CopyPixels(originalPixels, stride, 0);
    // 改用WriteableBitmap,直接处理原始像素
    WriteableBitmap source = await ToBlackAndWhiteImage(originalPixels);
    ChangedImage.Source = source;
}

2. 重写ToBlackAndWhiteImage方法,正确处理BGRA格式并返回WriteableBitmap

private Task<WriteableBitmap> ToBlackAndWhiteImage(byte[] originalPixels)
{ 
    // 按BGRA格式循环,步长为4
    for (int i = 0; i < originalPixels.Length; i += 4)
    {
        // 提取蓝、绿、红通道值
        byte blue = originalPixels[i];
        byte green = originalPixels[i + 1];
        byte red = originalPixels[i + 2];
        // 计算灰度值(使用ITU-R BT.601标准公式,比简单平均更准确)
        int gray = (int)(0.299 * red + 0.587 * green + 0.114 * blue);
        // 赋值回蓝、绿、红通道,保留透明度通道不变
        originalPixels[i] = (byte)gray;
        originalPixels[i + 1] = (byte)gray;
        originalPixels[i + 2] = (byte)gray;
        // 透明度通道originalPixels[i+3]保持不变
    }

    // 创建WriteableBitmap,直接使用处理后的像素数据
    WriteableBitmap bwImage = new WriteableBitmap(
        _originalImage.PixelWidth, 
        _originalImage.PixelHeight, 
        _originalImage.DpiX, 
        _originalImage.DpiY, 
        PixelFormats.Bgra32, 
        null);
    bwImage.WritePixels(
        new Int32Rect(0, 0, _originalImage.PixelWidth, _originalImage.PixelHeight), 
        originalPixels, 
        _originalImage.PixelWidth * 4, 
        0);

    return Task.FromResult(bwImage);
}

额外说明

  • 使用WriteableBitmap是WPF中处理原始像素数据的正确方式,它不需要编码成图像格式,直接渲染像素数组。
  • 灰度计算改用ITU-R BT.601标准公式,比简单平均更符合人眼对色彩的感知,灰度效果更自然。
  • 保留了原图像的透明度通道,避免图像出现透明异常。

内容的提问来源于stack exchange,提问作者Лев Поваляев

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 19:18:44