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

.NET框架升级后SkiaSharp与System.Drawing编码字节数组不一致问题咨询

问题

将项目从.NET Framework 4.7.2升级至.NET Standard 2.0,为适配Linux环境采用MSDN推荐的SkiaSharp处理图片。但在将BMP转为PNG/JPEG格式并获取字节数组时,SkiaSharp的输出结果与原System.Drawing.Image.Save的结果不一致,出于兼容性需求,需要让两者输出的字节数组完全一致,已尝试调整SKJpegEncoderOptions和SKPngEncoderOptions但未解决。

原System.Drawing实现代码

....
var encoder = GetEncoder(imageFormat);
if (encoder == null)
{
    return Array.Empty<byte>();
}

var myEncoder = Encoder.Quality;
var myEncoderParameters = new EncoderParameters(1);
var myEncoderParameter = new EncoderParameter(myEncoder, 50L);
myEncoderParameters.Param[0] = myEncoderParameter;

byte[] byteArray;
using (var stream = new MemoryStream())
{
    bmp.Save(stream, encoder, myEncoderParameters);
    byteArray = stream.ToArray();
}
....

public ImageCodecInfo GetEncoder(ImageFormat format)
{
    try
    {
        var imageDecoders = ImageCodecInfo.GetImageDecoders();

        return imageDecoders.FirstOrDefault(codec => codec.FormatID == format.Guid);
    }
    catch (Exception)
    {
        return null;
    }
}

原SkiaSharp实现代码

public byte[] BmpToByteArrayByImageFormat(SKBitmap bmp, SKEncodedImageFormat imageFormat)
{
    try
    {
        var data = bmp.Encode(imageFormat, 50);

        return data.ToArray();
    }
    catch (Exception)
    {
        return Array.Empty<byte>();
    }
}
解决方案

针对JPEG格式的对齐调整

System.Drawing的GDI+ JPEG编码器和SkiaSharp编码器在压缩细节、色彩采样上存在默认差异,需精准匹配参数:

  • 指定YCbCr采样比例为4:4:4(GDI+对质量≥50的JPEG默认用该采样)
  • 禁用渐进式模式(GDI+默认生成非渐进式JPEG)
  • 对齐质量参数映射逻辑(GDI+与SkiaSharp的质量数值并非完全等价,需微调测试)

调整后的SkiaSharp JPEG处理代码:

public byte[] BmpToByteArrayByImageFormat(SKBitmap bmp, SKEncodedImageFormat imageFormat)
{
    try
    {
        if (imageFormat == SKEncodedImageFormat.Jpeg)
        {
            var options = new SKJpegEncoderOptions
            {
                Quality = 50,
                Subsample = SKJpegEncoderSubsample.Ratio444,
                Progressive = false
            };
            using var data = bmp.Encode(options);
            return data.ToArray();
        }
        
        var data = bmp.Encode(imageFormat, 50);
        return data.ToArray();
    }
    catch (Exception)
    {
        return Array.Empty<byte>();
    }
}

针对PNG格式的对齐调整

PNG的差异主要来自调色板处理、压缩级别和元数据:

  • 索引色BMP:需确保SkiaSharp保留原调色板,避免自动转RGB
  • 压缩级别:GDI+默认压缩级别对应SkiaSharp的6-7级
  • 滤镜设置:GDI+默认无PNG滤镜

调整后的SkiaSharp PNG处理代码:

public byte[] BmpToByteArrayByImageFormat(SKBitmap bmp, SKEncodedImageFormat imageFormat)
{
    try
    {
        if (imageFormat == SKEncodedImageFormat.Png)
        {
            var options = new SKPngEncoderOptions
            {
                CompressionLevel = SKPngEncoderCompressionLevel.Level6,
                FilterFlags = SKPngEncoderFilterFlags.None
            };
            // 若原BMP为索引色,需提前将SKBitmap配置为对应索引颜色类型
            using var data = bmp.Encode(options);
            return data.ToArray();
        }
        
        var data = bmp.Encode(imageFormat, 50);
        return data.ToArray();
    }
    catch (Exception)
    {
        return Array.Empty<byte>();
    }
}

额外注意事项

  • 色彩空间:确保SkiaSharp的SKBitmap使用sRGB色彩配置(与GDI+默认一致)
  • 透明通道:若原BMP含透明通道,需明确是否保留,两者处理逻辑有差异
  • 测试验证:对24位、32位、索引色等不同类型BMP逐一测试,对比字节数组哈希值确认一致性

内容的提问来源于stack exchange,提问作者Willis Liou

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 03:41:10