引用:SixLabors.ImageSharp,SixLabors.ImageSharp.Drawing,System.Drawing.Common
/// <summary> /// 羣組圖片合併 /// </summary> public static class ImageSharpHelper { /// <summary> /// 背景圖片縮略圖大小 /// </summary> public static int BackHeigth = 210; #region 獲取合併後的圖片 /// <summary> /// 獲取合併後的圖片 /// </summary> /// <param name="ImageFile">要合併的圖片路徑</param> /// <returns></returns> public static ApiResult GetImageSharp(List<string> ImageFile) { if (ImageFile.Count <= 1 || ImageFile.Count > 9) { return ApiResult.Fail(ApiEnum.OtherError, "合併的圖片只能2到9張"); } //背景圖 var aBase64Str = @"iVBORw0KGgoAAAANSUhEUgAAALEAAACxCAIAAAAES8uSAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMTM4IDc5LjE1OTgyNCwgMjAxNi8wOS8xNC0wMTowOTowMSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTcgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkE4OTBFNDM1OTMwQjExRTlBN0ZBOTQyQzFCQjg0MzRBIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkE4OTBFNDM2OTMwQjExRTlBN0ZBOTQyQzFCQjg0MzRBIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6QTg5MEU0MzM5MzBCMTFFOUE3RkE5NDJDMUJCODQzNEEiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6QTg5MEU0MzQ5MzBCMTFFOUE3RkE5NDJDMUJCODQzNEEiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7toEL7AAABQ0lEQVR42uzSQREAAAQAQfRPoiRfHexGuLmcDrhKAjyBJ/AEnsATeAJP4Ak8gSfwBJ7AE3gCT+AJ8ASewBN4Ak/gCTyBJ/AEnsATeAJP4Ak8gSfAE3gCT+AJPIEn8ASewBN4Ak/gCTyBJ/AEngBP4Ak8gSfwBJ7AE3gCT+AJPIEn8ASewBN4AjyBJ/AEnsATeAJP4Ak8gSfwBJ7AE3gCT+AJ8ASewBN4Ak/gCTyBJ/AEnsATeAJP4Ak8gSfAE3gCT+AJPIEn8ASewBN4Ak/gCTyBJ/AEngBP4Ak8gSfwBJ7AE3gCT+AJPIEn8ASewBN4Ak9IgCfwBJ7AE3gCT+AJPIEn8ASewBN4Ak/gCTwBnsATeAJP4Ak8gSfwBJ7AE3gCT+AJPIEn8AR4Ak/gCTyBJ/AEnsATeAJP4Ak8gSfwBI+sAAMAmMcDC6uBzccAAAAASUVORK5CYII="; List<byte[]> list = new List<byte[]>(); foreach (var item in ImageFile) { list.Add(GetImageByte(item)); } return ImageCaoByte(Convert.FromBase64String(aBase64Str), list); } #endregion #region 合併圖片 base64 List集合 /// <summary> /// 合併圖片 base64 List集合 /// </summary> /// <param name="backBase64">背景圖片</param> /// <param name="ListBase64">合成圖片集合</param> /// <returns></returns> public static ApiResult ImageCaoBase64(string backBase64, List<string> ListBase64) { List<byte[]> list = new List<byte[]>(); foreach (var item in ListBase64) { list.Add(Convert.FromBase64String(item)); } return ImageCaoByte(Convert.FromBase64String(backBase64), list); #region 單張測試 //byte[] templebytes = Convert.FromBase64String(aBase64Str); //byte[] outputbytes = Convert.FromBase64String(bBase64Str); //System.Drawing.Image temple = MakeThumbnail(templebytes, 200, 200, ThumbnailMode.Cut); //System.Drawing.Image output = MakeThumbnail(outputbytes, 100, 100, ThumbnailMode.Cut); //var templeNailByte = ImgToByt(temple); //var outputNailByte = ImgToByt(output); //IImageFormat format = null; //Image<Rgba32> templeRgba32= SixLabors.ImageSharp.Image.Load(templeNailByte, out format); //Image<Rgba32> outputRgba32 = SixLabors.ImageSharp.Image.Load(outputNailByte); //var result = MergeImageRgba32(templeRgba32, outputRgba32, 0, 0, format); //return result; #endregion } #endregion #region 合併圖片 字節 List集合 /// <summary> /// 合併圖片 字節 List集合 /// </summary> /// <param name="backBase64">背景圖片</param> /// <param name="ListBase64">合成圖片集合</param> /// <returns></returns> public static ApiResult ImageCaoByte(byte[] backBase64, List<byte[]> ListBase64) { //base64轉字節 byte[] templebytes = backBase64;// Convert.FromBase64String(backBase64); //縮略圖 System.Drawing.Image temple = MakeThumbnail(templebytes, BackHeigth, BackHeigth, ThumbnailMode.Cut); //圖片轉字節 byte[] templeNailByte = ImgToByt(temple); ApiResult result = ApiResult.Fail(ApiEnum.OtherError, "請求失敗"); var ListCount = ListBase64.Count; for (int i = 0; i < ListCount; i++) { byte[] outputbytes = ListBase64[i]; System.Drawing.Image output = MakeThumbnail(outputbytes, SizeWidth(ListCount, BackHeigth), SizeHeight(ListCount, BackHeigth), ThumbnailMode.Cut); byte[] outputNailByte = ImgToByt(output); Image<Rgba32> outputRgba32 = SixLabors.ImageSharp.Image.Load(outputNailByte); //背景圖 IImageFormat format = null; Image<Rgba32> templeRgba32 = SixLabors.ImageSharp.Image.Load(templeNailByte, out format); //合併圖片 result = MergeImageRgba32(templeRgba32, outputRgba32, XWidth(ListCount, i + 1, BackHeigth), YHeight(ListCount, i + 1, BackHeigth), format); if (i < ListCount - 1 && result.Status) { var str = result.Data.ToString(); var dataBase64 = str.Substring(str.IndexOf(',') + 1); templeNailByte = Convert.FromBase64String(dataBase64); } } return result; } #endregion #region 合併圖片 小圖片放在大圖片上面 MergeImageBase64 /// <summary> /// 合併圖片 小圖片放在大圖片上面 MergeImageBase64 /// </summary> /// <param name="TempleBase64Str">模板大圖片base64</param> /// <param name="OutputBase64Str">模板小圖片base64</param> /// <param name="x">X座標</param> /// <param name="y">y座標</param> /// <returns></returns> public static ApiResult MergeImageBase64(string TempleBase64Str, string OutputBase64Str, int x, int y) { string strRet = null; if (string.IsNullOrEmpty(TempleBase64Str)) { return ApiResult.Fail(ApiEnum.ParameterError, "請傳入模板大圖片base64"); } if (string.IsNullOrEmpty(OutputBase64Str)) { return ApiResult.Fail(ApiEnum.ParameterError, "請傳入模板小圖片base64"); } if (x < 0 || y < 0) { return ApiResult.Fail(ApiEnum.ParameterError, "座標不能傳入負數"); } try { byte[] templebytes = Convert.FromBase64String(TempleBase64Str); byte[] outputbytes = Convert.FromBase64String(OutputBase64Str); IImageFormat format = null; var imagesTemle = SixLabors.ImageSharp.Image.Load(templebytes, out format); var outputImg = SixLabors.ImageSharp.Image.Load(outputbytes); if (imagesTemle.Height - (outputImg.Height + y) <= 0) { return ApiResult.Fail(ApiEnum.ParameterError, "Y座標高度超限"); } if (imagesTemle.Width - (outputImg.Width + x) <= 0) { return ApiResult.Fail(ApiEnum.ParameterError, "X座標寬度超限"); } //進行多圖片處理 imagesTemle.Mutate(a => { //仍是合併 a.DrawImage(outputImg, new SixLabors.Primitives.Point(x, y), 1); }); strRet = imagesTemle.ToBase64String(format); return ApiResult.Success(strRet); } catch (Exception ex) { return ApiResult.Fail(ApiEnum.ParameterError, "報錯信息" + ex.Message); } } #endregion #region 合併圖片 小圖片放在大圖片上面 MergeImageRgba32 /// <summary> /// 合併圖片 小圖片放在大圖片上面 MergeImageRgba32 /// </summary> /// <param name="TempleByte">模板大圖片Byte</param> /// <param name="OutputBaseByte">模板小圖片Byte</param> /// <param name="x">X座標</param> /// <param name="y">y座標</param> /// <param name="format">format</param> /// <returns></returns> public static ApiResult MergeImageRgba32(Image<Rgba32> TempleByte, Image<Rgba32> OutputBaseByte, int x, int y, IImageFormat format) { string strRet = null; if (x < 0 || y < 0) { return ApiResult.Fail(ApiEnum.ParameterError, "座標不能傳入負數"); } try { var imagesTemle = TempleByte; var outputImg = OutputBaseByte; if (imagesTemle.Height - (outputImg.Height + y) < 0) { return ApiResult.Fail(ApiEnum.ParameterError, "Y座標高度超限"); } if (imagesTemle.Width - (outputImg.Width + x) < 0) { return ApiResult.Fail(ApiEnum.ParameterError, "X座標寬度超限"); } //進行多圖片處理 imagesTemle.Mutate(a => { //仍是合併 a.DrawImage(outputImg, new SixLabors.Primitives.Point(x, y), 1); }); strRet = imagesTemle.ToBase64String(format); return ApiResult.Success(strRet, "成功"); } catch (Exception ex) { return ApiResult.Fail(ApiEnum.ParameterError, "報錯信息" + ex.Message); } } #endregion #region 生成縮略圖 /// <summary> /// 生成縮略圖 /// </summary> /// <param name="imgBytes">源文件字節數組</param> /// <param name="width">縮略圖寬度</param> /// <param name="height">縮略圖高度</param> /// <param name="mode">縮略圖方式</param> public static System.Drawing.Image MakeThumbnail(byte[] imgBytes, int width, int height, ThumbnailMode mode) { using (var sourceImage = FromBytes(imgBytes)) { return MakeThumbnailThis(sourceImage, width, height, mode); } } /// <summary> /// 生成縮略圖 /// </summary> /// <param name="sourceImage">源圖</param> /// <param name="width">縮略圖寬度</param> /// <param name="height">縮略圖高度</param> /// <param name="mode">縮略圖方式</param> public static System.Drawing.Image MakeThumbnailThis(System.Drawing.Image sourceImage, int width, int height, ThumbnailMode mode) { var towidth = width; var toheight = height; var x = 0; var y = 0; var ow = sourceImage.Width; var oh = sourceImage.Height; switch (mode) { case ThumbnailMode.FixedBoth: break; case ThumbnailMode.FixedW: toheight = oh * width / ow; break; case ThumbnailMode.FixedH: towidth = ow * height / oh; break; case ThumbnailMode.Cut: if (ow / (double)oh > towidth / (double)toheight) { oh = sourceImage.Height; ow = sourceImage.Height * towidth / toheight; y = 0; x = (sourceImage.Width - ow) / 2; } else { ow = sourceImage.Width; oh = sourceImage.Width * height / towidth; x = 0; y = (sourceImage.Height - oh) / 2; } break; } //一、新建一個BMP圖片 var bitmap = new Bitmap(towidth, toheight); //二、新建一個畫板 var g = Graphics.FromImage(bitmap); try { //三、設置高質量插值法 g.InterpolationMode = InterpolationMode.High; //四、設置高質量,低速度呈現平滑程度 g.SmoothingMode = SmoothingMode.HighQuality; //五、清空畫布並以透明背景色填充 g.Clear(Color.Transparent); //六、在指定位置而且按指定大小繪製原圖片的指定部分 g.DrawImage(sourceImage, new Rectangle(0, 0, towidth, toheight), new Rectangle(x, y, ow, oh), GraphicsUnit.Pixel); return bitmap; } catch (Exception e) { throw e; } finally { g.Dispose(); } } #endregion #region 字節轉換成圖片流 /// <summary> /// 字節轉換成圖片流 /// </summary> /// <param name="bytes">字節數組</param> /// <returns></returns> public static System.Drawing.Image FromBytes(byte[] bytes) { using (var ms = new MemoryStream(bytes)) { return System.Drawing.Image.FromStream(ms); } } #endregion #region 圖片流轉換成字節 /// <summary> /// 圖片流轉換成字節 /// </summary> /// <param name="img">要轉換的Image對象</param> /// <returns>轉換後返回的字節流</returns> public static byte[] ImgToByt(System.Drawing.Image img) { MemoryStream ms = new MemoryStream(); byte[] imagedata = null; img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg); imagedata = ms.GetBuffer(); return imagedata; } #endregion #region 根據http圖片路徑返回圖片的字節流byte[] /// <summary> /// 根據http圖片路徑返回圖片的字節流byte[] /// </summary> /// <param name="imagePath">圖片路徑</param> /// <returns>返回的字節流</returns> public static byte[] GetImageByte(string imagePath) { WebClient client = new WebClient(); byte[] pageData = client.DownloadData(imagePath); return pageData; } #endregion #region 根據本機圖片路徑返回圖片的字節流byte[] /// <summary> /// 根據本機圖片路徑返回圖片的字節流byte[] /// </summary> /// <param name="imagePath">圖片路徑</param> /// <returns>返回的字節流</returns> public static byte[] GetImageByteIam(string imagePath) { FileStream files = new FileStream(imagePath, FileMode.Open); byte[] imgByte = new byte[files.Length]; files.Read(imgByte, 0, imgByte.Length); files.Close(); return imgByte; } #endregion #region 獲取小的縮略圖高度 /// <summary> /// 獲取小的縮略圖高度 /// </summary> /// <param name="Sum">總張數</param> /// <param name="BackHeigth">背景圖片的大小</param> /// <returns></returns> public static int SizeHeight(int Sum, int BackHeigth) { if (Sum <= 4) { return BackHeigth / 2; } else if (Sum > 4 && Sum <= 9) { return BackHeigth / 3; } return 0; } #endregion #region 獲取小的縮略圖寬度 /// <summary> /// 獲取小的縮略圖寬度 /// </summary> /// <param name="Sum">總張數</param> /// <param name="BackWidth">背景圖片的大小</param> /// <returns></returns> public static int SizeWidth(int Sum, int BackWidth) { if (Sum <= 4) { return BackHeigth / 2; } else if (Sum > 4 && Sum <= 9) { return BackHeigth / 3; } return 0; } #endregion #region 獲取X座標點 /// <summary> /// 獲取X座標點 /// </summary> /// <param name="Sum">總張數</param> /// <param name="Several">第幾張圖片</param> /// <param name="BackHeigth">背景圖片的大小</param> /// <returns></returns> public static int XWidth(int Sum, int Several, int BackHeigth) { if (Sum == 2) { return (Several - 1) * (BackHeigth / 2); } else if (Sum > 2 && Sum <= 4) { if (Several % 2 == 1) { return 0; } else { return BackHeigth / 2; } } else if (Sum > 4 && Sum <= 9) { if (Several % 3 == 1) { return 0; } else if (Several % 3 == 2) { return BackHeigth / 3; } else { return (BackHeigth / 3) * 2; } } return 0; } #endregion #region 獲取Y座標點 /// <summary> /// 獲取Y座標點 /// </summary> /// <param name="Sum">總張數</param> /// <param name="Several">第幾張圖片</param> /// <param name="BackHeigth">背景圖片的大小</param> /// <returns></returns> public static int YHeight(int Sum, int Several, int BackHeigth) { if (Sum == 2) { return BackHeigth / 4; } else if (Sum > 2 && Sum <= 4) { if (Several <= 2) { return 0; } else { return BackHeigth / 2; } } else if (Sum > 4 && Sum <= 6) { if (Several <= 3) { return BackHeigth / 6; } else { return BackHeigth / 2; } } else if (Sum > 6 && Sum <= 9) { if (Several <= 3) { return 0; } else if (Several > 3 && Several <= 6) { return BackHeigth / 3; } else { return (BackHeigth / 3) * 2; } } return 0; } #endregion } /// <summary> /// 縮略圖模式 /// </summary> public enum ThumbnailMode { /// <summary> /// 指定寬高裁剪(不變形) /// </summary> Cut = 1, /// <summary> /// 指定寬度,高度自動 /// </summary> FixedW = 2, /// <summary> /// 指定高度,寬度自動 /// </summary> FixedH = 4, /// <summary> /// 指定寬高(變形) /// </summary> FixedBoth = 8 }