现在的位置: 首页 > 综合 > 正文

[翻译]Asp.net生成高质量缩略图

2011年11月19日 ⁄ 综合 ⁄ 共 5032字 ⁄ 字号 评论关闭
原文:http://www.thebrainparasite.com/post/Creating-great-thumbnails-in-ASPNET.aspx

使用ASP.NET内置的功能创建缩略图是非常方便和容易实现的。

int width = 190;
int height = 190;
Bitmap source 
= new Bitmap("c:\someimage.gif");
System.Drawing.Image thumb 
= source.GetThumbnailImage(width,height,null,IntPtr.Zero);

(31.7k)

麻烦的是,它生产的缩略图质量相对较差且生成的文件过大。该方法生成的缩略图往往看起来非常污浊,或许很多情况下这对你所需要的来说已经足够好。

一个选择

我常用的一个方法是使用 System.Drawing.Graphics 库 重画图像,这实现起来非常简单,但是却有非常好的效果。下面是我用来生成缩略图的一个示例函数

public static Bitmap CreateThumbnail(Bitmap source, int thumbWi, int thumbHi, bool maintainAspect)
        
{
            
// return the source image if it's smaller than the designated thumbnail
            if (source.Width < thumbWi && source.Height < thumbHi) return source;

            System.Drawing.Bitmap ret 
= null;
            
try
            
{
                
int wi, hi;

                wi 
= thumbWi;
                hi 
= thumbHi;

                
if (maintainAspect)
                
{
                    
// maintain the aspect ratio despite the thumbnail size parameters
                    if (source.Width > source.Height)
                    
{
                        wi 
= thumbWi;
                        hi 
= (int)(source.Height * ((decimal)thumbWi / source.Width));
                    }

                    
else
                    
{
                        hi 
= thumbHi;
                        wi 
= (int)(source.Width * ((decimal)thumbHi / source.Height));
                    }

                }


                
// original code that creates lousy thumbnails
                
// System.Drawing.Image ret = source.GetThumbnailImage(wi,hi,null,IntPtr.Zero);
                ret = new Bitmap(wi, hi);
                
using (Graphics g = Graphics.FromImage(ret))
                
{
                    g.InterpolationMode 
= System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                    g.FillRectangle(Brushes.White, 
00, wi, hi);
                    g.DrawImage(source, 
00, wi, hi);
                }

            }

            
catch
            
{
                ret 
= null;
            }


            
return ret;
        }

(10.5k)

这个函数是很方便的,因为的它的一个参数用来标识是否维在生成缩略图的时候维持图像的长宽比。这个缩略图魔法发生在下面的代码中

                using (Graphics g = Graphics.FromImage(ret))
                
{
                    g.InterpolationMode 
= System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                    g.FillRectangle(Brushes.White, 
00, wi, hi);
                    g.DrawImage(source, 
00, wi, hi);
                }

这个方法有点慢但是却让人难以舍弃,从下面的插图的对比可见:

(31.7k)original aG8klKbxhE-h43x2_tLGsw (10.5k)

我想说这是文件和图像质量都非常棒的实现,但是……

我们可以做的更好

现在我门可以混入 JPEG压缩来真正的优化结果, 我不想假装完全了解JPEG压缩的代码如何工作的,但它确实扭转了乾坤。

                //Configure JPEG Compression Engine
                System.Drawing.Imaging.EncoderParameters encoderParams = new System.Drawing.Imaging.EncoderParameters();
                
long[] quality = new long[1];
                quality[
0= 75;
                System.Drawing.Imaging.EncoderParameter encoderParam 
= new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
                encoderParams.Param[
0= encoderParam;

                System.Drawing.Imaging.ImageCodecInfo[] arrayICI 
= System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
                System.Drawing.Imaging.ImageCodecInfo jpegICI 
= null;
                
for (int x = 0; x < arrayICI.Length; x++)
                
{
                    
if (arrayICI[x].FormatDescription.Equals("JPEG"))
                    
{
                        jpegICI 
= arrayICI[x];
                        
break;
                    }

                }

这段代码设置了保存经过压缩的缩略图所需的 encoderParameters 参数,quality[0] 的值设定压缩的级别,我曾经针对某些应用设置像40这么低的值也成功了,俺是当质量要求比较高的时候 ,我发现设置为75非常好。使用这段代码你能够在生成缩略图之前使用 JPEG 压缩算法,当保存的时候把 encoderParamaters 作为参数,例如:

    System.Drawing.Image myThumbnail = CreateThumbnail(myBitmap,Width,Height,false);                

    
//Configure JPEG Compression Engine
                System.Drawing.Imaging.EncoderParameters encoderParams = new System.Drawing.Imaging.EncoderParameters();
                
long[] quality = new long[1];
                quality[
0= 75;
                System.Drawing.Imaging.EncoderParameter encoderParam 
= new System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, quality);
                encoderParams.Param[
0= encoderParam;

                System.Drawing.Imaging.ImageCodecInfo[] arrayICI 
= System.Drawing.Imaging.ImageCodecInfo.GetImageEncoders();
                System.Drawing.Imaging.ImageCodecInfo jpegICI 
= null;
                
for (int x = 0; x < arrayICI.Length; x++)
                
{
                    
if (arrayICI[x].FormatDescription.Equals("JPEG"))
                    
{
                        jpegICI 
= arrayICI[x];
                        
break;
                    }

                }

    
    myThumbnail.Save(Path.Combine(SavePathThumb, fileName), jpegICI, encoderParams);
                myThumbnail.Dispose();

compressed (2.39k)

2.39K 大小 看起来依然很棒

结论和最后比较

这是最后三张缩略图从文件大小最大到最小的效果对比

original aG8klKbxhE-h43x2_tLGsw compressed

最大 = 31.7k

未压缩重绘 = 10.5k (67% smaller)

压缩重绘 = 2.39k (92% smaller)

难以舍弃的结果啊,缩略图生成函数和JPEG压缩的源代码 在下边 :

ThumbnailGenerator.cs (1.97 kb)

JPEGCompressionConfig.cs (969.00 bytes)

抱歉!评论已关闭.