在 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
Quality of a saved JPG in C#
提问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 VaryQualityLevel
method.
下面的代码示例演示如何使用 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 long
or 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);
参考: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 seenusing (...) {
in any other answers. In order to avoid memory leakage, it is best practice to dispose everything that implementsIDisposable
.
- 将其打包成适当的方法
- 实施
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);
}
}