【问题标题】:Resizing image in C#在 C# 中调整图像大小
【发布时间】:2014-07-15 00:41:04
【问题描述】:

我正在编写代码以在 C# 中调整 JPG 图像的大小。我的代码需要大约 6 秒来调整 20 张 JPG 图像的大小。我想知道在 C# 中是否有更快的方法来做到这一点?任何改善这一点的建议都值得赞赏!

这是我的代码:

Bitmap bmpOrig, bmpDest, bmpOrigCopy;
foreach (string strJPGImagePath in strarrFileList)
{
bmpOrig = new Bitmap(strJPGImagePath);
bmpOrigCopy = new Bitmap(bmpOrig);
bmpOrig.Dispose();
File.Delete(strJPGImagePath);

bmpDest = new Bitmap(bmpOrigCopy, new Size(100, 200));
bmpDest.Save(strJPGImagePath, jgpEncoder, myEncoderParameters);

bmpOrigCopy.Dispose();
bmpDest.Dispose();
}

感谢@Guffa 的解决方案。我将 dispose() 移出 foreach 循环。更新快的代码是:

        Bitmap bmpDest = new Bitmap(1, 1);
        foreach (string strJPGImagePath in strarrFileList)
        {
            using (Bitmap bmpOrig = new Bitmap(strJPGImagePath))
            { 
                bmpDest = new Bitmap(bmpOrig, new Size(100, 200)); 
            }
            bmpDest.Save(strJPGImagePath, jgpEncoder, myEncoderParameters);
        }
        bmpDest.Dispose();

【问题讨论】:

  • 第一:我认为工作代码应该发布在代码审查论坛上;这里codereview.stackexchange.com。第二:你为什么要处理和清理前循环内的阵列?可能你应该重用现有对象并在循环完成后清理所有内容
  • 当然 - 我这样做了,但它显示我内存不足异常!
  • @Guffa 解决方案怎么样?
  • @stackunderflow:以这种方式创建位图时,重用位图是行不通的。如果你想重用它,你需要将加载的位图绘制到现有的位图上,并且所有加载的位图仍然必须被释放。

标签: c# bitmap resize


【解决方案1】:

不要分两步复制位图,而是一步完成。这样可以大大减少内存使用量,因为内存中没有两个原始图像的副本。

foreach (string strJPGImagePath in strarrFileList) {
  Bitmap bmpDest;
  using(Bitmap bmpOrig = new Bitmap(strJPGImagePath)) {
    bmpDest = new Bitmap(bmpOrig, new Size(100, 200));
  }
  bmpDest.Save(strJPGImagePath, jgpEncoder, myEncoderParameters);
  bmpDest.Dispose();
}

【讨论】:

  • 哇,这真是太棒了,让代码快了两倍以上(2.4 秒)!我做了一个小改动,它甚至快了大约 100 毫秒(2.3 秒)。我编辑了我的主要帖子以包含编辑和更新的代码。再次感谢你! :)
  • @M0HS3N:您应该不将 dispose 移出循环,这将使您创建的所有位图都未处理,除了最后一个。
  • 对不起@Guffa,有一点我不明白,如果bmpDist 要在循环中使用,我们为什么要处理它并每次都重新创建它。我们可以重用它重新分配它然后在循环之后将它处理掉,它与值类型和ref ttype问题有关吗?
  • @stackunderflow:你可以重用它,但这不是你正在做的。当您执行bmpDest = new Bitmap(...) 时,您不会将图像放入现有对象中,而是创建一个新对象,并且对该对象的引用将替换变量中的任何现有引用。如果您想重用位图,则需要在循环之前创建一个,并使用Graphics 对象在循环中的该位图上进行绘制。
  • @stackunderflow:是的,这是不好的做法。 GC 很容易处理已处置的对象,但如果您不处置该对象,这将是一个资源昂贵的过程。它必须在被收集之前完成,在一个或多个收集中存活下来,这通常意味着它被移动到下一个堆代,这会将整个对象从一个内存区域移动到另一个内存区域。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-18
  • 2012-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多