为什么 Bitmap.Save 改变图像的大小?
Why Bitmap.Save changes image's size?
我成功更改了图像的 DateTaken
属性。但是,在重新保存图像后,它的大小发生了变化。我检查了 Matlab
,两个图像的字节是相同的。
为了检查更改 属性 是否会改变大小,我决定只打开文件并保存它而不更改任何属性。代码如下:
using (var image = new Bitmap(@"C:\Temp.jpg"))
{
image.Save(@"C:\Temp.jpg");
}
但是,尺寸还是变了。原始jpeg图像的大小1.jpg
是1.88 MB (1,975,162 bytes)
。重新保存为2.jpg
后,图片大小变为1.86 MB (1,960,824 bytes)
。
可能是什么问题?虽然 Matlab 向我保证图像的字节没有改变,但我想听听你说 Bitmap.Save
不应该改变图像的字节。
Jpeg 是一种压缩格式。它能够以不同的质量和不同的压缩格式保存。我的猜测是,两个图像的压缩级别设置不同。因为字节在读取时会被解压缩(无论压缩格式如何),所以字节将是相同的,即使它们的压缩方式不同。
想想如果你拿一个文件并用 ZIP 格式压缩它,然后你拿同一个文件用 RAR 格式压缩它。两个文件大小会不一样,但是解压后里面的文件是一样的
您可以阅读有关如何设置图像压缩级别的信息here
我正在从 link 复制代码以便于参考:
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 能够进行可变压缩,在压缩与保真度之间进行权衡。影响大小的因素包括:
具体的 JPEG 格式:Sequential 或 Progressive。 Sequential 在单次扫描中对组件的所有数据进行编码。渐进式在多次扫描中对一个组件进行编码。渐进通常可以产生更大的压缩。但是,有无数的设置适用于渐进式。
抽样。 Jpeg 允许以低于 Y 分量的速率对 Cb 和 Cb 分量进行采样。如果您对每两个 Y(垂直和水平)取一个 Cb 和 Cr 样本,则每 4 个 Y 样本将获得 1 个 Cb 和 CR 样本。这将要压缩的数据量从 12 减半减少到 6。
量化table秒。量化table选择是JPEG压缩设置的主要形式。许多编码器将其隐藏在 "quality" 设置后面。
霍夫曼 tables。一些编码器使用预定义的 Huffman tables。如果编码器生成针对特定图像优化的 Huffman table(更慢且工作量更大),您可以获得更好的压缩。
除非您使用与原始文件相同的设置重新压缩,否则您将获得不同的输出大小。即使您使用相同的设置,由于四舍五入,您通常会得到不同的值:JPEG 使用四舍五入为整数的浮点计算。
我成功更改了图像的 DateTaken
属性。但是,在重新保存图像后,它的大小发生了变化。我检查了 Matlab
,两个图像的字节是相同的。
为了检查更改 属性 是否会改变大小,我决定只打开文件并保存它而不更改任何属性。代码如下:
using (var image = new Bitmap(@"C:\Temp.jpg"))
{
image.Save(@"C:\Temp.jpg");
}
但是,尺寸还是变了。原始jpeg图像的大小1.jpg
是1.88 MB (1,975,162 bytes)
。重新保存为2.jpg
后,图片大小变为1.86 MB (1,960,824 bytes)
。
可能是什么问题?虽然 Matlab 向我保证图像的字节没有改变,但我想听听你说 Bitmap.Save
不应该改变图像的字节。
Jpeg 是一种压缩格式。它能够以不同的质量和不同的压缩格式保存。我的猜测是,两个图像的压缩级别设置不同。因为字节在读取时会被解压缩(无论压缩格式如何),所以字节将是相同的,即使它们的压缩方式不同。
想想如果你拿一个文件并用 ZIP 格式压缩它,然后你拿同一个文件用 RAR 格式压缩它。两个文件大小会不一样,但是解压后里面的文件是一样的
您可以阅读有关如何设置图像压缩级别的信息here
我正在从 link 复制代码以便于参考:
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 能够进行可变压缩,在压缩与保真度之间进行权衡。影响大小的因素包括:
具体的 JPEG 格式:Sequential 或 Progressive。 Sequential 在单次扫描中对组件的所有数据进行编码。渐进式在多次扫描中对一个组件进行编码。渐进通常可以产生更大的压缩。但是,有无数的设置适用于渐进式。
抽样。 Jpeg 允许以低于 Y 分量的速率对 Cb 和 Cb 分量进行采样。如果您对每两个 Y(垂直和水平)取一个 Cb 和 Cr 样本,则每 4 个 Y 样本将获得 1 个 Cb 和 CR 样本。这将要压缩的数据量从 12 减半减少到 6。
量化table秒。量化table选择是JPEG压缩设置的主要形式。许多编码器将其隐藏在 "quality" 设置后面。
霍夫曼 tables。一些编码器使用预定义的 Huffman tables。如果编码器生成针对特定图像优化的 Huffman table(更慢且工作量更大),您可以获得更好的压缩。
除非您使用与原始文件相同的设置重新压缩,否则您将获得不同的输出大小。即使您使用相同的设置,由于四舍五入,您通常会得到不同的值:JPEG 使用四舍五入为整数的浮点计算。