2009-09-27 29 views
53

Tôi đã tạo một ứng dụng C# nhỏ để tạo hình ảnh ở định dạng .jpg.Chất lượng của JPG đã lưu trong C#

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

Hình ảnh được tạo thành công. Tôi nhập một pic gốc, làm một số công cụ với nó và lưu nó. Chất lượng của pic mới này tuy nhiên, thấp hơn so với bản gốc.

Có cách nào để đặt chất lượng mong muốn không?

Trả lời

71

Ví dụ mã sau đây minh họa cách tạo EncoderParameter bằng cách sử dụng hàm tạo EncoderParameter. Để chạy ví dụ này, hãy dán mã và gọi phương thức VaryQualityLevel.

Ví dụ này yêu cầu tệp hình ảnh có tên TestPhoto.jpg có tại 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; 
} 

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

+2

đó làm việc. Có vẻ như không có tất cả điều này, chất lượng tiêu chuẩn của 50L được sử dụng. – KdgDev

+0

Bạn có lỗi đánh máy. jgpEncoder khi bạn có nghĩa là jpgEncoder;) –

+0

EncoderParameter có thể sử dụng tài nguyên không được quản lý và phải được xử lý. Tài liệu Msdn hơi thiếu về chủ đề này. Nó sẽ cho biết mảng 'Param' được khởi tạo với các phần tử null (do đó không có gì để vứt bỏ trước khi gán đầu tiên cho mỗi phần tử) và' EncoderParameters' hủy bỏ các tham số hiện tại của nó trên việc loại bỏ nó. –

13

Đây là một chủ đề cũ, nhưng tôi đã viết lại Microsoft (theo câu trả lời của Dustin Getz) để trở nên hữu ích hơn - thu nhỏ GetEncoderInfo và tạo phần mở rộng trên Hình ảnh. Dù sao không có gì thực sự mới, nhưng có thể sử dụng:

/// <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

Nếu bạn đang sử dụng .NET Compact Framework, một sự thay thế có thể sử dụng các ví dụ PNG định dạng lossless:

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

Dưới đây là một thậm chí đoạn nhỏ gọn hơn của mã cho tiết kiệm như JPEG với chất lượng cụ thể:

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

Hoặc, nếu 120 nhân vật dòng rộng quá dài cho bạn:

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

Đảm bảo chất lượng là long hoặc bạn sẽ nhận được ArgumentException!

+0

Chuyển ngay vào thư viện mã của tôi cảm ơn bạn rất nhiều! – JustJohn

+0

Ngoài ra, hãy xem [answer bytecode77] (https://stackoverflow.com/a/39493346/199364) cho một phiên bản này sử dụng 'using' để chắc chắn' Dispose' xảy ra ngay lập tức ở cuối. – ToolmakerSteve

4

Sử dụng kiểu GDI + không chữ (https://msdn.microsoft.com/en-us/library/windows/desktop/ms533845(v=vs.85).aspx) các thuộc tính để đặt chất lượng JPEG trông quá tải.

Một cách trực tiếp sẽ trông như thế này:

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

+0

Lưu ý nhỏ: Vì câu hỏi ban đầu là khiếu nại về chất lượng thấp, để giải quyết chất lượng tối đa đó: 'encoder.QualityLevel = 100'. – ToolmakerSteve

3

Câu trả lời wiki cộng đồng, mà được chấp nhận, referrs một ví dụ từ Microsoft.

Tuy nhiên, để tiết kiệm một số bạn thời gian, tôi luộc nó xuống một bản chất và

  • đóng gói nó thành một phương pháp thích hợp
  • thực hiện IDisposable. Tôi chưa thấy using (...) { trong bất kỳ câu trả lời nào khác.Để tránh rò rỉ bộ nhớ, cách tốt nhất là vất bỏ mọi thứ thực hiện 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

Ghi chú nhỏ: "95L" như được hiển thị cho chất lượng là giá trị mặc định tốt vì nó gần với tối đa "100L", nhưng sẽ tiết kiệm được một chút về kích thước tệp, cho hình ảnh rất chi tiết. Tôi thường sử dụng "90L" để "100L" để bảo quản chất lượng hiqh, "70L" đến "85L" cho chất lượng khá, nhưng kích thước tệp hợp lý hơn. Nó cũng phụ thuộc vào việc bạn đang làm "chỉnh sửa lặp lại" của một tập tin. Nếu vậy, hãy sử dụng "100L" cho đến lần chỉnh sửa cuối cùng (hoặc chỉnh sửa trong .png để không bị mất), sau đó thực hiện lưu cuối cùng với bất kỳ chất lượng nào bạn cần. – ToolmakerSteve

Các vấn đề liên quan