C# 如何在没有DrawImage的情况下生成高质量的图像缩略图
我有一个方法,我使用它从图像中获取一个缩略图作为字节[]。该方法接收图像的路径 该类工作得非常好,直到达到一个大小阈值,之后性能下降到可怜的低水平。不,我还没有确定阈值…主要是因为经过一些研究,我似乎使用了一种低效且不太可扩展的方法 我的设想似乎已得到证实 这个问题正是我所经历的。它不是解决方案的原因是因为答案谈到了使用其他图形API和绘制覆盖,这显然不适用于这里。我尝试了各种各样的事情,比如设置图形参数,但是没有什么不同 我正在处理的一个大图像示例是3872 x 2592,大小约为3.5Mb。有些要大得多,许多要小得多 我的搜寻并没有取得多少成果。事实上,我似乎只能找到包括System.Drawing.Graphics.DrawImage使用在内的建议。在一个例外情况下,有人建议包括试图使用PresentationFramework的程序集。这是一个WinForms应用程序,所以仅仅为了抓取一个缩略图似乎有点过分 我遇到的另一个建议是从文件中提取Exif信息(如果我记得的话),并试图仅获取该数据而不是整个图像。我并不反对,但我还没有找到一个足够完整的例子来说明这是如何实现的 我想知道p/Invoke选项。比GDI+显然能够提供的性能更好。但是,无论如何,如果我在这段代码中缺少一个优化,请指出它 以下是我目前的方法:C# 如何在没有DrawImage的情况下生成高质量的图像缩略图,c#,winforms,image-processing,thumbnails,drawimage,C#,Winforms,Image Processing,Thumbnails,Drawimage,我有一个方法,我使用它从图像中获取一个缩略图作为字节[]。该方法接收图像的路径 该类工作得非常好,直到达到一个大小阈值,之后性能下降到可怜的低水平。不,我还没有确定阈值…主要是因为经过一些研究,我似乎使用了一种低效且不太可扩展的方法 我的设想似乎已得到证实 这个问题正是我所经历的。它不是解决方案的原因是因为答案谈到了使用其他图形API和绘制覆盖,这显然不适用于这里。我尝试了各种各样的事情,比如设置图形参数,但是没有什么不同 我正在处理的一个大图像示例是3872 x 2592,大小约为3.5Mb。
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[] { };
}
另外,我首先使用Visual Studio 2012 profiler来到这里,它告诉我DrawImage负责加载图像时97.7%的CPU负载。我暂停/开始隔离加载代码。你不能使用Image.GetThumbnailImage?@flyingstrudel这是此方法的前身,性能差得多。无论在质量还是速度上,gdi+都比其他产品慢。尝试一下gdii如果你愿意为了性能而放弃一些质量,我建议你编写自己的降尺度算法。我自己在机器视觉应用程序中处理大于80mpx的海量图像时也必须这样做。在我的例子中,我只是在两个方向上每16个像素获取一个缩略图,或者更确切地说是一个适合在屏幕上显示的东西。如果你需要一个特定的大小,这有点棘手。如果你对内置的性能不满意,你应该考虑在一个不安全的块内实现你自己的缩放算法,或者使用DirectX来代替GCPU在GPU上进行计算。