从流中保存 JPG 文件会增加 C# 中的大小
Saving JPG file from stream increases size in C#
一些背景知识:
我正在使用 WPF 编写一个条码图像扫描仪桌面应用程序,它可以从文件位置(以前扫描的图像)获取输入,也可以直接从扫描仪(使用 NTWAIN)获取输入。在这两种情况下,我都创建或获取流。
现在,当我从流中创建一个新位图并使用编码器将其保存为 JPEG 文件时
using (var bmp = Image.FromStream(rawStream))
{
EncoderParameter ratio = new EncoderParameter(Encoder.Quality, 100L);
EncoderParameter depth = new EncoderParameter(Encoder.ColorDepth, 8L);
EncoderParameters codecParams = new EncoderParameters(2);
codecParams.Param[0] = ratio;
codecParams.Param[1] = depth;
ImageCodecInfo jpegCodecInfo = ImageCodecInfo.GetImageEncoders().FirstOrDefault(x => x.FormatID == ImageFormat.Jpeg.Guid);
bmp.Save(file.FileFullPath, jpegCodecInfo, codecParams); // Save to JPG
}
或内置
bmp.Save(file.FileFullPath, ImageFormat.Jpeg);
我倾向于以更大的文件大小结束。当然,情况并非总是如此,但当我将一个小的黑白 tiff 文件加载到内存中并编码为 jpg 时,情况确实如此。
我对图像处理的知识很初级,但我认为这是因为 jpg 文件以 24 位的颜色深度保存,而 tiff 图像最初存储为 1 位。 (黑白)
无论我做什么,我都无法使 jpg 文件与原始文件的位深度相匹配。
我发现的唯一解决方法是将文件重命名为 "filename.jpg" 并像这样保存
using (Bitmap bmp = new Bitmap(rawStream))
{
Save(file.FileFullPath);
}
但这感觉像是一个不会无限期有效的解决方案(作为附带问题,是否可以简单地将任何 *.bmp 或 *tiff 文件重命名为 *.jpg 并且它仍然有效?)
根据我的初步研究,似乎
bmp.Save()
不支持 jpeg 图像中位深度的编码参数。 "no reason".
的文件从 16kb 增长到 200kb 是可以理解的,我的客户不会高兴。
是否有已知的解决此问题的方法,或者在处理流和图像时我是否遗漏了一些明显的东西?
JPEG 最适合具有多种颜色、阴影和渐变的照片。典型的位深度:8(灰度)或 24(全彩色)。
如果您想要单色(1 位),我建议您再次使用 JPEG,尤其是因为 JPEG 会引入对照片可能无关紧要的编码伪像,但如果您的照片看起来像 "added pepper and salt"原始来源是 1 位。你越压缩它们,它就会越多。
您应该尝试改用 PNG,它没有此类瑕疵,更适合具有锐利边缘的数字源。
您也可以尝试使用智能调整大小算法(例如使用 8 位输出)将 TIFF 缩小 50% 或 75%,该算法会将原件中的微点转换为输出中的小渐变。我很久以前用 1 位 fax/scanner 图像做过,实际上效果很好。但是太久了,仍然没有这些资源。
一些背景知识:
我正在使用 WPF 编写一个条码图像扫描仪桌面应用程序,它可以从文件位置(以前扫描的图像)获取输入,也可以直接从扫描仪(使用 NTWAIN)获取输入。在这两种情况下,我都创建或获取流。
现在,当我从流中创建一个新位图并使用编码器将其保存为 JPEG 文件时
using (var bmp = Image.FromStream(rawStream))
{
EncoderParameter ratio = new EncoderParameter(Encoder.Quality, 100L);
EncoderParameter depth = new EncoderParameter(Encoder.ColorDepth, 8L);
EncoderParameters codecParams = new EncoderParameters(2);
codecParams.Param[0] = ratio;
codecParams.Param[1] = depth;
ImageCodecInfo jpegCodecInfo = ImageCodecInfo.GetImageEncoders().FirstOrDefault(x => x.FormatID == ImageFormat.Jpeg.Guid);
bmp.Save(file.FileFullPath, jpegCodecInfo, codecParams); // Save to JPG
}
或内置
bmp.Save(file.FileFullPath, ImageFormat.Jpeg);
我倾向于以更大的文件大小结束。当然,情况并非总是如此,但当我将一个小的黑白 tiff 文件加载到内存中并编码为 jpg 时,情况确实如此。
我对图像处理的知识很初级,但我认为这是因为 jpg 文件以 24 位的颜色深度保存,而 tiff 图像最初存储为 1 位。 (黑白)
无论我做什么,我都无法使 jpg 文件与原始文件的位深度相匹配。
我发现的唯一解决方法是将文件重命名为 "filename.jpg" 并像这样保存
using (Bitmap bmp = new Bitmap(rawStream))
{
Save(file.FileFullPath);
}
但这感觉像是一个不会无限期有效的解决方案(作为附带问题,是否可以简单地将任何 *.bmp 或 *tiff 文件重命名为 *.jpg 并且它仍然有效?)
根据我的初步研究,似乎
bmp.Save()
不支持 jpeg 图像中位深度的编码参数。 "no reason".
的文件从 16kb 增长到 200kb 是可以理解的,我的客户不会高兴。是否有已知的解决此问题的方法,或者在处理流和图像时我是否遗漏了一些明显的东西?
JPEG 最适合具有多种颜色、阴影和渐变的照片。典型的位深度:8(灰度)或 24(全彩色)。
如果您想要单色(1 位),我建议您再次使用 JPEG,尤其是因为 JPEG 会引入对照片可能无关紧要的编码伪像,但如果您的照片看起来像 "added pepper and salt"原始来源是 1 位。你越压缩它们,它就会越多。
您应该尝试改用 PNG,它没有此类瑕疵,更适合具有锐利边缘的数字源。
您也可以尝试使用智能调整大小算法(例如使用 8 位输出)将 TIFF 缩小 50% 或 75%,该算法会将原件中的微点转换为输出中的小渐变。我很久以前用 1 位 fax/scanner 图像做过,实际上效果很好。但是太久了,仍然没有这些资源。