WPF实现图片合成或加水印的方法【2种方法】
程序员文章站
2022-06-29 19:40:29
本文实例讲述了wpf实现图片合成或加水印的方法。分享给大家供大家参考,具体如下:
最近项目中应用多次应用了图片合成,为了今后方便特此记下。
在wpf下有两种图片合成的方...
本文实例讲述了wpf实现图片合成或加水印的方法。分享给大家供大家参考,具体如下:
最近项目中应用多次应用了图片合成,为了今后方便特此记下。
在wpf下有两种图片合成的方式,一种还是用原来c#提供的gdi+方式,命名空间是system.drawing 和 system.drawing.imaging,另一种是wpf中新添加的api,命名空间是 system.windows.media 和 system.windows.media.imaging 。
我们来做一个简单的例子,分别用上面的两种方式实现,功能是在一个背景图上面,画一个头像,然后在写一个签名。
首先准备一张背景图(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)); //创建一个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; //设置高质量,低速度呈现平滑程度 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#数据结构与算法教程》、《c#面向对象程序设计入门教程》及《c#程序设计之线程使用技巧总结》
希望本文所述对大家c#程序设计有所帮助。
上一篇: Excel利用剪贴板或错位引用将多列行数不一的数据复制粘帖到一列
下一篇: C# 基础入门--变量