为什么 Bitmap.Save 会更改图像的大小

本文关键字:图像 Bitmap Save 为什么 | 更新日期: 2023-09-27 17:56:29

我成功地更改了图像的DateTaken属性。但是,重新保存图像后,其大小发生了变化。我检查了Matlab,两个图像的字节是相同的。

为了检查更改属性是否会更改大小,我决定只打开文件并保存它而不更改任何属性。代码如下:

using (var image = new Bitmap(@"C:'Temp'1.jpg"))
{  
    image.Save(@"C:'Temp'2.jpg");
}

但是,大小仍然发生了变化。原始 jpeg 图像1.jpg的大小为 1.88 MB (1,975,162 bytes) 。将其重新保存到2.jpg后,图像的大小更改为 1.86 MB (1,960,824 bytes)

可能是什么问题?虽然 Matlab 向我保证图像的字节没有改变,但我想听听你说Bitmap.Save不应该改变图像的字节。

为什么 Bitmap.Save 会更改图像的大小

Jpeg 是一种压缩格式。它能够以不同的质量和不同的压缩格式保存。我的猜测是,两个图像的压缩级别设置不同。由于字节在读取时被解压缩(无论压缩格式如何),因此即使字节的压缩方式不同,它们也将是相同的。

考虑一下,如果您获取一个文件并用 ZIP 格式压缩它,然后您采用相同的文件并用 RAR 格式压缩它。这两个文件的大小不同,但是当它们解压缩时,文件内部是相同的。

您可以在此处阅读有关如何设置图像压缩级别的信息

我正在从链接中复制代码以便于参考:

private void VaryQualityLevel()
{
    // Get a bitmap.
    Bitmap bmp1 = new Bitmap(@"c:'TestPhoto.jpg");
    ImageCodecInfo jpgEncoder = GetEncoder(ImageFormat.Jpeg);
    // Create an Encoder object based on the GUID 
    // for the Quality parameter category.
    System.Drawing.Imaging.Encoder myEncoder =
        System.Drawing.Imaging.Encoder.Quality;
    // Create an EncoderParameters object. 
    // An EncoderParameters object has an array of EncoderParameter 
    // objects. In this case, there is only one 
    // EncoderParameter object in the array.
    EncoderParameters myEncoderParameters = new EncoderParameters(1);
    EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, 50L);
    myEncoderParameters.Param[0] = myEncoderParameter;
    bmp1.Save(@"c:'TestPhotoQualityFifty.jpg", jpgEncoder, myEncoderParameters);
    myEncoderParameter = new EncoderParameter(myEncoder, 100L);
    myEncoderParameters.Param[0] = myEncoderParameter;
    bmp1.Save(@"c:'TestPhotoQualityHundred.jpg", jpgEncoder, myEncoderParameters);
    // Save the bitmap as a JPG file with zero quality level compression.
    myEncoderParameter = new EncoderParameter(myEncoder, 0L);
    myEncoderParameters.Param[0] = myEncoderParameter;
    bmp1.Save(@"c:'TestPhotoQualityZero.jpg", jpgEncoder, myEncoderParameters);
}

JPEG能够进行可变压缩,以压缩与对原始的保真度之间进行权衡。可能影响大小的因素包括:

  1. 特定的 JPEG 格式:顺序或渐进式。顺序在一次扫描中对组件的所有数据进行编码。逐行扫描在多个扫描中对组件进行编码。渐进式通常会产生更大的压缩。但是,有无数的设置适用于渐进式。

  2. 采样。Jpeg 允许以低于 Y 分量的速率对 Cb 和 Cb 分量进行采样。如果每两个 Y(垂直和水平)取一个 Cb 和 Cr 样本,则每 4 个 Y 个样本获得 1 个 Cb 和 CR 样本。这将要压缩的数据量从 12 减少到 6

  3. 量化表。量化表选择是JPEG压缩设置的主要形式。许多编码器将其隐藏在"质量"设置后面。

  4. 霍夫曼表。某些编码器使用预定义的霍夫曼表。如果编码器生成针对特定图像优化的霍夫曼表(速度较慢且工作量较多),则可以获得更好的压缩。

除非您使用原始设置的相同设置重新压缩,否则您将获得不同的输出大小。即使您使用相同的设置,您通常也会因为舍入而提出不同的值:JPEG 使用四舍五入为整数的浮点计算。