我需要在不损失太多质量的情况下调整许多图像的大小。
使用PresentationFramework (WPF)相当快,但质量很差。
使用GDI+,它的质量很好,但被锁定在UI-Thread -> singleCored上。:-(
有没有在一段代码中结合速度和质量的又好又快的算法?;-)
发布于 2011-08-29 22:50:42
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() -但即使您不能,您也应该能够从它获得更多的吞吐量(即使是在单线程上)。
发布于 2011-08-29 21:39:28
没有理由不在单独的线程上为此打开单独的消息泵,这只是意味着您可以在100个线程中并行执行;)。
我知道这是一个更加神秘的部分,但是有一些应用程序通过在每个启动的线程上实现特定的窗口消息泵来为每个窗口提供一个稀疏线程。同样的方法也可以用于此。将其视为.NET UI编程201级别。
https://stackoverflow.com/questions/7230687
复制相似问题