WPF實(shí)現(xiàn)圖片合成或加水印的方法【2種方法】
本文實(shí)例講述了WPF實(shí)現(xiàn)圖片合成或加水印的方法。分享給大家供大家參考,具體如下:
最近項(xiàng)目中應(yīng)用多次應(yīng)用了圖片合成,為了今后方便特此記下。
在WPF下有兩種圖片合成的方式,一種還是用原來(lái)C#提供的GDI+方式,命名空間是System.Drawing 和 System.Drawing.Imaging,另一種是WPF中新添加的API,命名空間是 System.Windows.Media 和 System.Windows.Media.Imaging 。
我們來(lái)做一個(gè)簡(jiǎn)單的例子,分別用上面的兩種方式實(shí)現(xiàn),功能是在一個(gè)背景圖上面,畫一個(gè)頭像,然后在寫一個(gè)簽名。
首先準(zhǔn)備一張背景圖(bg.jpg)和兩個(gè)頭像圖片(tiger.png 和 lion.png)最后的生成的圖片效果如下圖:
把準(zhǔn)備的素材拷貝到項(xiàng)目中,其文件屬性【復(fù)制到輸出目錄】選擇【始終復(fù)制】,【生成操作】選擇【內(nèi)容】。
這里貼一下兩種方式的主要代碼,具體代碼可以在文章最后點(diǎn)擊下載。
第一種方式
使用RenderTargetBitmap 和 DrawingVisual 方式
private BitmapSource MakePicture(string bgImagePath, string headerImagePath, string signature) { //獲取背景圖 BitmapSource bgImage = new BitmapImage(new Uri(bgImagePath, UriKind.Relative)); //獲取頭像 BitmapSource headerImage = new BitmapImage(new Uri(headerImagePath, UriKind.Relative)); //創(chuàng)建一個(gè)RenderTargetBitmap 對(duì)象,將WPF中的Visual對(duì)象輸出 RenderTargetBitmap composeImage = new RenderTargetBitmap(bgImage.PixelWidth, bgImage.PixelHeight, bgImage.DpiX, bgImage.DpiY, PixelFormats.Default); FormattedText signatureTxt = new FormattedText(signature, System.Globalization.CultureInfo.CurrentCulture, System.Windows.FlowDirection.LeftToRight, new Typeface(System.Windows.SystemFonts.MessageFontFamily, FontStyles.Normal, FontWeights.Normal, FontStretches.Normal), 50, System.Windows.Media.Brushes.White); DrawingVisual drawingVisual = new DrawingVisual(); DrawingContext drawingContext = drawingVisual.RenderOpen(); drawingContext.DrawImage(bgImage, new Rect(0, 0, bgImage.Width, bgImage.Height)); //計(jì)算頭像的位置 double x = (bgImage.Width / 2 - headerImage.Width) / 2; double y = (bgImage.Height - headerImage.Height) / 2 - 100; drawingContext.DrawImage(headerImage, new Rect(x, y, headerImage.Width, headerImage.Height)); //計(jì)算簽名的位置 double x2 = (bgImage.Width/2 - signatureTxt.Width) / 2; double y2 = y + headerImage.Height + 20; drawingContext.DrawText(signatureTxt, new System.Windows.Point(x2, y2)); drawingContext.Close(); composeImage.Render(drawingVisual); //定義一個(gè)JPG編碼器 JpegBitmapEncoder bitmapEncoder = new JpegBitmapEncoder(); //加入第一幀 bitmapEncoder.Frames.Add(BitmapFrame.Create(composeImage)); //保存至文件(不會(huì)修改源文件,將修改后的圖片保存至程序目錄下) string savePath = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase + @"\合成.jpg"; bitmapEncoder.Save(File.OpenWrite(Path.GetFileName(savePath))); return composeImage; }
第二種方式
利用原來(lái)的GDI+方式
private BitmapSource MakePictureGDI(string bgImagePath, string headerImagePath, string signature) { GDI.Image bgImage = GDI.Bitmap.FromFile(bgImagePath); GDI.Image headerImage = GDI.Bitmap.FromFile(headerImagePath); //新建一個(gè)畫板,畫板的大小和底圖一致 System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(bgImage.Width, bgImage.Height); System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bitmap); //設(shè)置高質(zhì)量插值法 g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High; //設(shè)置高質(zhì)量,低速度呈現(xiàn)平滑程度 g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality; //清空畫布并以透明背景色填充 g.Clear(System.Drawing.Color.Transparent); //先在畫板上面畫底圖 g.DrawImage(bgImage, new GDI.Rectangle(0, 0, bitmap.Width, bitmap.Height)); //再在畫板上畫頭像 int x = (bgImage.Width / 2 - headerImage.Width) / 2; int y = (bgImage.Height - headerImage.Height) / 2 - 100; g.DrawImage(headerImage, new GDI.Rectangle(x, y, headerImage.Width, headerImage.Height), new GDI.Rectangle(0, 0, headerImage.Width, headerImage.Height), GDI.GraphicsUnit.Pixel); //在畫板上寫文字 using (GDI.Font f = new GDI.Font("Arial", 20, GDI.FontStyle.Bold)) { using (GDI.Brush b = new GDI.SolidBrush(GDI.Color.White)) { float fontWidth = g.MeasureString(signature, f).Width; float x2 = (bgImage.Width / 2 - fontWidth) / 2; float y2 = y + headerImage.Height + 20; g.DrawString(signature, f, b, x2, y2); } } try { string savePath = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase + @"\GDI+合成.jpg"; bitmap.Save(savePath, System.Drawing.Imaging.ImageFormat.Jpeg); return ToBitmapSource(bitmap); } catch (System.Exception e) { throw e; } finally { bgImage.Dispose(); headerImage.Dispose(); g.Dispose(); } } #region GDI+ Image 轉(zhuǎn)化成 BitmapSource [System.Runtime.InteropServices.DllImport("gdi32")] static extern int DeleteObject(IntPtr o); public BitmapSource ToBitmapSource(GDI.Bitmap bitmap) { IntPtr ip = bitmap.GetHbitmap(); BitmapSource bitmapSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap( ip, IntPtr.Zero, System.Windows.Int32Rect.Empty, System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions()); DeleteObject(ip);//釋放對(duì)象 return bitmapSource; } #endregion
附:完整實(shí)例代碼點(diǎn)擊此處本站下載。
更多關(guān)于C#相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《C#常見控件用法教程》、《WinForm控件用法總結(jié)》、《C#數(shù)據(jù)結(jié)構(gòu)與算法教程》、《C#面向?qū)ο蟪绦蛟O(shè)計(jì)入門教程》及《C#程序設(shè)計(jì)之線程使用技巧總結(jié)》
希望本文所述對(duì)大家C#程序設(shè)計(jì)有所幫助。
相關(guān)文章
C# 無(wú)邊框窗體邊框陰影效果的簡(jiǎn)單實(shí)現(xiàn)
這篇文章介紹了C# 無(wú)邊框窗體邊框陰影效果的簡(jiǎn)單實(shí)現(xiàn),有需要的朋友可以參考一下2013-10-10C#實(shí)現(xiàn)數(shù)據(jù)包加密與解密實(shí)例詳解
這篇文章主要介紹了C#實(shí)現(xiàn)數(shù)據(jù)包加密與解密的方法,是一項(xiàng)很實(shí)用的技能,需要的朋友可以參考下2014-07-07.Net WInform開發(fā)筆記(三)談?wù)勛灾瓶丶?自定義控件)
自定義控件的出現(xiàn)有利于用戶更好的實(shí)現(xiàn)自己的想法,可以封裝一些常用的方法,屬性等等,本文詳細(xì)介紹一下自定義控件的實(shí)現(xiàn),感興趣的朋友可以了解下2013-01-01C#中的Hangfire和Quartz.NET 任務(wù)調(diào)度的區(qū)別解析
Hangfire 和 Quartz.NET 是兩種常見的 C# 任務(wù)調(diào)度庫(kù),它們有不同的特點(diǎn)和使用場(chǎng)景,本文給大家介紹C#中的Hangfire和Quartz.NET 任務(wù)調(diào)度的區(qū)別,感興趣的朋友一起看看吧2024-08-08WinForm導(dǎo)出文件為Word、Excel、文本文件的方法
這篇文章主要介紹了WinForm導(dǎo)出文件為Word、Excel、文本文件的方法,本文直接給出實(shí)現(xiàn)代碼,代碼中包含相應(yīng)注釋,需要的朋友可以參考下2015-03-03