在C#中调整图片大小

5

我正在用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();

1
首先:我认为工作代码应该发布在代码审查论坛上;这里是http://codereview.stackexchange.com/。其次:你为什么要在foreach循环内部处理和清理数组?也许你应该重复使用现有对象,并在循环结束后清理所有内容。 - stackunderflow
当然 - 我做了那个,但它显示了内存异常! - NESHOM
@Guffa 的解决方案怎么样? - stackunderflow
@stackunderflow:如果以这种方式创建位图,则重复使用它们是行不通的。如果您想要重复使用它,您需要将加载的位图绘制到现有位图上,并且所有已加载的位图仍然必须被处理。 - Guffa
1个回答

6

不要分两步复制位图,改为一步。这样可以大大减少内存使用量,因为您不必同时在内存中拥有两个原始图像的副本。

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秒)。我已经编辑了我的主贴,包含了修改和更新后的代码。再次感谢您! :) - NESHOM
@M0HS3N:你不应该将dispose移出循环,这会导致除了最后一个之外,所有创建的位图都没有被处理。 - Guffa
对不起 @Guffa,有一点我没明白,如果 bmpDist 将在循环内使用,为什么我们每次都要处理并重新创建它。我们可以重用它、重新分配它,然后在循环结束后再处理它,这与值类型和引用类型有关吗? - stackunderflow
1
@stackunderflow:你可以重复使用它,但这不是你正在做的事情。当你执行bmpDest = new Bitmap(...)时,你并没有将图像放入现有对象中,而是创建了一个新对象,并且该对象的引用替换了变量中的任何现有引用。如果你想重复使用位图,则需要在循环之前创建一个位图,并在循环中使用Graphics对象在该位图上绘制。 - Guffa
好的解释!我还有一个问题:如果我重复使用bmpDest并让GC来处理它,这样做是否是不好的实践?? - stackunderflow
1
@stackunderflow:是的,那是一种不好的做法。已释放的对象对于垃圾回收器来说非常容易处理,但如果您不释放对象,则这是一种资源昂贵的过程。在可以收集它之前,必须完成它的终结,经历一个或多个收集过程,通常意味着将其移动到下一个堆代中,这将使整个对象从一个内存区域移动到另一个内存区域。 - Guffa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接