C # 中保存 JPG 的质量

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

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

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

有没有什么办法来确定你想要的质量?

84365 次浏览

下面的代码示例演示如何使用 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

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

您需要使用接受 ImageEncoder 及其参数的另一个 Save ()重载。

这是一个老线程,但是我已经重写了微软(根据 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 );
}

如果您正在使用.NET CompactFramework,一个替代方案可能是使用 PNG 无损格式,即:

image.Save(filename, ImageFormat.Png);

下面是一段更加紧凑的代码,可以保存为具有特定质量的 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

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

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

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

社区 wiki 的答案是可以接受的,它引用了微软的一个例子。

但是,为了节省你们一些时间,我把它浓缩成一个精华和

  • 用适当的方法包装
  • 实施 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);
}
}