【问题标题】:Bmp to jpg/png in C#C#中的Bmp到jpg/png
【发布时间】:2010-09-07 16:28:19
【问题描述】:

有什么方法可以将 bmp 图像转换为 jpg/png 而不会丢失 C# 中的质量?使用 Image 类,我们可以将 bmp 转换为 jpg,但输出图像的质量很差。我们能否获得与使用最高质量的 Photoshop 转换为 jpg 的图像一样好的质量水平?

【问题讨论】:

    标签: c# image-manipulation


    【解决方案1】:

    我正在开发一个费用报告应用程序,当从位图对象保存时,我对 JPG(和 PNG)的默认质量设置非常满意。

    https://msdn.microsoft.com/en-us/library/9t4syfhh%28v=vs.110%29.aspx

    Bitmap finalBitmap = ....; //from disk or whatever
    finalBitmap.Save(xpsFileName + ".final.jpg", ImageFormat.Jpeg);
    finalBitmap.Save(xpsFileName + ".final.png", ImageFormat.Png);
    

    我使用的是 .NET 4.6...也许在后续框架版本中质量有所提高。

    【讨论】:

      【解决方案2】:
      public static class BitmapExtensions
      {
          public static void SaveJPG100(this Bitmap bmp, string filename)
          {            
              EncoderParameters encoderParameters = new EncoderParameters(1);
              encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
              bmp.Save(filename, GetEncoder(ImageFormat.Jpeg), encoderParameters);
          }
      
          public static void SaveJPG100(this Bitmap bmp, Stream stream)
          {
              EncoderParameters encoderParameters = new EncoderParameters(1);
              encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
              bmp.Save(stream, GetEncoder(ImageFormat.Jpeg), encoderParameters);
          }
      
          public static ImageCodecInfo GetEncoder(ImageFormat format)
          {
              ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
      
              foreach (ImageCodecInfo codec in codecs)
              {
                  if (codec.FormatID == format.Guid)
                  {
                      return codec;
                  }
              }
      
              return null;
          }
      }
      

      【讨论】:

      • 一行中GetEncoder的等效表达式:return ImageCodecInfo.GetImageDecoders().Where(x => x.FormatID == format.Guid).FirstOrDefault();
      • 或者更短的return ImageCodecInfo.GetImageEncoders().FirstOrDefault(x => x.FormatID == ImageFormat.Jpeg.Guid);。
      【解决方案3】:

      jestro 提供的 BitmapExtensions 很棒,我使用了它们。但是想显示更正的版本 - 适用于 Image 父类,我认为这更方便,并提供了一种提供质量的方法:

      public static class ImageExtensions
      {
          public static void SaveJpeg(this Image img, string filePath, long quality)
          {
              var encoderParameters = new EncoderParameters(1);
              encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, quality);
              img.Save(filePath, GetEncoder(ImageFormat.Jpeg), encoderParameters);
          }
      
          public static void SaveJpeg(this Image img, Stream stream, long quality)
          {
              var encoderParameters = new EncoderParameters(1);
              encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, quality);
              img.Save(stream, GetEncoder(ImageFormat.Jpeg), encoderParameters);
          }
      
          static ImageCodecInfo GetEncoder(ImageFormat format)
          {
              ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
              return codecs.Single(codec => codec.FormatID == format.Guid);
          }
      }
      

      【讨论】:

        【解决方案4】:

        只想说JPEG本质上是一种有损格式。所以理论上,即使在最高设置下,你也会有一些信息丢失,但这在很大程度上取决于图像。但 png 是无损的。

        【讨论】:

          【解决方案5】:
          var qualityEncoder = Encoder.Quality;
          var quality = (long)<desired quality>;
          var ratio = new EncoderParameter(qualityEncoder, quality );
          var codecParams = new EncoderParameters(1);
          codecParams.Param[0] = ratio;
          var jpegCodecInfo = <one of the codec infos from ImageCodecInfo.GetImageEncoders() with mime type = "image/jpeg">;
          bmp.Save(fileName, jpegCodecInfo, codecParams); // Save to JPG
          

          【讨论】:

          • 这里应该没有一些using语句吧?我注意到 EncoderParameter 是 IDisposable,但我对一次性模式的掌握还不够,无法确定它们是必需的。
          • 是的,应该有一些 using 语句。上面的代码是可以做什么的示例,而不是应该使用的示例。
          【解决方案6】:

          从根本上说,您将无法保持相同的质量,因为 jpg(据我所知)即使在尽可能高的质量设置下也总是有损。

          如果位精度真的很重要,请考虑使用 png,它有一些无损模式。

          【讨论】:

            【解决方案7】:

            你可以试试:

            Bitmap.InterpolationMode = InterpolationMode.HighQualityBicubic;
            

            和

            Bitmap.CompositingQuality = CompositingQuality.HighQuality;
            

            这确实保持了相当高的质量,但不是最高的。

            【讨论】:

            • 位图没有这样的属性。它们必须应用于图形和图像修改期间,例如调整大小。
            猜你喜欢
            • 2012-04-03
            • 2012-12-26
            • 2012-01-24
            • 1970-01-01
            • 2018-08-27
            • 2017-09-12
            • 1970-01-01
            • 2010-09-29
            • 2012-11-25
            相关资源
            最近更新 更多