WPF實現(xiàn)圖片合成或加水印的方法【2種方法】
本文實例講述了WPF實現(xiàn)圖片合成或加水印的方法。分享給大家供大家參考,具體如下:
最近項目中應用多次應用了圖片合成,為了今后方便特此記下。
在WPF下有兩種圖片合成的方式,一種還是用原來C#提供的GDI+方式,命名空間是System.Drawing 和 System.Drawing.Imaging,另一種是WPF中新添加的API,命名空間是 System.Windows.Media 和 System.Windows.Media.Imaging 。
我們來做一個簡單的例子,分別用上面的兩種方式實現(xiàn),功能是在一個背景圖上面,畫一個頭像,然后在寫一個簽名。
首先準備一張背景圖(bg.jpg)和兩個頭像圖片(tiger.png 和 lion.png)最后的生成的圖片效果如下圖:


把準備的素材拷貝到項目中,其文件屬性【復制到輸出目錄】選擇【始終復制】,【生成操作】選擇【內容】。
這里貼一下兩種方式的主要代碼,具體代碼可以在文章最后點擊下載。
第一種方式
使用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)建一個RenderTargetBitmap 對象,將WPF中的Visual對象輸出
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));
//計算頭像的位置
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));
//計算簽名的位置
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);
//定義一個JPG編碼器
JpegBitmapEncoder bitmapEncoder = new JpegBitmapEncoder();
//加入第一幀
bitmapEncoder.Frames.Add(BitmapFrame.Create(composeImage));
//保存至文件(不會修改源文件,將修改后的圖片保存至程序目錄下)
string savePath = System.AppDomain.CurrentDomain.SetupInformation.ApplicationBase + @"\合成.jpg";
bitmapEncoder.Save(File.OpenWrite(Path.GetFileName(savePath)));
return composeImage;
}
第二種方式
利用原來的GDI+方式
private BitmapSource MakePictureGDI(string bgImagePath, string headerImagePath, string signature)
{
GDI.Image bgImage = GDI.Bitmap.FromFile(bgImagePath);
GDI.Image headerImage = GDI.Bitmap.FromFile(headerImagePath);
//新建一個畫板,畫板的大小和底圖一致
System.Drawing.Bitmap bitmap = new System.Drawing.Bitmap(bgImage.Width, bgImage.Height);
System.Drawing.Graphics g = System.Drawing.Graphics.FromImage(bitmap);
//設置高質量插值法
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.High;
//設置高質量,低速度呈現(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 轉化成 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);//釋放對象
return bitmapSource;
}
#endregion
附:完整實例代碼點擊此處本站下載。
更多關于C#相關內容感興趣的讀者可查看本站專題:《C#常見控件用法教程》、《WinForm控件用法總結》、《C#數(shù)據(jù)結構與算法教程》、《C#面向對象程序設計入門教程》及《C#程序設計之線程使用技巧總結》
希望本文所述對大家C#程序設計有所幫助。
相關文章
C# Dictionary和SortedDictionary的簡介
今天小編就為大家分享一篇關于C# Dictionary和SortedDictionary的簡介,小編覺得內容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-10-10
MessageBox的Buttons和三級聯(lián)動效果
這篇文章主要介紹了MessageBox的Buttons和三級聯(lián)動的相關資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-11-11
C#中Abstract方法和Virtual方法的區(qū)別
這篇文章介紹了C#中Abstract方法和Virtual方法的區(qū)別,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-04-04
C# 中const,readonly,static的使用小結
這篇文章主要介紹了C# 中使用const,readonly,static的示例,幫助大家更好的理解和使用c#,感興趣的朋友可以了解下2021-01-01
C#實現(xiàn)xml文件反序列化讀入數(shù)據(jù)到object的方法
這篇文章主要介紹了C#實現(xiàn)xml文件反序列化讀入數(shù)據(jù)到object的方法,涉及C#操作XML文件類型轉換的相關技巧,具有一定參考借鑒價值,需要的朋友可以參考下2015-07-07
C#統(tǒng)計字符串中數(shù)字個數(shù)的方法
這篇文章主要介紹了C#統(tǒng)計字符串中數(shù)字個數(shù)的方法,涉及C#遍歷字符串并判斷數(shù)字的技巧,需要的朋友可以參考下2015-06-06

