在 C# 中保存的 JPG 的质量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1484759/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 17:58:54  来源:igfitidea点击:

Quality of a saved JPG in C#

c#image-processing

提问by KdgDev

I made a small C# app to create an image in .jpg format.

我制作了一个小型 C# 应用程序来创建 .jpg 格式的图像。

pictureBox.Image.Save(name,ImageFormat.Jpeg);

The image is succesfully created. I input an original pic, do some stuff with it and save it. The quality of this new pic however, is lower than that of the original.

图像已成功创建。我输入了一张原始图片,用它做一些事情并保存它。然而,这张新照片的质量低于原始照片。

Is there any way to set the desired quality?

有没有办法设置所需的质量?

采纳答案by Dustin Getz

The following code example demonstrates how to create a EncoderParameter using the EncoderParameter constructor. To run this example, paste the code and call the VaryQualityLevelmethod.

下面的代码示例演示如何使用 EncoderParameter 构造函数创建 EncoderParameter。要运行此示例,请粘贴代码并调用该VaryQualityLevel方法。

This example requires an image file named TestPhoto.jpg located at c:.

此示例需要位于 c: 的名为 TestPhoto.jpg 的图像文件。

private void VaryQualityLevel()
{
    // Get a bitmap.
    Bitmap bmp1 = new Bitmap(@"c:\TestPhoto.jpg");
    ImageCodecInfo jgpEncoder = 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", jgpEncoder, 
        myEncoderParameters);

    myEncoderParameter = new EncoderParameter(myEncoder, 100L);
    myEncoderParameters.Param[0] = myEncoderParameter;
    bmp1.Save(@"c:\TestPhotoQualityHundred.jpg", jgpEncoder, 
        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", jgpEncoder, 
        myEncoderParameters);

}

private ImageCodecInfo GetEncoder(ImageFormat format)
{
    ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
    foreach (ImageCodecInfo codec in codecs)
    {
        if (codec.FormatID == format.Guid)
        {
            return codec;
        }
    }
    return null;
}

Ref: http://msdn.microsoft.com/en-us/library/system.drawing.imaging.encoderparameter.aspx

参考:http: //msdn.microsoft.com/en-us/library/system.drawing.imaging.encoderparameter.aspx

回答by JoshJordan

Check out MSDN's article on how to set JPEG Compression level.

查看 MSDN 关于如何设置 JPEG 压缩级别的文章。

You need to use the other Save() overload that takes an ImageEncoder and its parameters.

您需要使用带有 ImageEncoder 及其参数的其他 Save() 重载。

回答by Wolf5370

This is an old thread, but I have rewritten the Microsoft (as per Dustin Getz answer) to be a little more useful - shrinking GetEncoderInfo and making an extension on Image. Anyway nothing really new, but may be of use:

这是一个旧线程,但我已经重写了 Microsoft(根据 Dustin Getz 的回答)以使其更有用 - 缩小 GetEncoderInfo 并在 Image 上进行扩展。无论如何,没有什么新东西,但可能有用:

    /// <summary>
    /// Retrieves the Encoder Information for a given MimeType
    /// </summary>
    /// <param name="mimeType">String: Mimetype</param>
    /// <returns>ImageCodecInfo: Mime info or null if not found</returns>
    private static ImageCodecInfo GetEncoderInfo(String mimeType)
    {
        var encoders = ImageCodecInfo.GetImageEncoders();
        return encoders.FirstOrDefault( t => t.MimeType == mimeType );
    }

    /// <summary>
    /// Save an Image as a JPeg with a given compression
    ///  Note: Filename suffix will not affect mime type which will be Jpeg.
    /// </summary>
    /// <param name="image">Image: Image to save</param>
    /// <param name="fileName">String: File name to save the image as. Note: suffix will not affect mime type which will be Jpeg.</param>
    /// <param name="compression">Long: Value between 0 and 100.</param>
    private static void SaveJpegWithCompressionSetting(Image image, string fileName, long compression)
    {
        var eps = new EncoderParameters(1);
        eps.Param[0] = new EncoderParameter(Encoder.Quality, compression);
        var ici = GetEncoderInfo("image/jpeg");
        image.Save(fileName, ici, eps);
    }

    /// <summary>
    /// Save an Image as a JPeg with a given compression
    /// Note: Filename suffix will not affect mime type which will be Jpeg.
    /// </summary>
    /// <param name="image">Image: This image</param>
    /// <param name="fileName">String: File name to save the image as. Note: suffix will not affect mime type which will be Jpeg.</param>
    /// <param name="compression">Long: Value between 0 and 100.</param>
    public static void SaveJpegWithCompression(this Image image, string fileName, long compression)
    {
        SaveJpegWithCompressionSetting( image, fileName, compression );
    }

回答by AlainD

If you are using the .NET Compact Framework, an alternative might be to use the PNG lossless format ie:

如果您使用的是 .NET Compact Framework,另一种可能是使用 PNG 无损格式,即:

image.Save(filename, ImageFormat.Png);

回答by Roman Starkov

Here's an even more compact chunk of code for saving as JPEG with a specific quality:

这是一个更紧凑的代码块,用于保存为具有特定质量的 JPEG:

var encoder = ImageCodecInfo.GetImageEncoders().First(c => c.FormatID == ImageFormat.Jpeg.Guid);
var encParams = new EncoderParameters() { Param = new[] { new EncoderParameter(Encoder.Quality, 90L) } };
image.Save(path, encoder, encParams);

Or, if 120 character wide lines are too long for you:

或者,如果 120 个字符宽的行对您来说太长:

var encoder = ImageCodecInfo.GetImageEncoders()
                            .First(c => c.FormatID == ImageFormat.Jpeg.Guid);
var encParams = new EncoderParameters(1);
encParams.Param[0] = new EncoderParameter(Encoder.Quality, 90L);
image.Save(path, encoder, encParams);

Make sure the quality is a longor you will get an ArgumentException!

确保质量是一个,long否则你会得到一个ArgumentException

回答by epox

Using typeless GDI+ style ( https://msdn.microsoft.com/en-us/library/windows/desktop/ms533845(v=vs.85).aspx) attributes for setting JPEG Quality looks overkilling.

使用无类型 GDI+ 样式 ( https://msdn.microsoft.com/en-us/library/windows/desktop/ms533845(v=vs.85).aspx) 属性设置 JPEG 质量看起来有些过分。

A direct way should look like this:

直接的方式应该是这样的:

FileStream stream = new FileStream("new.jpg", FileMode.Create);
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.QualityLevel = 100;   // "100" for maximum quality (largest file size).
encoder.Frames.Add(BitmapFrame.Create(image));
encoder.Save(stream);

Ref: https://msdn.microsoft.com/en-us/library/system.windows.media.imaging.jpegbitmapencoder.rotation(v=vs.110).aspx#Anchor_2

参考:https: //msdn.microsoft.com/en-us/library/system.windows.media.imaging.jpegbitmapencoder.rotation(v=vs.110).aspx# Anchor_2

回答by bytecode77

The community wiki answer, which is accepted, referrs to an example from Microsoft.

被接受的社区 wiki 答案引用了 Microsoft 的一个示例。

However, in order to save some of you time, I boiled it down to an essence and

然而,为了节省你们中的一些时间,我把它归结为一个精华和

  • Packed it into a proper method
  • Implemented IDisposable. I haven't seen using (...) {in any other answers. In order to avoid memory leakage, it is best practice to dispose everything that implements IDisposable.
  • 将其打包成适当的方法
  • 实施IDisposable。我没有using (...) {在任何其他答案中看到。为了避免内存泄漏,最好将所有实现IDisposable.


public static void SaveJpeg(string path, Bitmap image)
{
    SaveJpeg(path, image, 95L);
}
public static void SaveJpeg(string path, Bitmap image, long quality)
{
    using (EncoderParameters encoderParameters = new EncoderParameters(1))
    using (EncoderParameter encoderParameter = new EncoderParameter(Encoder.Quality, quality))
    {
        ImageCodecInfo codecInfo = ImageCodecInfo.GetImageDecoders().First(codec => codec.FormatID == ImageFormat.Jpeg.Guid);
        encoderParameters.Param[0] = encoderParameter;
        image.Save(path, codecInfo, encoderParameters);
    }
}