阅读文章

重提:上传图片生成略缩图“最佳解决”

[日期:2008-02-25] 来源:  作者: [字体: ]

     从用 .Net Web 开发到现在所看到的略缩生成代码都不尽人意,要不太局限,要不失真厉害。
  
  为此写了一个相对完善的函数供大家学习。
  
  其中的 SaveIamge 函数提供了失真解决方法,对于处理过的图片(如加水印……)要求保持高品质可以直接调用。
  
  using System;
  using System.IO;
  using System.Drawing;
  using System.Drawing.Drawing2D;
  using System.Drawing.Imaging;
  using System.Drawing.Text;
  using System.Text.RegularExpressions;
  
  /// <summary>
  // 图片处理。
  // http://www.hulaka.com/
  // (c) 2008 Dao
  /// </summary>
  public class Image
  {
   /// <summary>
   /// 缩略模式。
   /// </summary>
   public enum ThumbMode : byte
   {
   /// <summary>
   /// 完整模式
   /// </summary>
   Full = 1,
   /// <summary>
   /// 最大尺寸
   /// </summary>
   Max
   }
  
   /// <summary>
   /// 缩略图。
   /// </summary>
   /// <param name="image">要缩略的图片</param>
   /// <param name="size">要缩放的尺寸</param>
   /// <param name="mode">缩略模式</param>
   /// <param name="contentAlignment">对齐方式</param>
   /// <returns>返回已经缩放的图片。</returns>
   public static Bitmap Thumbnail(Bitmap image, Size size, ThumbMode mode, ContentAlignment contentAlignment)
   {
   if (!size.IsEmpty && !image.Size.IsEmpty && !size.Equals(image.Size))
   {
   //先取一个宽比例。
   double scale = (double)image.Width / (double)size.Width;
   //缩略模式
   switch (mode)
   {
   case ThumbMode.Full:
   if (image.Height > image.Width)
   scale = (double)image.Height / (double)size.Height;
   break;
   case ThumbMode.Max:
   if (image.Height / scale < size.Height)
   scale = (double)image.Height / (double)size.Height;
   break;
   }
   SizeF newSzie = new SizeF((float)(image.Width / scale), (float)(image.Height / scale));
   Bitmap result = new Bitmap(size.Width, size.Height);
   using (Graphics g = Graphics.FromImage(result))
   {
   g.FillRectangle(Brushes.White, new Rectangle(new Point(0, 0), size));
   g.InterpolationMode = InterpolationMode.HighQualityBicubic;
   g.SmoothingMode = SmoothingMode.HighQuality;
   g.PixelOffsetMode = PixelOffsetMode.HighQuality;
   g.CompositingMode = CompositingMode.SourceOver;
   g.CompositingQuality = CompositingQuality.HighQuality;
   g.TextRenderingHint = TextRenderingHint.AntiAliasGridFit;
   //对齐方式
   RectangleF destRect;
   switch (contentAlignment)
   {
   case ContentAlignment.TopCenter:
   destRect = new RectangleF(new PointF(-(float)((newSzie.Width - size.Width) * 0.5), 0), newSzie);
   break;
   case ContentAlignment.TopRight:
   destRect = new RectangleF(new PointF(-(float)(newSzie.Width - size.Width), 0), newSzie);
   break;
   case ContentAlignment.MiddleLeft:
   destRect = new RectangleF(new PointF(0, -(float)((newSzie.Height - size.Height) * 0.5)), newSzie);
   break;
   case ContentAlignment.MiddleCenter:
   destRect = new RectangleF(new PointF(-(float)((newSzie.Width - size.Width) * 0.5), -(float)((newSzie.Height - size.Height) * 0.5)), newSzie);
   break;
   case ContentAlignment.MiddleRight:
   destRect = new RectangleF(new PointF(-(float)(newSzie.Width - size.Width), -(float)((newSzie.Height - size.Height) * 0.5)), newSzie);
   break;
   case ContentAlignment.BottomLeft:
   destRect = new RectangleF(new PointF(0, -(float)(newSzie.Height - size.Height)), newSzie);
   break;
   case ContentAlignment.BottomCenter:
   destRect = new RectangleF(new PointF(-(float)((newSzie.Width - size.Width) * 0.5), -(float)(newSzie.Height - size.Height)), newSzie);
   break;
   case ContentAlignment.BottomRight:
   destRect = new RectangleF(new PointF(-(float)(newSzie.Width - size.Width), -(float)(newSzie.Height - size.Height)), newSzie);
   break;
   default:
   destRect = new RectangleF(new PointF(0, 0), newSzie);
   break;
   }
   g.DrawImage(image, destRect, new RectangleF(new PointF(0F, 0F), image.Size), GraphicsUnit.Pixel);
   image.Dispose();
   }
   return result;
   }
   else
   return image;
   }
  
   /// <summary>
   /// 保存图片。
   /// </summary>
   /// <param name="image">要保存的图片</param>
   /// <param name="quality">品质(1L~100L之间,数值越大品质越好)</param>
   /// <param name="filename">保存路径</param>
   public static void SaveIamge(Bitmap image, long quality, string filename)
   {
   using (EncoderParameters encoderParams = new EncoderParameters(1))
   {
   using (EncoderParameter parameter = (encoderParams.Param[0] = new EncoderParameter(Encoder.Quality, quality)))
   {
   ImageCodecInfo encoder = null;
   //取得扩展名
   string ext = Path.GetExtension(filename);
   if (string.IsNullOrEmpty(ext))
   ext = ".jpg";
   //根据扩展名得到解码、编码器
   foreach (ImageCodecInfo codecInfo in ImageCodecInfo.GetImageEncoders())
   {
   if (Regex.IsMatch(codecInfo.FilenameExtension, string.Format(@"(;|^)\*\{0}(;|$)", ext), RegexOptions.IgnoreCase))
   {
   encoder = codecInfo;
   break;
   }
   }
   Directory.CreateDirectory(Path.GetDirectoryName(filename));
   image.Save(filename, encoder, encoderParams);
   }
   }
   }
  
   /// <summary>
   /// 保存图片。
   /// </summary>
   /// <param name="stream">要保存的流</param>
   /// <param name="quality">品质(1L~100L之间,数值越大品质越好)</param>
   /// <param name="filename">保存路径</param>
   public static void SaveIamge(Stream stream, long quality, string filename)
   {
   using (Bitmap bmpTemp = new Bitmap(stream))
   {
   SaveIamge(bmpTemp, quality, filename);
   }
   }
  }
  调用方法如下:
  using (Bitmap bmpAvatar = Image.Thumbnail(new Bitmap(/*<流,FileUpload 控件的 PostedFile.InputStream 属性>*/), new Size(48, 48), Image.ThumbMode.Full, ContentAlignment.MiddleCenter))
  {
   Image.SaveIamge(bmpAvatar, 95L, Server.MapPath("~/upfiles/Avatar.jpg"));
  }
  
  演示程序:
  
  下载演示程序
  http://www.hulaka.com/Get/38.rar  


阅读:
录入:blue1000

评论 】 【 推荐 】 【 打印
上一篇:对软件外包的思考
下一篇:LINQ体验(11)——LINQ to SQL语句之Null语义和String/DateTi
相关文章      
本文评论
发表评论


点评: 字数
姓名:

  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款