生成缩略图的最有效方法是什么?

4

我正在开发一个图形应用程序,需要为每个页面保留缩略图。挑战在于如何在不影响性能的情况下生成缩略图文件?

当前这是我的代码:

VisualBrush VisualBrush = new VisualBrush(pageToGenerateThumbnailFor);
UIVisual.Background = VisualBrush;

RenderTargetBitmap = new RenderTargetBitmap((int)UIVisual.ActualWidth, (int)UIVisual.ActualHeight, 96, 96, PixelFormats.Pbgra32);

rtb.Render(UIVisual);

using (FileStream outStream = new FileStream(ThumbFileFullPath, FileMode.OpenOrCreate, 
System.IO.FileAccess.ReadWrite))
{
   PngBitmapEncoder pngEncoder = new PngBitmapEncoder();
   pngEncoder.Frames.Add(BitmapFrame.Create(rtb));
   pngEncoder.Save(outStream);
}

那么,有没有更快的方法为给定的视觉生成缩略图呢?
谢谢。

你有多少张图片?它们的更改频率是多少?这些因素可能会影响正确答案。 - Lee Taylor
请访问http://imageresizing.net/获取一个好的解决方案,并访问http://www.nathanaeljones.com/blog/2009/20-image-resizing-pitfalls获取有关图像调整大小的一般信息。 - Paul Zahra
图片数量可能会有所不同,我不知道用户会如何使用它,但是对于更改,只有当用户调整大小、旋转或移动图像时才会发生。 - simo
2个回答

3

最近我做了一些关于电子商务网站生成图像缩略图的研究。一开始,我自己生成位图,然后进行调整大小等操作,与上面的答案类似。由于磁盘上的图像大小和质量问题,我查看了http://imageresizing.net/,从那以后就没有再回头了。它可以通过一行代码非常快速地从byte()、流和物理文件中生成图像。

ImageBuilder.Current.Build(New MemoryStream(bImage), sImageLocation + sFullFileName, New      ResizeSettings("maxwidth=214&maxheight=238"))

我强烈推荐使用这个组件,而不是试图重新发明轮子...

这是一个适用于Web应用程序的解决方案,但是我们所拥有的是桌面应用程序.. - simo
嗨,萨米尔,这将在WPF应用程序中毫无问题地工作。我甚至在定期的Windows服务上调用它。 - James
imageresizing不是免费的 - 它涉及到许可证等问题,如果你只想使用框架而不涉及第三方库(和成本),有很多方法可以获得高质量、高性能的缩略图。 - LordWabbit
图片调整大小不是免费的 - 这涉及到许可证等问题,如果你只想得到一些质量良好、性能出色的缩略图,完全可以使用框架自身提供的方法,而无需引入第三方库(和相关费用)。 - LordWabbit
这是10年前的@LordWabbit... - James
@James - 不过奇怪的是,它仍然相关,并且可能会帮助那些正在寻找解决方案的人。你的回复有什么帮助吗? - undefined

1

我写的实用程序库中的以下类对我来说表现良好,生成清晰质量的缩略图...

using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Threading;

namespace Simple {
    public static class ThumbnailCreator {
        private static readonly object _lock = new object();

        public static Bitmap createThumbnail(Stream source, Int32 width, Int32 height) {
            Monitor.Enter(_lock);
            Bitmap output = null;
            try {
                using (Bitmap workingBitmap = new Bitmap(source)) {
                    // Determine scale based on requested height/width (this preserves aspect ratio)
                    Decimal scale;
                    if (((Decimal)workingBitmap.Width / (Decimal)width) > ((Decimal)workingBitmap.Height / (Decimal)height)) {
                        scale = (Decimal)workingBitmap.Width / (Decimal)width;
                    }
                    else {
                        scale = (Decimal)workingBitmap.Height / (Decimal)height;
                    }
                    // Calculate new height/width
                    Int32 newHeight = (Int32)((Decimal)workingBitmap.Height / scale);
                    Int32 newWidth = (Int32)((Decimal)workingBitmap.Width / scale);
                    // Create blank BitMap of appropriate size
                    output = new Bitmap(newWidth, newHeight, PixelFormat.Format32bppArgb);
                    // Create Graphics surface
                    using (Graphics g = Graphics.FromImage(output)) {
                        g.CompositingMode = System.Drawing.Drawing2D.CompositingMode.SourceCopy;
                        g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                        Rectangle destRectangle = new Rectangle(0, 0, newWidth, newHeight);
                        // Use Graphics surface to draw resized BitMap to blank BitMap
                        g.DrawImage(workingBitmap, destRectangle, 0, 0, workingBitmap.Width, workingBitmap.Height, GraphicsUnit.Pixel);
                    }
                }
            }
            catch {
                output = null;
            }
            finally {
                Monitor.Exit(_lock);
            }
            return output;
        }
    }
}

它还保留了原始图像的宽高比。


1
哦,天啊!这段代码看起来就像是从IL反编译出来的 :P 当你有“lock”关键字时,为什么还要使用“Monitor.Enter”和“Exit”呢? - khellang

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