好久没写博客了,一个字:忙
今天索性随便贴一些代码,这些代码主要是为了解决图片的压缩问题
我们都知道,移动端的图片不易过大,否则就会拉低加载速度!影响用户体验
因此,我们就有必要通过程序生成大图片的缩略图!这种场景常用在加载图片列表时
比如,有十张大小2M左右的图片需要加载出来,那么在完成加载完成就需要20M的网络资源,因此,使用缩略图是有必要的
好了,废话基本说完了,下面看代码:

public class PicManger { private Image srcImage; private string srcFileName; /// <summary> /// 创建 /// </summary> /// <param name="FileName">原始图片路径</param> public bool SetImage(string FileName) { srcFileName = Utils.GetMapPath(FileName); try { srcImage = Image.FromFile(srcFileName); } catch { return false; } return true; } /// <summary> /// 回调 /// </summary> /// <returns></returns> public bool ThumbnailCallback() { return false; } /// <summary> /// 生成缩略图,返回缩略图的Image对象 /// </summary> /// <param name="Width">缩略图宽度</param> /// <param name="Height">缩略图高度</param> /// <returns>缩略图的Image对象</returns> public Image GetImage(int Width, int Height) { Image img; Image.GetThumbnailImageAbort callb = new Image.GetThumbnailImageAbort(ThumbnailCallback); img = srcImage.GetThumbnailImage(Width, Height, callb, IntPtr.Zero); return img; } /// <summary> /// 保存缩略图 /// </summary> /// <param name="Width"></param> /// <param name="Height"></param> public void SaveThumbnailImage(int Width, int Height) { switch (Path.GetExtension(srcFileName).ToLower()) { case ".png": SaveImage(Width, Height, ImageFormat.Png); break; case ".gif": SaveImage(Width, Height, ImageFormat.Gif); break; default: SaveImage(Width, Height, ImageFormat.Jpeg); break; } } /// <summary> /// 生成缩略图并保存 /// </summary> /// <param name="Width">缩略图的宽度</param> /// <param name="Height">缩略图的高度</param> /// <param name="imgformat">保存的图像格式</param> /// <returns>缩略图的Image对象</returns> public void SaveImage(int Width, int Height, ImageFormat imgformat) { if (imgformat != ImageFormat.Gif && (srcImage.Width > Width) || (srcImage.Height > Height)) { Image img; Image.GetThumbnailImageAbort callb = new Image.GetThumbnailImageAbort(ThumbnailCallback); img = srcImage.GetThumbnailImage(Width, Height, callb, IntPtr.Zero); srcImage.Dispose(); img.Save(srcFileName, imgformat); img.Dispose(); } } #region Helper /// <summary> /// 保存图片 /// </summary> /// <param name="image">Image 对象</param> /// <param name="savePath">保存路径</param> /// <param name="ici">指定格式的编解码参数</param> private static void SaveImage(Image image, string savePath, ImageCodecInfo ici) { //设置 原图片 对象的 EncoderParameters 对象 EncoderParameters parameters = new EncoderParameters(1); parameters.Param[0] = new EncoderParameter(Encoder.Quality, ((long)100)); image.Save(savePath, ici, parameters); parameters.Dispose(); } /// <summary> /// 获取图像编码解码器的所有相关信息 /// </summary> /// <param name="mimeType">包含编码解码器的多用途网际邮件扩充协议 (MIME) 类型的字符串</param> /// <returns>返回图像编码解码器的所有相关信息</returns> private static ImageCodecInfo GetCodecInfo(string mimeType) { ImageCodecInfo[] CodecInfo = ImageCodecInfo.GetImageEncoders(); foreach (ImageCodecInfo ici in CodecInfo) { if (ici.MimeType == mimeType) return ici; } return null; } /// <summary> /// 计算新尺寸 /// </summary> /// <param name="width">原始宽度</param> /// <param name="height">原始高度</param> /// <param name="maxWidth">最大新宽度</param> /// <param name="maxHeight">最大新高度</param> /// <returns></returns> private static Size ResizeImage(int width, int height, int maxWidth, int maxHeight) { //此次2012-02-05修改过================= if (maxWidth <= 0) maxWidth = width; if (maxHeight <= 0) maxHeight = height; //以上2012-02-05修改过================= decimal MAX_WIDTH = (decimal)maxWidth; decimal MAX_HEIGHT = (decimal)maxHeight; decimal ASPECT_RATIO = MAX_WIDTH / MAX_HEIGHT; int newWidth, newHeight; decimal originalWidth = (decimal)width; decimal originalHeight = (decimal)height; if (originalWidth > MAX_WIDTH || originalHeight > MAX_HEIGHT) { decimal factor; // determine the largest factor if (originalWidth / originalHeight > ASPECT_RATIO) { factor = originalWidth / MAX_WIDTH; newWidth = Convert.ToInt32(originalWidth / factor); newHeight = Convert.ToInt32(originalHeight / factor); } else { factor = originalHeight / MAX_HEIGHT; newWidth = Convert.ToInt32(originalWidth / factor); newHeight = Convert.ToInt32(originalHeight / factor); } } else { newWidth = width; newHeight = height; } return new Size(newWidth, newHeight); } /// <summary> /// 得到图片格式 /// </summary> /// <param name="name">文件名称</param> /// <returns></returns> public static ImageFormat GetFormat(string name) { string ext = name.Substring(name.LastIndexOf(".") + 1); switch (ext.ToLower()) { case "jpg": case "jpeg": return ImageFormat.Jpeg; case "bmp": return ImageFormat.Bmp; case "png": return ImageFormat.Png; case "gif": return ImageFormat.Gif; default: return ImageFormat.Jpeg; } } #endregion /// <summary> /// 制作小正方形 /// </summary> /// <param name="image">图片对象</param> /// <param name="newFileName">新地址</param> /// <param name="newSize">长度或宽度</param> public static void MakeSquareImage(Image image, string newFileName, int newSize) { int i = 0; int width = image.Width; int height = image.Height; if (width > height) i = height; else i = width; Bitmap b = new Bitmap(newSize, newSize); try { Graphics g = Graphics.FromImage(b); //设置高质量插值法 g.InterpolationMode = InterpolationMode.HighQualityBicubic; //设置高质量,低速度呈现平滑程度 g.SmoothingMode = SmoothingMode.AntiAlias; g.PixelOffsetMode = PixelOffsetMode.HighQuality; //清除整个绘图面并以透明背景色填充 g.Clear(Color.Transparent); if (width < height) g.DrawImage(image, new Rectangle(0, 0, newSize, newSize), new Rectangle(0, (height - width) / 2, width, width), GraphicsUnit.Pixel); else g.DrawImage(image, new Rectangle(0, 0, newSize, newSize), new Rectangle((width - height) / 2, 0, height, height), GraphicsUnit.Pixel); SaveImage(b, newFileName, GetCodecInfo("image/" + GetFormat(newFileName).ToString().ToLower())); } finally { image.Dispose(); b.Dispose(); } } /// <summary> /// 制作小正方形 /// </summary> /// <param name="fileName">图片文件名</param> /// <param name="newFileName">新地址</param> /// <param name="newSize">长度或宽度</param> public static void MakeSquareImage(string fileName, string newFileName, int newSize) { MakeSquareImage(Image.FromFile(fileName), newFileName, newSize); } /// <summary> /// 制作远程小正方形 /// </summary> /// <param name="url">图片url</param> /// <param name="newFileName">新地址</param> /// <param name="newSize">长度或宽度</param> public static void MakeRemoteSquareImage(string url, string newFileName, int newSize) { Stream stream = GetRemoteImage(url); if (stream == null) return; Image original = Image.FromStream(stream); stream.Close(); MakeSquareImage(original, newFileName, newSize); } /// <summary> /// 制作缩略图 /// </summary> /// <param name="original">图片对象</param> /// <param name="newFileName">新图路径</param> /// <param name="maxWidth">最大宽度</param> /// <param name="maxHeight">最大高度</param> public static void MakeThumbnailImage(Image original, string newFileName, int maxWidth, int maxHeight) { Size _newSize = ResizeImage(original.Width, original.Height, maxWidth, maxHeight); using (Image displayImage = new Bitmap(original, _newSize)) { try { displayImage.Save(newFileName, original.RawFormat); } finally { original.Dispose(); } } } /// <summary> /// 制作缩略图 /// </summary> /// <param name="fileName">文件名</param> /// <param name="newFileName">新图路径</param> /// <param name="maxWidth">最大宽度</param> /// <param name="maxHeight">最大高度</param> public static void MakeThumbnailImage(string fileName, string newFileName, int maxWidth, int maxHeight) { //2012-02-05修改过,支持替换 byte[] imageBytes = File.ReadAllBytes(fileName); Image img = Image.FromStream(new System.IO.MemoryStream(imageBytes)); MakeThumbnailImage(img, newFileName, maxWidth, maxHeight); //原文 //MakeThumbnailImage(Image.FromFile(fileName), newFileName, maxWidth, maxHeight); } #region 2012-2-19 新增生成图片缩略图方法 /// <summary> /// 生成缩略图 /// </summary> /// <param name="fileName">源图路径(绝对路径)</param> /// <param name="newFileName">缩略图路径(绝对路径)</param> /// <param name="width">缩略图宽度</param> /// <param name="height">缩略图高度</param> /// <param name="mode">生成缩略图的方式</param> public static void MakeThumbnailImage(string fileName, string newFileName, int width, int height, string mode) { Image originalImage = Image.FromFile(fileName); int towidth = width; int toheight = height; int x = 0; int y = 0; int ow = originalImage.Width; int oh = originalImage.Height; switch (mode) { case "HW"://指定高宽缩放(可能变形) break; case "W"://指定宽,高按比例 toheight = originalImage.Height * width / originalImage.Width; break; case "H"://指定高,宽按比例 towidth = originalImage.Width * height / originalImage.Height; break; case "Cut"://指定高宽裁减(不变形) if ((double)originalImage.Width / (double)originalImage.Height > (double)towidth / (double)toheight) { oh = originalImage.Height; ow = originalImage.Height * towidth / toheight; y = 0; x = (originalImage.Width - ow) / 2; } else { ow = originalImage.Width; oh = originalImage.Width * height / towidth; x = 0; y = (originalImage.Height - oh) / 2; } break; default: break; } //新建一个bmp图片 Bitmap b = new Bitmap(towidth, toheight); try { //新建一个画板 Graphics g = Graphics.FromImage(b); //设置高质量插值法 g.InterpolationMode = InterpolationMode.HighQualityBicubic; //设置高质量,低速度呈现平滑程度 g.SmoothingMode = SmoothingMode.AntiAlias; g.PixelOffsetMode = PixelOffsetMode.HighQuality; //清空画布并以透明背景色填充 g.Clear(Color.Transparent); //在指定位置并且按指定大小绘制原图片的指定部分 g.DrawImage(originalImage, new Rectangle(0, 0, towidth, toheight), new Rectangle(x, y, ow, oh), GraphicsUnit.Pixel); SaveImage(b, newFileName, GetCodecInfo("image/" + GetFormat(newFileName).ToString().ToLower())); } catch (System.Exception e) { throw e; } finally { originalImage.Dispose(); b.Dispose(); } } #endregion #region 2012-10-30 新增图片裁剪方法 /// <summary> /// 裁剪图片并保存 /// </summary> /// <param name="fileName">源图路径(绝对路径)</param> /// <param name="newFileName">缩略图路径(绝对路径)</param> /// <param name="maxWidth">缩略图宽度</param> /// <param name="maxHeight">缩略图高度</param> /// <param name="cropWidth">裁剪宽度</param> /// <param name="cropHeight">裁剪高度</param> /// <param name="X">X轴</param> /// <param name="Y">Y轴</param> public static bool MakeThumbnailImage(string fileName, string newFileName, int maxWidth, int maxHeight, int cropWidth, int cropHeight, int X, int Y) { byte[] imageBytes = File.ReadAllBytes(fileName); Image originalImage = Image.FromStream(new System.IO.MemoryStream(imageBytes)); Bitmap b = new Bitmap(cropWidth, cropHeight); try { using (Graphics g = Graphics.FromImage(b)) { //设置高质量插值法 g.InterpolationMode = InterpolationMode.HighQualityBicubic; //设置高质量,低速度呈现平滑程度 g.SmoothingMode = SmoothingMode.AntiAlias; g.PixelOffsetMode = PixelOffsetMode.HighQuality; //清空画布并以透明背景色填充 g.Clear(Color.Transparent); //在指定位置并且按指定大小绘制原图片的指定部分 g.DrawImage(originalImage, new Rectangle(0, 0, cropWidth, cropHeight), X, Y, cropWidth, cropHeight, GraphicsUnit.Pixel); Image displayImage = new Bitmap(b, maxWidth, maxHeight); SaveImage(displayImage, newFileName, GetCodecInfo("image/" + GetFormat(newFileName).ToString().ToLower())); return true; } } catch (System.Exception e) { throw e; } finally { originalImage.Dispose(); b.Dispose(); } } #endregion /// <summary> /// 制作远程缩略图 /// </summary> /// <param name="url">图片URL</param> /// <param name="newFileName">新图路径</param> /// <param name="maxWidth">最大宽度</param> /// <param name="maxHeight">最大高度</param> public static void MakeRemoteThumbnailImage(string url, string newFileName, int maxWidth, int maxHeight) { Stream stream = GetRemoteImage(url); if (stream == null) return; Image original = Image.FromStream(stream); stream.Close(); MakeThumbnailImage(original, newFileName, maxWidth, maxHeight); } /// <summary> /// 获取图片流 /// </summary> /// <param name="url">图片URL</param> /// <returns></returns> private static Stream GetRemoteImage(string url) { HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url); request.Method = "GET"; request.ContentLength = 0; request.Timeout = 20000; HttpWebResponse response = null; try { response = (HttpWebResponse)request.GetResponse(); return response.GetResponseStream(); } catch { return null; } } #region 动态剪切图片 2015年3-25日陈卧龙 /// <summary> /// 动态裁剪图片并保存 /// </summary> /// <param name="fileName">源图路径(绝对路径)</param> /// <param name="newFileName">缩略图路径(绝对路径)</param> /// <param name="num">将图片规则剪裁成的份数 规则图形 应该为偶数</param> ///算法代码参考:http://blog.163.com/smhily_min/blog/static/75206226201132815412644/ /// /// <param name="X">X轴</param> /// <param name="Y">Y轴</param> /// <param name="Xnum">水平切割的份数</param> /// <param name="Ynum">竖直切割的份数</param> /// <param name="i">for循环参数i</param> /// <returns></returns> public static bool cutImage(string fileName, string newFileName, int Xnum,int Ynum ,int i) { int maxWidth; int maxHeight; int cropWidth; int cropHeight; int X; int Y; // using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read)) { System.Drawing.Image image = System.Drawing.Image.FromStream(fs); int width = image.Width; int height = image.Height; maxWidth = cropWidth = (int)Math.Round(Convert.ToDecimal(width / Xnum)); maxHeight = cropHeight = (int)Math.Round(Convert.ToDecimal(height / Ynum)); // X = (i % Xnum) * (width / Xnum); Y = (int)Math.Floor(Convert.ToDecimal(i / Xnum)) * (int)Math.Round(Convert.ToDecimal(height / Ynum)); } // byte[] imageBytes = File.ReadAllBytes(fileName); Image originalImage = Image.FromStream(new System.IO.MemoryStream(imageBytes)); Bitmap b = new Bitmap(cropWidth, cropHeight); try { using (Graphics g = Graphics.FromImage(b)) { //设置高质量插值法 g.InterpolationMode = InterpolationMode.HighQualityBicubic; //设置高质量,低速度呈现平滑程度 g.SmoothingMode = SmoothingMode.AntiAlias; g.PixelOffsetMode = PixelOffsetMode.HighQuality; //清空画布并以透明背景色填充 g.Clear(Color.Transparent); //在指定位置并且按指定大小绘制原图片的指定部分 g.DrawImage(originalImage, new Rectangle(0, 0, cropWidth, cropHeight), X, Y, cropWidth, cropHeight, GraphicsUnit.Pixel); Image displayImage = new Bitmap(b, maxWidth, maxHeight); SaveImage(displayImage, newFileName, GetCodecInfo("image/" + GetFormat(newFileName).ToString().ToLower())); return true; } } catch (System.Exception e) { throw e; } finally { originalImage.Dispose(); b.Dispose(); } } #endregion #region 图片旋转函数 /// <summary> /// 以逆时针为方向对图像进行旋转 Bitmap的用法:http://blog.sina.com.cn/s/blog_4bc3dab30100ccph.html /// </summary> /// <param name="b">位图流</param> /// <param name="angle">旋转角度[0,360](前台给的)</param> /// <returns></returns> public static Bitmap Rotate(Bitmap b, int angle) { angle = angle % 360; //弧度转换 double radian = angle * Math.PI / 180.0; double cos = Math.Cos(radian); double sin = Math.Sin(radian); //原图的宽和高 int w = b.Width; int h = b.Height; int W = (int)(Math.Max(Math.Abs(w * cos - h * sin), Math.Abs(w * cos + h * sin))); int H = (int)(Math.Max(Math.Abs(w * sin - h * cos), Math.Abs(w * sin + h * cos))); //目标位图 Bitmap dsImage = new Bitmap(W, H); System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(dsImage); g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.Bilinear; g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; //计算偏移量 Point Offset = new Point((W - w) / 2, (H - h) / 2); //构造图像显示区域:让图像的中心与窗口的中心点一致 Rectangle rect = new Rectangle(Offset.X, Offset.Y, w, h); Point center = new Point(rect.X + rect.Width / 2, rect.Y + rect.Height / 2); g.TranslateTransform(center.X, center.Y); g.RotateTransform(360 - angle); //恢复图像在水平和垂直方向的平移 g.TranslateTransform(-center.X, -center.Y); g.DrawImage(b, rect); //重至绘图的所有变换 g.ResetTransform(); g.Save(); g.Dispose(); //dsImage.Save("yuancd.jpg", System.Drawing.Imaging.ImageFormat.Jpeg); return dsImage; } #endregion 图片旋转函数 }
通过Base64编码来上传图片的代码如下:

public class PicHandler : IHttpHandler { public static string CmdocumentUrl = ConfigurationManager.AppSettings["CmdocumentUrl"]; public static readonly string BaseDir = ConfigurationManager.AppSettings["BaseDir"]; public void ProcessRequest(HttpContext context) { if (HttpContext.Current.Request.QueryString["action"] == "action") { try { WeLogHelper.WriteLog("上传图片开始"); uppic(); } catch(Exception ex) { WeLogHelper.WriteLog(ex.ToString()); } } context.Response.ContentType = "text/plain"; } protected void uppic() { //13 代表现场考察打分附件 DocumentTypeIdEnum keyword = (DocumentTypeIdEnum)Enum.ToObject(typeof(DocumentTypeIdEnum), 13); string pic = HttpContext.Current.Request.Form["images"]; pic = HttpContext.Current.Server.UrlDecode(pic); if (pic != null) { var imgData = pic.Split(',')[1]; string dummyData = imgData.Trim().Replace("%", "").Replace(",", "").Replace(" ", "+"); if (dummyData.Length % 4 > 0) { dummyData = dummyData.PadRight(dummyData.Length + 4 - dummyData.Length % 4, '='); } byte[] byteArray = Convert.FromBase64String(dummyData); MemoryStream stream = new MemoryStream(byteArray); Bitmap image = new Bitmap(stream); string kkpath = Guid.NewGuid().ToString(); string serverPath = BaseDir + "/" + kkpath + "/"; // string serverPath = HttpContext.Current.Server.MapPath(fileurl); if (Directory.Exists(serverPath) == false)//如果不存在就创建file文件夹 { Directory.CreateDirectory(serverPath); } string picNum = Guid.NewGuid().ToString("N"); string relativeUri = "/" + kkpath.ToString() + "/" + picNum + ".png"; string url = serverPath + picNum + ".png"; image.Save(url); // #region 生成缩略图 string Uri = BaseDir + relativeUri; //缩略图名称 string SLT_PicName = Guid.NewGuid().ToString("N") + ".png"; string SLT_url = serverPath + SLT_PicName; //WeLogHelper.WriteLog("缩略图:" + SLT_url); PicManger.MakeThumbnailImage(url, SLT_url, 100, 100, "Cut"); //PicManger.SaveImage(bpmImg, SLT_url, PicManger.GetCodecInfo("image/" + PicManger.GetFormat(SLT_PicName).ToString().ToLower())); #endregion string Base64SR = "data:image/png;base64," + new InspectionRatingSeeModel().ImgToBase64String(SLT_url); DocumentM M = new DocumentM() { DocumentId=Convert.ToInt64(DateTime.Now.ToString("yyMMddhhmmss")), DocumentName = Path.GetFileName(picNum + ".png"), DocumentPath = serverPath, DocumentTypeId = keyword, CreateUserName = "", Url = relativeUri, Documenttemppath=SLT_url, DocRealPath= CmdocumentUrl + relativeUri, DocBase64SR= Base64SR }; // WeLogHelper.WriteLog("缩略图:"+SLT_url); var MJson = JsonHelper.JsonSerializer(M); // //WeLogHelper.WriteLog(MJson); HttpContext.Current.Response.Write(MJson); } HttpContext.Current.Response.End(); } public bool IsReusable { get { return false; } } }
生成Base64编码的方法如下:

public String ImgToBase64String(string fileName) { FileInfo file = new FileInfo(fileName); var stream = file.OpenRead(); byte[] buffer = new byte[file.Length]; //读取图片字节流 stream.Read(buffer, 0, Convert.ToInt32(file.Length)); //将字节流转化成base64字符串 return Convert.ToBase64String(buffer); }
生成的Base64编码如果想要展示出来,就需要加上前缀,前缀要结合图片的扩展名,如下:

foreach (var item in RatingModel.CmDocumentList) { string Uri = item.Documenttemppath; item.DocBase64SR = "data:image/png;base64,"+ImgToBase64String(Uri); //WeLogHelper.WriteLog(item.DocBase64SR); }
Uri为绝对路径!
前端调用如下:

<ul> <li class="weui-uploader__file" style="background-image:url(@item.DocBase64SR)"> <div class="weui-uploader__file-content"></div> </li>
本博客都是精华!请笑纳!哈哈哈!
谢谢!