C# 根据图片生成缩略图.直接输出到客户端.

根据指定宽高,生成缩略图


   /// <summary>
    /// 生成缩略图.
    /// </summary>
    public class ImageThumbnailHandler : IHttpHandler
    {
        public void ProcessRequest(HttpContext context)
        {
            var Request = context.Request;
            context.Response.ContentType = "image/gif";

            int width = Request.GetInt("w",-1);
            int height = Request.GetInt("h", -1);

            //string fileId = Request.GetString("Id", "/noimg.png"); 
            //因为是直接通过HttpHandler映射进来的.所以.路径本身就包含参数.
            //例如 http://localhost:30700/Uploads/IDCard/temp/test.jpg.exd?w=100&h=100
            // Uploads/IDCard/temp/test.jpg.exd
            string fileId = Request.Url.AbsolutePath;
            //去掉.exd?w=100&h=100后面的部分
            fileId = fileId.Remove(fileId.LastIndexOf('.'));
            var ext = Path.GetExtension(fileId);

            string thumbPath = context.Server.MapPath("/Uploads/Thumbs/" + fileId.Remove(fileId.LastIndexOf('.')) + "_" + width + "_" + height +  ext); 
            //优先输出缩略图
            if (System.IO.File.Exists(thumbPath))
            {   //直接输出缩略图.
                context.Response.WriteFile(thumbPath);
                context.Response.End();
                return;
            }

            string filePath = context.Server.MapPath(fileId);
            //原图输出
            if (width == -1)
            {
                context.Response.WriteFile(filePath);
                context.Response.End();
                return;
            }
            //if (! System.IO.File.Exists(filePath))
            //{ 
            //    //找不到图片返回一个默认的图片
            //    filePath = context.Server.MapPath("/Uploads/noimg.png"); 
            //}

            System.Drawing.Image originalImage = System.Drawing.Image.FromFile(filePath);
            MakeCutThumbnailToResponse(originalImage, thumbPath, context, width, height);

            context.Response.End();
        }


        /// <summary>
        /// 生成缩略图直接输出到客户端
        /// </summary>
        /// <param name="originalImagePath">源图路径(物理路径)  </param>
        /// <param name="thumbnailPath">缩略图路径(物理路径)</param>
        /// <param name="width">缩略图宽度</param>
        /// <param name="height">缩略图高度</param>
        public void MakeCutThumbnailToResponse(System.Drawing.Image originalImage, string thumbPath, HttpContext context, int width, int height)
        {
            //缩略图画布宽高  

            double cut_x = 0;                               //原图剪切后,保留部分的坐标x
            double cut_y = 0;                               //原图剪切后,保留部分的坐标y
            double cut_Width = originalImage.Width;         //原图剪切后,保留部分的宽度
            double cut_Height = originalImage.Height;       //原图剪切后,保留部分的高度

            double windowImg_x = 0;                         //裁剪后保留部分的图片显示在画布上的窗口的x坐标
            double windowImg_y = 0;                         //裁剪后保留部分的图片显示在画布上的窗口的y坐标
            double windowImg_Width = width;                 //裁剪后保留部分的图片显示在画布上的窗口的宽度  //原图宽度不够会拉伸哦,超出部分被剪切
            double windowImg_Height = height;               //裁剪后保留部分的图片显示在画布上的窗口的高度  //原图高度不够会拉伸哦,超出部分被剪切


            //2.计算被切的图  
            //上传的图片的宽和高小等于缩略图
            if (originalImage.Width <= width && originalImage.Height <= height)
            {
                //上传的图片大于缩略图 宽高都不超,无需裁剪
                //居中 写全图 
                cut_x = 0;                        
                cut_y = 0;                         
                //缩略图按原始宽高 
                cut_Width = originalImage.Width;    //原图被显示的部分 宽
                cut_Height = originalImage.Height;  //原图被显示的部分 高

                //画布的宽高

                windowImg_Width = originalImage.Width;        //能看到的图片部分的宽
                windowImg_Height = originalImage.Height;      //能看到的图片部分的高

                windowImg_x = Convert.ToInt32((width - originalImage.Width) / 2); //居中;  //能看到的图片部分的宽
                windowImg_y = Convert.ToInt32((height - originalImage.Height) / 2); //居中; //能看到的图片部分的高
            }
            else if (originalImage.Width <= width)
            {   //上传的图片大于缩略图超高不超宽
                //裁剪超高部分 
                cut_x = 0;                         //原图被显示的部分坐标x
                cut_y = Convert.ToInt32( ( originalImage.Height - height ) / 2); //居中;  //原图被显示的部分坐标y
                //缩略图按原始宽高 
                cut_Width = originalImage.Width;    //原图被显示的部分 宽
                cut_Height = height;                //原图被显示的部分 部分高

                //画布的宽高

                windowImg_Width = originalImage.Width;                          //能看到的图片部分的宽
                windowImg_Height = height;       //能看到的图片部分的高

                windowImg_x = Convert.ToInt32((width - originalImage.Width) / 2); //居中;  //能看到的图片部分的宽
                windowImg_y = 0;                                                  //全高; //能看到的图片部分的高

            }
            else if (originalImage.Height <= height)
            {   //上传的图片大于缩略图超宽不超高
                cut_x = Convert.ToInt32((originalImage.Width - width) / 2);  //原图被显示的部分坐标x
                cut_y = 0; //居中;                                           //原图被显示的部分坐标y
                //缩略图按原始宽高 
                cut_Width = width;                                //原图被显示的部分 宽
                cut_Height = originalImage.Height;                //原图被显示的部分 高

                //画布的宽高 
                windowImg_Width = width;                          //能看到的图片部分的宽
                windowImg_Height = originalImage.Height;          //能看到的图片部分的高

                windowImg_x = 0; //居中;  //能看到的图片部分的宽
                windowImg_y = Convert.ToInt32((height - originalImage.Height) / 2); 
            }
            else
            { 
                //上传的图片大于缩略图宽高都超
                //这个裁剪会自动缩放一部分,然后再裁剪.
                        //画布的宽高 
                        windowImg_Width = width;   //全图
                        windowImg_Height = height; //全图 
                        windowImg_x = 0;
                        windowImg_y = 0; 
                        cut_x = 0;                      //一般图像的有效核心信息都显示在照片的中间部分.此处默认为0
                        cut_y = 0;                      //一般图像的有效核心信息都显示在照片的中间部分.此处默认为0



                        if (originalImage.Width >= originalImage.Height)
                        {
                            //宽的,显示最大高
                            cut_Height = originalImage.Height; //已定 不可变 

                            cut_x = originalImage.Width * 0.08;  //从8%的宽度处开始裁剪,提高图片显示核心信息的比例.不要就显示一个肩膀

                            double suofangbili = (double)windowImg_Width / (double)windowImg_Height;// 缩放比例 //已定 不可变  
                            cut_Width = originalImage.Height * suofangbili;// //已定 不可变 


                            //求 缩小后全图片的宽度
                            double miniImg_Width = originalImage.Width / (cut_Width / windowImg_Width); 

                            //如果画布的宽度比缩小后的图像宽度  更宽的话, 需要把图片左右居中,  否则就已经被自动裁剪了
                            if (width > miniImg_Width) 
                            {
                                windowImg_x = (width - miniImg_Width) / 2;
                            }

                        }
                        else
                        {  
                            //高的,显示最大宽度
                            cut_Width = originalImage.Width; //已定 不可变 

                            cut_y = originalImage.Height * 0.08; //从8%的高度处开始裁剪,提高图片显示核心信息的比例.不要就显示一个头发

                            double suofangbili = (double)windowImg_Width / (double)windowImg_Height;          // 缩放比例 //已定 不可变 
                            cut_Height = originalImage.Width / suofangbili;//windowImg_Height;//已定 不可变 

                            //求 缩小后全图片的宽度
                            double miniImg_Height = originalImage.Height / (cut_Height / windowImg_Height);

                            //如果画布的宽度比缩小后的图像宽度  更宽的话, 需要把图片左右居中,  否则就已经被自动裁剪了
                            if (height > miniImg_Height)
                            {
                                windowImg_y = (height - miniImg_Height) / 2;
                            }
                        }



            }


            //新建一个bmp图片,并设置缩略图大小. 
            System.Drawing.Image bitmap = new System.Drawing.Bitmap(width, height); //整个背景大图
            //新建一个画板 
            System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bitmap);
            //设置高质量插值法 
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
            //设置高质量,低速度呈现平滑程度 
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            //清空画布并设置背景色 
            g.Clear(System.Drawing.ColorTranslator.FromHtml("#000"));

            //在指定位置并且按指定大小绘制原图片的指定部分 
            //第一个System.Drawing.Rectangle是画布坐标和宽高,
            //第二个是原图片写在画布上的坐标和宽高,
            //最后一个参数是指定数值单位为像素 
            g.DrawImage(originalImage,
                new System.Drawing.Rectangle((int)windowImg_x, (int)windowImg_y, (int)windowImg_Width, (int)windowImg_Height),
                new System.Drawing.Rectangle((int)cut_x, (int)cut_y, (int)cut_Width, (int)cut_Height), 
                System.Drawing.GraphicsUnit.Pixel);

            try
            {

                bitmap.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Png);

                string thumbDirectory = System.IO.Path.GetDirectoryName(thumbPath);

                if (!System.IO.Directory.Exists(thumbDirectory))
                {
                    System.IO.Directory.CreateDirectory(thumbDirectory);
                }

                bitmap.Save(thumbPath, System.Drawing.Imaging.ImageFormat.Png);

                context.Response.End();
            }
            catch (System.Exception e)
            {
                throw e;
            }
            finally
            {
                originalImage.Dispose();
                bitmap.Dispose();
                g.Dispose();
            }
        }


        /// <summary>
        /// 生成缩略图直接输出到客户端(会有些效果不好,建议用上面的.MakeCutThumbnailToResponse)
        /// </summary>
        /// <param name="originalImagePath">源图路径(物理路径)  </param>
        /// <param name="thumbnailPath">缩略图路径(物理路径)</param>
        /// <param name="width">缩略图宽度</param>
        /// <param name="height">缩略图高度</param>
        public void MakeThumbnailToResponse(System.Drawing.Image originalImage, string thumbPath, HttpContext context, int width, int height)
        {
            //缩略图画布宽高 
            int toWidth = width;
            int toHeight = height;
            //原始图片写入画布坐标和宽高(用来设置裁减溢出部分) 
            int x = 0;
            int y = 0;
            int oldWidth = originalImage.Width;
            int oldHeight = originalImage.Height;
            //原始图片画布,设置写入缩略图画布坐标和宽高(用来原始图片整体宽高缩放) 
            int bg_x = 0;
            int bg_y = 0;
            int bg_w = toWidth;
            int bg_h = toHeight;
            //倍数变量 
            double multiple = 0;
            //获取宽长的或是高长与缩略图的倍数 
            if (originalImage.Width >= originalImage.Height) multiple = (double)originalImage.Width / (double)toWidth;
            else multiple = (double)originalImage.Height / (double)toHeight;
            //上传的图片的宽和高小等于缩略图 
            if (oldWidth <= toWidth && oldHeight <= toHeight)
            {
                //缩略图按原始宽高 
                bg_w = originalImage.Width;
                bg_h = originalImage.Height;
                //空白部分用背景色填充 
                bg_x = Convert.ToInt32(((double)toWidth - (double)oldWidth) / 2);
                bg_y = Convert.ToInt32(((double)toHeight - (double)oldHeight) / 2);
            }
            //上传的图片的宽和高大于缩略图 
            else
            {
                //宽高按比例缩放 
                bg_w = Convert.ToInt32((double)originalImage.Width / multiple);
                bg_h = Convert.ToInt32((double)originalImage.Height / multiple);
                //空白部分用背景色填充 
                bg_y = Convert.ToInt32(((double)toHeight - (double)bg_h) / 2);
                bg_x = Convert.ToInt32(((double)toWidth - (double)bg_w) / 2);
            }
            //新建一个bmp图片,并设置缩略图大小. 
            System.Drawing.Image bitmap = new System.Drawing.Bitmap(toWidth, toHeight);
            //新建一个画板 
            System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bitmap);
            //设置高质量插值法 
            g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBilinear;
            //设置高质量,低速度呈现平滑程度 
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            //清空画布并设置背景色 
            g.Clear(System.Drawing.ColorTranslator.FromHtml("#F2F2F2"));
            //在指定位置并且按指定大小绘制原图片的指定部分 
            //第一个System.Drawing.Rectangle是原图片的画布坐标和宽高,第二个是原图片写在画布上的坐标和宽高,最后一个参数是指定数值单位为像素 
            g.DrawImage(originalImage, new System.Drawing.Rectangle(bg_x, bg_y, bg_w, bg_h), new System.Drawing.Rectangle(x, y, oldWidth, oldHeight), System.Drawing.GraphicsUnit.Pixel);
            try
            {

                bitmap.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Png);

                string thumbDirectory = System.IO.Path.GetDirectoryName(thumbPath);

                if (!System.IO.Directory.Exists(thumbDirectory))
                {
                    System.IO.Directory.CreateDirectory(thumbDirectory);
                }

                bitmap.Save(thumbPath, System.Drawing.Imaging.ImageFormat.Png);

                context.Response.End();
            }
            catch (System.Exception e)
            {
                throw e;
            }
            finally
            {
                originalImage.Dispose();
                bitmap.Dispose();
                g.Dispose();
            }
        }

        public bool IsReusable
        {
            get
            {
                return false;
            }
        }
    }

    /// <summary>
    /// Request扩展
    /// </summary>
    public static class RequestHelper
    {
        #region Get/GetInt/GetFloat
        /// <summary>
        /// 接收传值
        /// </summary>
        /// <param name="VarName">参数名称</param>
        /// <returns>参数对应的值</returns>
        static public String GetString(this HttpRequest Request, String varName)
        {
            if (string.IsNullOrEmpty(Request[varName]))
            { 
                return string.Empty;
            }
            else
            {
                return Request[varName];
            } 
        }

                /// <summary>
        /// 接收传值
        /// </summary>
        /// <param name="VarName">参数名称</param>
        /// <returns>参数对应的值</returns>
        static public String GetString(this HttpRequest Request, String varName,string defaultValue)
        {
            if (string.IsNullOrEmpty(Request[varName]))
            {
                return defaultValue;
            }
            else
            {
                return Request[varName];
            } 
        }

        /// <summary>
        /// GetInt
        /// </summary>
        /// <param name="varName"></param>
        /// <param name="defValue"></param>
        /// <returns></returns>
        static public int GetInt(this HttpRequest Request, string varName, int defaultValue)
        {

            if (string.IsNullOrEmpty( Request[varName] ))
            {

                return defaultValue;
            }
            else
            {
                int.TryParse(Request[varName], out defaultValue);
                return defaultValue;
            } 
        }


        /// <summary>
        /// Get日期格式的参数.
        /// </summary>
        /// <param name="varName"></param> 
        /// <returns></returns>
        static public DateTime? GetDateTime(this HttpRequest Request, string varName)
        {
            if (string.IsNullOrEmpty(Request[varName]))
            { 
                return null;
            }
            else
            {
                DateTime d = DateTime.MinValue;
                DateTime.TryParse(Request[varName], out d);
                return d;
            }
        }


        /// <summary>
        /// GetDecimal 获取十进制数,一般货币形式.
        /// </summary>
        /// <param name="varName"></param>
        /// <param name="defValue"></param>
        /// <returns></returns>
        static public double GetDouble(this HttpRequest Request, string varName, double defaultValue)
        {
            if (string.IsNullOrEmpty(Request[varName]))
            {
                return defaultValue;
            }
            else
            {
                double.TryParse(Request[varName], out defaultValue);
                return defaultValue;
            }
        }

        /// <summary>
        /// GetDecimal 获取十进制数,一般货币形式.
        /// </summary>
        /// <param name="varName"></param>
        /// <param name="defValue"></param>
        /// <returns></returns>
        static public decimal GetDecimal(this HttpRequest Request, string varName, decimal defaultValue)
        {
            if (string.IsNullOrEmpty(Request[varName]))
            {
                return defaultValue;
            }
            else
            {
                decimal.TryParse(Request[varName], out defaultValue);
                return defaultValue;
            }
        }

        /// <summary>
        /// GetFloat
        /// </summary>
        /// <param name="varName"></param>
        /// <param name="defValue"></param>
        /// <returns></returns>
        static public float GetFloat(this HttpRequest Request, string varName, float defaultValue)
        {
            if (string.IsNullOrEmpty(Request[varName]))
            {
                return defaultValue;
            }
            else
            {
                float.TryParse(Request[varName], out defaultValue);
                return defaultValue;
            }
        }
        #endregion

        #region IsPost/IsGet
        /// <summary>
        /// 判断当前页面是否接收到了Post请求
        /// </summary>
        /// <returns>是否接收到了Post请求</returns>
        public static bool IsPost(this HttpRequest Request)
        {
            return Request.HttpMethod.Equals("POST");
        }
        /// <summary>
        /// 判断当前页面是否接收到了Get请求
        /// </summary>
        /// <returns>是否接收到了Get请求</returns>
        public static bool IsGet(this HttpRequest Request)
        {
            return Request.HttpMethod.Equals("GET");
        }
        #endregion
    }

在web.config中配置好 处理程序映射, 这里的*.img 直接在图片路径的后面加上.

 <handlers>
        <add name="ImageThumbnailHandler" verb="*" path="*.img" type="命名空间.ImageThumbnailHandler,命名空间"/>
    </handlers>

使用方法
http://localhost:2222/upload/a.jpg.img&w=120&h=80

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值