如何在没有DrawImage的情况下生成图像的高质量缩略图

时间:2013-07-01 18:44:28

标签: c# winforms image-processing thumbnails drawimage

我有一种方法可用于从图像中获取Byte[]缩略图。该方法接收图像的路径。

该课程运作良好,直到你达到一个大小阈值,之后性能下降到可怜的低水平。不,我还没有确定门槛...主要是因为经过一些研究后,似乎我使用的方法效率低,而且可扩展性不高。

我的方案似乎已在this SO thread确认。

这个问题确切地说明了我正在经历的事情。它不是解决方案的原因是因为答案是使用其他图形API和Paint覆盖,这显然不适用于此。我尝试了各种各样的东西,比如设置图形参数,但这没什么区别。

我正在处理的大型图片的一个示例是3872 x 2592,大小约为3.5Mb。一些更多,更多或更小或更小。

我的搜索没有收获太多。事实上,我似乎只能找到包含使用System.Drawing.Graphics.DrawImage()的建议。在一个例外中,建议包括试图使用PresentationFramework的程序集。这是一个WinForms应用,所以这似乎只是抓取缩略图。

我遇到的另一个建议是从文件中提取Exif信息(如果我记得的话)并尝试仅抓取数据而不是整个图像。我并不反对,但我还没有找到一个完整的例子来说明这是如何进行的。

我想知道P / Invoke选项。比GDI +(显然)能够提供的性能更好。但是,无论如何,如果我在此代码中缺少优化,请指出。

这是我目前的方法:

public static Byte[] GetImageThumbnailAsBytes(String FilePath)
{
    if (File.Exists(FilePath))
    {
        Byte[] ba = File.ReadAllBytes(FilePath);
        if (ba != null)
        {
            using (MemoryStream ms = new MemoryStream(ba, false))
            {
                Int32 thWidth = _MaxThumbWidth;
                Int32 thHeight = _MaxThumbHeight;
                Image i = Image.FromStream(ms, true, false);
                ImageFormat imf = i.RawFormat;
                Int32 w = i.Width;
                Int32 h = i.Height;
                Int32 th = thWidth;
                Int32 tw = thWidth;
                if (h > w)
                {
                    Double ratio = (Double)w / (Double)h;
                    th = thHeight < h ? thHeight : h;
                    tw = thWidth < w ? (Int32)(ratio * thWidth) : w;
                }
                else
                {
                    Double ratio = (Double)h / (Double)w;
                    th = thHeight < h ? (Int32)(ratio * thHeight) : h;
                    tw = thWidth < w ? thWidth : w;
                }
                Bitmap target = new Bitmap(tw, th);
                Graphics g = Graphics.FromImage(target);
                g.SmoothingMode = SmoothingMode.HighQuality;
                g.CompositingQuality = CompositingQuality.HighQuality;
                g.InterpolationMode = InterpolationMode.Bilinear; //NearestNeighbor
                g.CompositingMode = CompositingMode.SourceCopy;
                Rectangle rect = new Rectangle(0, 0, tw, th);
                g.DrawImage(i, rect, 0, 0, w, h, GraphicsUnit.Pixel);
                using (MemoryStream ms2 = new MemoryStream())
                {
                    target.Save(ms2, imf);
                    target.Dispose();
                    i.Dispose();
                    return ms2.ToArray();
                }
            }
        }
    }
    return new Byte[] { };
}

P.S。我首先使用Visual Studio 2012探查器到达此处,该探查器告诉我DrawImage()在加载图像时负责97.7%的CPU负载(我暂停/启动以隔离加载代码)。

0 个答案:

没有答案