c# - 在不使用 GDI+/WPF 的情况下,C# 中的快速+高质量图像大小调整算法

标签 c# performance algorithm image resize

我需要在不损失太多质量的情况下调整大量图像的大小。
使用 PresentationFramework (WPF) 非常快,但质量很差。
使用 GDI+,质量很好,但锁定到 UI-Thread -> singleCored。 :-(
是否有一种在一段代码中结合速度和质量的又好又快的算法? ;-)

最佳答案

GDI+(又名 System.Drawing)不需要消息泵,并且可以愉快地在多线程上工作;只有真正的控件可以 - 您甚至可以在控制台应用程序(没有消息泵)中使用 Bitmap

因此,例如,您可以执行以下操作(我已经对此进行了测试):

static void Main(string[] args)
{
    foreach (var file in Directory.GetFiles("C:\\MyImages", "*.jpg"))
    {
        // Spawn threads.
        new Action<string, float>(ResizeImage).BeginInvoke(file, 0.1f, null, null);
    }
    Console.ReadLine();
}

public static void ResizeImage(string filename, float scale)
{
    using (var bitmap = Image.FromFile(filename))
    using (var resized = ResizeBitmap(bitmap, 0.1f, InterpolationMode.HighQualityBicubic))
    {
        var newFile = Path.ChangeExtension(filename, ".thumbnail" + Path.GetExtension(filename));
        if (File.Exists(newFile))
            File.Delete(newFile);
        resized.Save(newFile);
    }
}

public static Bitmap ResizeBitmap(Image source, float scale, InterpolationMode quality)
{
    if (source == null)
        throw new ArgumentNullException("source");

    // Figure out the new size.
    var width = (int)(source.Width * scale);
    var height = (int)(source.Height * scale);

    // Create the new bitmap.
    // Note that Bitmap has a resize constructor, but you can't control the quality.
    var bmp = new Bitmap(width, height);

    using (var g = Graphics.FromImage(bmp))
    {
        g.InterpolationMode = quality;
        g.DrawImage(source, new Rectangle(0, 0, width, height));
        g.Save();
    }

    return bmp;
}

编辑根据this post似乎 System.Drawing 有一个全局锁;特别是对于 DrawImage()(请记住,这不是因为消息泵)。不幸的是,获得多线程访问的唯一方法可能是使用 DirectX/SharpDX并创建启用多线程的设备;创建一些后备缓冲区并在那里调整大小 - 然后您可以调整缩小/最大化过滤器。我不确定您是否可以从 DirectX 中的多个线程 Draw() - 但即使您不能,您也应该能够从中获得更多的吞吐量(即使在单个线程上)。

关于c# - 在不使用 GDI+/WPF 的情况下,C# 中的快速+高质量图像大小调整算法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7230687/

相关文章:

c# - 带参数的本地化错误消息

c# - 什么时候使用 [MTAThread]?

asp.net - 如何防止IIS编译网站?

k个元素的计数序列

algorithm - 字数 : how inefficient is McIlroy's solution?

c# - C# 应用程序中 C++ 模块的探查器

c# - 将应用程序中的所有事件归为一类是否是一种不好的做法?

performance - 如何提高 cassandra 中的插入性能?

mysql - 两列索引为一列,或一列索引

string - 根据动态模式匹配符号流