2009-09-27 64 views
53

我做了一个小的C#应用​​程序来创建.jpg格式的图像。在C中保存JPG的质量#

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

图像被成功创建。我输入一张原始图片,用它做一些东西并保存。然而,这张新照片的质量比原来的低。

有没有什么方法可以设置所需的质量?

回答

71

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

这个例子需要一个名为TestPhoto.jpg的图像文件位于c :.

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; 
} 

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

+2

工程。看起来没有这些,使用50L的标准质量。 – KdgDev 2009-09-28 00:39:06

+0

你有一个错字。 jgpEncoder当你的意思是jpgEncoder;) – 2013-12-10 13:50:44

+0

EncoderParameter可能会使用非托管资源,必须予以处置。 Msdn文档在这个问题上有点缺乏。它应该声明'Param'数组是用空元素初始化的(因此在第一次赋值给每个元素之前不需要处理),并且'EncoderParameters'将它的当前参数放置在自己的dispose中。 – 2014-07-11 10:34:57

13

这是一个古老的线程,但我已经重写了微软(按达斯汀·盖茨的回答)是一个小更实用 - 收缩GetEncoderInfo,使图像上的延伸。 反正没有什么新意,但可能是有用的:

/// <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); 
    } 
2

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

image.Save(filename, ImageFormat.Png); 
30

这里是一个甚至代码更紧凑块用于为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); 

或者,如果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); 

确保质量是long或者您将得到ArgumentException

+0

进入我的代码库非常感谢你! – JustJohn 2017-03-26 20:24:20

+0

另请参见[bytecode77的回答](https://stackoverflow.com/a/39493346/199364),该版本使用'using'确保'Dispose'在最后立即执行。 – ToolmakerSteve 2017-08-05 11:18:36

4

使用无类型的GDI +风格(https://msdn.microsoft.com/en-us/library/windows/desktop/ms533845(v=vs.85).aspx)属性设置JPEG质量看起来overkilling。

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

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); 

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

+0

小问题:由于原始问题是关于低质量的投诉,因此要解决使用最高质量问题:'encoder.QualityLevel = 100'。 – ToolmakerSteve 2017-08-05 11:14:51

3

社区维基答案,这是公认的,referrs从微软的例子。

然而,为了节省一些你的时候,我煮下来到一个本质和

  • 盒装入适当的方法
  • 实现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); 
    } 
} 
+0

小注:质量所示的“95L”是一个很好的默认值,因为它接近“100L”的最大值,但对于非常详细的图像,它会在文件大小上节省一些。我通常使用“90L”到“100L”来保存质量,“70L”到“85L”质量不错,但文件大小更合理。这也取决于你是否在对文件进行“重复编辑”。如果是这样,请使用“100L”直到上次编辑(或者在.png中编辑为无损),然后以您需要的任何质量进行最终保存。 – ToolmakerSteve 2017-08-05 12:05:45