我有一种方法可用于从图像中获取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负载(我暂停/启动以隔离加载代码)。