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

如何从JPEG格式Bitmap中获取压缩质量值?

从JPEG Bitmap中获取压缩质量值的问题

我尝试从加载自JPEG图片的Bitmap中获取质量值,编写了如下C#代码:

int GetQuality(Bitmap bitmap) {
    if (!bitmap.RawFormat.Equals(ImageFormat.Jpeg)) return -1;

    ImageCodecInfo jpegEncoder = ImageCodecInfo.GetImageEncoders().First(c => c.FormatID == ImageFormat.Jpeg.Guid);
    var jpegGuid = jpegEncoder.Clsid;
    var jpegParams = bitmap.GetEncoderParameterList(jpegGuid);
    EncoderParameter qualityParam = jpegParams?.Param[1]!;

    BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
    FieldInfo? field = typeof(EncoderParameter).GetField("_parameterValue", bindFlags);
    object obj = field!.GetValue(qualityParam)!;
    IntPtr qualityParamValue = (IntPtr) obj;
    unsafe {
        //byte* qpvPtr = (byte*) qualityParamValue;
        //var quality = *qpvPtr;    // val is type byte with a value of 0

        var quality = *(byte*) qualityParamValue; // val is type byte with a value of 0
        return quality;
    }
}

但对于以50%压缩质量(使用EncoderParameter(Encoder.Quality, 50L))保存的JPEG Bitmap,获取到的质量值为0。要么是我的反射及unsafe代码存在问题,要么是JPEG Bitmap中并未存储质量值。我参考EncoderParameter的构造函数编写了上述代码,该构造函数如下:

public EncoderParameter(Encoder encoder, byte value)
{
    _parameterGuid = encoder.Guid;

    _parameterValueType = EncoderParameterValueType.ValueTypeByte;
    _numberOfValues = 1;
    _parameterValue = Marshal.AllocHGlobal(sizeof(byte));

    *(byte*)_parameterValue = value;
    GC.KeepAlive(this);
}

其中byte value为0-100的质量值。我的unsafe代码是否正确实现了*(byte*)_parameterValue = value;的逆操作?如果没有,问题出在哪?如果正确,是否意味着压缩后的Bitmap中并未存储质量值?


问题分析与解答

1. Unsafe代码逻辑无问题

从构造函数的实现来看,_parameterValue指向的是一块分配的字节内存,里面存储了byte类型的质量值。你的unsafe代码*(byte*) qualityParamValue确实是构造函数中*(byte*)_parameterValue = value;的逆操作,这部分逻辑是正确的。

2. 核心原因:JPEG不存储压缩质量参数

你获取到0的本质原因是:加载到内存的Bitmap对象,以及原始JPEG文件本身,都不会存储编码时设置的压缩质量值。

  • 压缩质量是JPEG编码时的控制参数,它只影响压缩算法的行为(比如量化表的选择),但这个参数本身不会被写入最终的JPEG文件。
  • 当你从JPEG文件加载Bitmap时,.NET仅解码像素数据,不会保留编码时的质量参数;GetEncoderParameterList返回的是编码器的默认参数或空值,并非原始编码时的设置。

3. 验证方式

直接解析JPEG文件的二进制内容就能确认:JPEG的文件结构(SOI、DQT、SOF等标记)中没有专门存储压缩质量的字段,质量仅通过量化表间接体现,但无法直接还原出原始的0-100数值。

4. 替代方案

如果需要保留压缩质量信息,只能在保存JPEG时,将质量值额外存储到其他位置(比如图片的EXIF元数据、单独的配置文件等),后续读取时再从这些地方获取。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 22:13:15