使用.NET加载的JPEG图像如何以相同质量保存?

14

我有一台佳能数码相机,将其设置为以超精细质量拍摄,并输出大小为3兆的.jpg文件。如果我在ASP.NET中这样加载它(这对于更改其dpi分辨率、裁剪或其他操作很有用)。

imgPicture = Image.FromFile(Config.WorkDirectory + this.TempPhotoName);
bmpPicture = new Bitmap(imgPicture);

然后我像这样再次保存它:

bmpModified.Save(Config.WorkDirectory + this.TempPhotoName,System.Drawing.Imaging.ImageFormat.Jpeg);

它输出的JPG文件大小仅为约700KB左右。存在一定的质量损失。

我也尝试过以下方式保存:

bmpPicture.Save(Config.WorkDirectory + this.TempPhotoName, codecJpeg, encparams);

codecJpeg是什么

ImageCodecInfo codecJpeg = this.getEncoderInfo("image/jpeg");


    private ImageCodecInfo getEncoderInfo(string mimeType)
    {
        // Get image codecs for all image formats
        ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders();

        // Find the correct image codec
        for (int i = 0; i < codecs.Length; i++)
            if (codecs[i].MimeType == mimeType)
                return codecs[i];
        return null;
    }

以及encparams:

EncoderParameters encparams = new EncoderParameters(1);
encparams.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 97L);

通过这种方式,尺寸(我猜品质也是如此)得到保持,但是我手动输入了品质。

我想问:

有没有一种方法可以在不硬编码品质值的情况下保存与加载时相同品质的图像?

提前感谢您。

3个回答

5
所以看起来您知道如何设置质量,您只需要知道如何从原始图像中获取质量?
如果质量在元数据中,则我认为Image.PropertyItems可能会有所帮助。(我不知道JPEG编码器中是否甚至有一个标准比例尺度的质量。)
编辑:我刚刚检查过,我下载的JPEG没有任何关于质量的标签。
其中一种选择可能是计算文件应该以大约相同的质量结束的大小,然后保存它多次,进行二进制搜索以确定最适当的质量。这很糟糕,但也许会行得通。
我有一种隐隐约约的感觉,就是可能没有一种方法可以仅保留原始质量设置,尽管我没有非常好的理由怀疑这一点...

2
设置PropertyItems并重新保存会导致质量损失,因为图像将被重新编码。在此处阅读更多信息:https://dev59.com/73NA5IYBdhLWcg3wPbSe - arbiter
有一个称为PropertyTagJPEGQuality的属性元素可用于获取JPEG质量,但它被标记为Adobe Photoshop的私有标签,因此我不知道它是否由相机填充。无论如何,将JPEG以相同的质量值存储没有太大意义,因为会存在质量损失。 - arbiter
1
我的观点是,我使用的JPEG文件中没有填充它 :) 但我仍然不同意你的基本观点:我怀疑通常情况下你会想要存储与原始图像具有相同质量值的JPEG文件,即使你将失去一些质量。原始质量值显示了你对质量的关注程度,新的质量值也是如此。 - Jon Skeet
3
不,你不会得到70%的70% - 这不是它的工作原理。不要忘记,当你重新加载它时,你将重新加载自然比完美原始数据更容易压缩的数据 - 所以你可以再次用“中等”质量进行压缩,而不会像从完美原始开始一样丢失那么多数据。 - Jon Skeet
1
微软在http://support.microsoft.com/kb/324790/en-us上指出,JPEG文件中不存储质量因素,但如果它们是“通常”的量化表,则可以从量化表中推断出来。他们只提供了原则和指向那些“通常”量化表的链接。 - Frédéric
显示剩余2条评论

1

阅读此处如何在不重新编码图像的情况下保存图像:如何:使用元数据重新编码JPEG图像

然而,如果您进行裁剪或其他图像操作,则无法避免质量损失(从技术上讲,如果您使用16的倍数边界工作,则可以进行无损裁剪,但据我所知,这不能使用 .net 中可用的库完成)。


0

你必须使用额外的参数来告诉GDI+检测颜色方案。

例如:

using (var img = Image.FromStream(fileupload.InputStream, true,true))
{
    img.Save(fileOnDisk, ImageFormat.Jpeg);
}

using (var img = Image.FromFile("yourimage", true))
{
    img.Save(fileOnDisk, ImageFormat.Jpeg);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接