Quantcast
Channel: panjj 最新博客
Viewing all articles
Browse latest Browse all 59

C#的另类图片缩放

$
0
0

导读:在指定大小的框框内,对图片等比例缩放,你有没有碰到?有的话以下代码可能有些用。

问题场景

最近碰到一个客户提出一个需求:图片缩放功能,上传的图片尺寸可以是任何比例,而且有横向也有纵向的,在规定的尺寸范围内缩放,缩放后的图片不能有剪切的,缩放后图片可视比例和原图片比例相等。如果明白的话,很明显这种缩放,横向或纵向可能会留空白的边,于是把这种情况跟客户说了,客户也很明白,说可以接受。

问题分析得出思路

平时接触的图片缩放或剪切,都不是此类的,先在google上搜索了一下,有需求,但没有看到几个解决方案,这么来真的要自己写一些程序了,缕缕思路:首先要计算出缩放后图片的尺寸,该尺寸的长宽都在指定尺寸范围内,也就是,如果上传的图片和指定尺寸比例不等的话,不是纵向就是横向会留下空边,但不会两向都会留,因为上传的图片长宽都比指定尺寸大的话,需要把图片缩小,直至长或宽和指定的长或宽相等,如果上传的图片长宽都比指定的长宽小的话,也需要把图片放大,直至长或宽和指定的长或宽相等。开始写代码了,先把这个思想转化成代码:

        /// <summary>
        /// 给定一个矩形(长方形 正方形)剪切的范围 传入一张图片的原始尺寸 
        /// 得到一个在该矩形范围内的最佳尺寸(原图的比例不会变)
        /// add 2goo 2011-4-8
        /// </summary>
        /// <param name="specifySize">指定尺寸</param>
        /// <param name="originalSize">原始尺寸</param>
        /// <returns>返回(原图片等比例)最佳尺寸</returns>
        private static Size ResizeSite(Size specifySize, Size originalSize)
        {
            Size finaSize = new Size();
            float specifyScale = (float)specifySize.Width / (float)specifySize.Height;
            float originalScale = (float)originalSize.Width / (float)originalSize.Height;
            if (specifySize.Width >= originalSize.Width)
            {
                finaSize.Height = specifySize.Height;
                finaSize.Width = (int)(finaSize.Height * originalScale);
                if (finaSize.Width > specifySize.Width)
                {
                    finaSize.Width = specifySize.Width;
                    finaSize.Height = (int)(finaSize.Width / originalScale);
                }
            }
            else
            {
                finaSize.Width = specifySize.Width;
                finaSize.Height = (int)(finaSize.Width / originalScale);
                if (finaSize.Height > specifySize.Height)
                {
                    finaSize.Height = specifySize.Height;
                    finaSize.Width = (int)(finaSize.Height * originalScale);
                }
            }
            return finaSize;
        }

后续思路

只要结合指定尺寸把上传的图片的长宽计算出来,那剩下的工作就是图片的缩放处理了,写代码之前,想法大概思路是这样的:先结合刚才的代码,把图片的长宽取出来,用C#的Graphics DrawImage把图片等比列缩放成计算出来的尺寸,然后再画个新图,尺寸和指向尺寸一样,把刚才的缩放好的图片粘贴找这张新图上即可,当然这个过程,还要计算空边(有两边)的尺寸,好了写好代码如下:

        /// <summary>
        /// 缩放图片 按比例 如果指定的尺寸和原图片尺寸比例不等,会留空边
        /// 2goo add 2011-04-06
        /// </summary>
        /// <param name="postedFile">原图HttpPostedFile对象</param>
        /// <param name="savePath">保存图片的绝对路径 包括图片名</param>
        /// <param name="newWidth">指定宽度</param>
        /// <param name="newHeight">指定高度</param>
        public static void ResizeImage(System.Web.HttpPostedFile postedFile, 
            string savePath, int newWidth, int newHeight)
        {
            //创建目录
            string dir = Path.GetDirectoryName(savePath);
            if (!Directory.Exists(dir))
                Directory.CreateDirectory(dir);

            //原始图片(获取原始图片创建对象,并使用流中嵌入的颜色管理信息)
            System.Drawing.Image originalImage = 
                System.Drawing.Image.FromStream(postedFile.InputStream, true);

            int ow = originalImage.Width;//原始宽度
            int oh = originalImage.Height;//原始高度

            Size toSize = ResizeSite(new Size(newWidth, newHeight), new Size(ow,oh));
            int towidth = toSize.Width;//原图片缩放后的宽度
            int toheight = toSize.Height;//原图片缩放后的高度

            int x = 0;
            int y = 0;

            x = (newWidth - towidth) / 2;
            y = (newHeight - toheight) / 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.HighQualityBicubic;
            //设置高质量,低速度呈现平滑程度
            g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            //清空画布并以透明背景色填充
            g.Clear(System.Drawing.Color.Transparent);
            //在指定位置并且按指定大小绘制原图片的指定部分
            g.DrawImage(originalImage, new System.Drawing.Rectangle(0, 0, towidth, toheight),
            new System.Drawing.Rectangle(0, 0, ow, oh),
            System.Drawing.GraphicsUnit.Pixel);
            //--------------------------------------------------------------------------------

            //新建一个bmp图片2
            System.Drawing.Image bitmap2 = new System.Drawing.Bitmap(newWidth, newHeight);
            //新建一个画板2
            System.Drawing.Graphics g2 = System.Drawing.Graphics.FromImage(bitmap2);
            //设置高质量插值法
            g2.InterpolationMode = 
                System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
            //设置高质量,低速度呈现平滑程度
            g2.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            //清空画布并以透明背景色填充
            g2.Clear(System.Drawing.Color.White);
            g2.DrawImageUnscaled(bitmap,new Point(x,y));

            try
            {
                //以jpg格式保存缩略图
                bitmap2.Save(savePath, System.Drawing.Imaging.ImageFormat.Jpeg);
            }
            catch (System.Exception e)
            {
                throw e;
            }
            finally
            {
                originalImage.Dispose();
                bitmap.Dispose();
                bitmap2.Dispose();
                g2.Dispose();
                g.Dispose();
            }
        }
上面方法介绍:ResizeImage其实就是图片缩放,然后保存到磁盘里的整个过程。方法需要HttpPostedFile(Request.Files["controlName"]) 图片保存路径(绝对路径和包含图片的名字),保存宽度和高度。四个参数即可。

其中有到的类库如下:

using System;
using System.Drawing;
using System.IO;

如果有问题,回复我...


Viewing all articles
Browse latest Browse all 59

Trending Articles