【问题标题】:Reduce image quality/size without loading into memory?在不加载到内存的情况下降低图像质量/大小?
【发布时间】:2013-04-12 15:23:04
【问题描述】:

我完全停留在图像大小调整上,因为我得到了OutOfMemoryException 使用的图像大小调整的典型示例,这些示例可以在许多以 OOM 为特色的问题中找到。

我什至尝试了可以​​在 Nuget 上找到的 DynamicImage,这也引发了OutOfMemoryException

谁能告诉我如何在 C# 中降低图像的质量/大小,而不将其加载到内存中?

编辑:我想要 c# equivalent 这个,如果有的话?

编辑:我放弃了调整大小的典型方法,因为我无法避免在旧服务器上运行的实时站点上出现 OutOfMemoryExceptions。

进一步编辑:我的服务器操作系统是 Microsoft Server 2003 Standard Edition

我可以发布我的代码示例,但我正在尝试找到解决 OutOfMemoryExceptions 的方法。

public static void ResizeImage(string imagePath, int imageWidth, int imageHeight, bool upscaleImage) {
      using (Image image = Image.FromFile(imagePath, false)) {
        int width = image.Width;
        int height = image.Height;
        if (width > imageWidth || height > imageHeight || upscaleImage) {

          image.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipX);
          image.RotateFlip(System.Drawing.RotateFlipType.Rotate180FlipX);

          float ratio = 0;
          if (width > height) {
            ratio = (float)width / (float)height;
            width = imageWidth;
            height = Convert.ToInt32(Math.Round((float)width / ratio));
          }
          else {
            ratio = (float)height / (float)width;
            height = imageHeight;
            width = Convert.ToInt32(Math.Round((float)height / ratio));
          }

          using (Bitmap bitmap = new Bitmap(width, height)) {
            bitmap.SetResolution(image.HorizontalResolution, image.VerticalResolution);
            using (Graphics graphic = Graphics.FromImage(bitmap)) {

              graphic.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
              graphic.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
              graphic.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
              graphic.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
              graphic.DrawImage(image, 0, 0, width, height);

              string extension = ".jpg"; // Path.GetExtension(originalFilePath);

              using (EncoderParameters encoderParameters = new EncoderParameters(1)) {
                encoderParameters.Param[0] = new EncoderParameter(Encoder.Quality, 100L);
                using (MemoryStream imageMemoryStream = new MemoryStream()) {
                  bitmap.Save(imageMemoryStream, GetImageCodec(extension), encoderParameters);
                  using (Image result = Image.FromStream(imageMemoryStream, true, false)) {
                    string newFullPathName = //path;
                    result.Save(newFullPathName);
                  }
                }
              }
            }
          }
        }
      }
        }

我也尝试了这段代码,因为我希望 GetThumbnailImage 会降低我的图片质量/大小,但这也会引发 OOM 异常:

viewModel.File.SaveAs(path);
        Image image = Image.FromFile(path);
        Image thumbnail = image.GetThumbnailImage(600, 600, null, new IntPtr());
        image.Dispose();
        File.Delete(path);
        thumbnail.Save(path);
        thumbnail.Dispose();

同样,我的两个代码示例都适用于我的本地机器,所以我不想在代码中查找错误/修复,因为它们应该没问题。我正在寻找任何解决方案来避免 OOM 异常,我想在不将图像加载到内存的情况下以某种方式减小 fize 大小,但任何可以帮助我的替代想法将不胜感激。

【问题讨论】:

  • 请发布您尝试过的内容。我可能只是你的代码中的一个错误。
  • 我已经解释过我什至尝试过 Nuget 包,但潜在的错误仍然存​​在。我相信问题出在托管我的网站的服务器上,因为在我自己的机器上运行时我没有得到 OutOfMemoryExceptions。但是我的问题是我是否可以在不将图像加载到内存的情况下减小图像的大小,我想知道它是否可能以及如果可以的话从哪里开始。
  • [必需,FileExtensionsAttribute("jpg|png|gif|jpeg")] public HttpPostedFileBase File { get;放; }
  • 我非常怀疑问题出在图像大小上,很可能您没有正确处理对象导致内存不足异常。您使用的图像的文件大小是多少?如果您按照@ic3b3rg 已经建议的方式发布您的代码,最好的办法是。只是想清楚一点,如果不加载到内存中,就无法调整图像大小。
  • 是的 - 由于服务器设置不同,可能会在 prod 中收到 OOM,但在 dev 中不会收到。我想到了一些 - 服务器上更少的物理 RAM、x86 与 x64、碎片、processModel 或 IIS 限制(不确定这是 OOM 还是只是重新启动)等等。

标签: c# image out-of-memory


【解决方案1】:

您可以尝试通过command line.NET bindings 使用ImageMagick。 ImageMagick 有 some options 在读取文件时调整大小,这应该会减少内存消耗。

【讨论】:

  • 知道它们是什么选项吗?
  • @Tyler - 尝试“读取调整大小”选项
【解决方案2】:

您使用的“图像”可能不是受支持的格式或已损坏。

【讨论】:

  • 代码在本地运行良好,但在我的实时站点上失败,在旧服务器上,用相同的图片测试
  • 旧服务器运行的是什么版本的 Windows?
  • Microsoft Server 2003 标准版
【解决方案3】:

我没有提到我继承了没有正确处理图像的遗留代码,因为我认为它在修复后并不相关。奇怪的是,重新启动网站和 AppPool 后,我能够再次上传图片而没有出现 OutOfMemoryExcepiton。我很难理解为什么会发生这种情况,因为我已经更改了代码以正确处理图像并且已经进行了几次部署,所以我希望这能从内存中清除任何未处理的图像?图片调整大小和上传的所有代码都在一个静态类中,我相信 GC.collect() 不适用于静态变量?

我的理论是,未处理的图像已经在内存中累积,并且即使我重新部署到该站点时仍然存在,因为这是我可以得出的唯一结论,因为在重新启动应用程序池后代码再次开始工作。

我会删除我的问题,但现在已经回答了,如果有人可以帮助解释这里发生了什么,我很乐意重新分配答案。

【讨论】:

    猜你喜欢
    • 2014-04-09
    • 1970-01-01
    • 2016-04-18
    • 1970-01-01
    • 2010-12-05
    • 2011-08-26
    • 2020-11-24
    • 2010-12-03
    • 1970-01-01
    相关资源
    最近更新 更多