欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

.NET生成水印更好的方法实例代码

程序员文章站 2022-04-28 20:42:56
前言 众所周知为了保护知识产权,防止资源被盗用,水印在博客、网店等场景中非常常见。 本文首先演示了基于system.drawing.image做正常操作。然后基于dir...

前言

众所周知为了保护知识产权,防止资源被盗用,水印在博客、网店等场景中非常常见。

本文首先演示了基于system.drawing.image做正常操作。然后基于direct2d/wic/directwrite,演示了一种全新、不同的“骚”操作。

方法1-system.drawing给图片加水印

system.drawing.image原生属于gdi的一部分,是windows only,但随着nuget包system.drawing.common的发布,现在system.drawing.image已经支持linux:

install-package system.drawing.common -version 4.5.1

以下代码演示了如何从给图片加水印:

// 加水印
var watermarkedstream = new memorystream();
using (var img = image.fromstream(file.openread(@"d:\_\watermarkdemo.png")))
{
 using (var graphic = graphics.fromimage(img))
 {
  var font = new font("微软雅黑", 30, fontstyle.bold, graphicsunit.pixel);
  var color = color.fromargb(128, 255, 255, 255);
  var brush = new solidbrush(color);
  var point = new point(img.width - 130, img.height - 50);

  graphic.drawstring("水印在此", font, brush, point);
  img.save(watermarkedstream, imageformat.png);
 }
}

效果如图(没有黄色剪头):

.NET生成水印更好的方法实例代码

附:edi.wang做了一个nuget包,可以轻松地配置水印参数:

nuget:https://github.com/ediwang/edi.imagewatermark

文章:https://edi.wang/post/2018/10/12/add-watermark-to-uploaded-image-aspnet-core

方法2-direct2d/wic给图片加水印

direct2d源于windows 8/ie 10,安装ie 10之后,windows 7也能用。direct2d基于direct3d,很显然,是windows only的。

direct2d是windows下一代的2d渲染库,随着direct2d一起发布的,还有windows imaging component(简称wic)和directwrite。

相关说明和文档链接:

技术 说明 链接
direct2d 基于硬件加速的2d图形渲染 go
wic 高性能图片编码、解码 go
directwrite 基于硬件加速的文字渲染 go

如果您打开链接看了一眼,就不难看出,这些技术都是基于com的,但我们使用.net,不是吗?

好在我们有sharpdx

sharpdx对这些directx技术做了封装,在这个demo中,我们需要安装sharpdx.direct2d1和sharpdx.mathematics两个包:

install-package sharpdx.direct2d1 -version 4.2.0
install-package sharpdx.mathematics -version 4.2.0

以下代码演示了如何使用sharpdx.direct2d1给图片加水印:

using d2d = sharpdx.direct2d1;
using dwrite = sharpdx.directwrite;
using sharpdx;
using sharpdx.io;
using wic = sharpdx.wic;

memorystream addwatermark(stream filename, string watermarktext)
{
  using (var wic = new wic.imagingfactory2())
  using (var d2d = new d2d.factory())
  using (var image = createwicimage(wic, filename))
  using (var wicbitmap = new wic.bitmap(wic, image.size.width, image.size.height, wic.pixelformat.format32bpppbgra, wic.bitmapcreatecacheoption.cacheondemand))
  using (var target = new d2d.wicrendertarget(d2d, wicbitmap, new d2d.rendertargetproperties()))
  using (var bmppicture = d2d.bitmap.fromwicbitmap(target, image))
  using (var dwritefactory = new sharpdx.directwrite.factory())
  using (var brush = new d2d.solidcolorbrush(target, new color(0xff, 0xff, 0xff, 0x7f)))
  {
    target.begindraw();
    {
      target.drawbitmap(bmppicture, new rectanglef(0, 0, target.size.width, target.size.height), 1.0f, d2d.bitmapinterpolationmode.linear);
      target.drawrectangle(new rectanglef(0, 0, target.size.width, target.size.height), brush);
      var textformat = new dwrite.textformat(dwritefactory, "微软雅黑", dwrite.fontweight.bold, dwrite.fontstyle.normal, 30.0f);
      target.drawtext(watermarktext, textformat, new rectanglef(target.size.width - 130, target.size.height - 50, int.maxvalue, int.maxvalue), brush);
    }
    target.enddraw();

    var ms = new memorystream();
    saved2dbitmap(wic, wicbitmap, ms);
    return ms;
  }
}

void saved2dbitmap(wic.imagingfactory wicfactory, wic.bitmap wicbitmap, stream outputstream)
{
  using (var encoder = new wic.bitmapencoder(wicfactory, wic.containerformatguids.png))
  {
    encoder.initialize(outputstream);
    using (var frame = new wic.bitmapframeencode(encoder))
    {
      frame.initialize();
      frame.setsize(wicbitmap.size.width, wicbitmap.size.height);

      var pixelformat = wicbitmap.pixelformat;
      frame.setpixelformat(ref pixelformat);
      frame.writesource(wicbitmap);

      frame.commit();
      encoder.commit();
    }
  }
}

wic.formatconverter createwicimage(wic.imagingfactory wicfactory, stream stream)
{
  using (var decoder = new wic.pngbitmapdecoder(wicfactory))
  {
    var decodestream = new wic.wicstream(wicfactory, stream);
    decoder.initialize(decodestream, wic.decodeoptions.cacheonload);
    using (var decodeframe = decoder.getframe(0))
    {
      var converter = new wic.formatconverter(wicfactory);
      converter.initialize(decodeframe, wic.pixelformat.format32bpppbgra);
      return converter;
    }
  }
}

调用方式:

file.writeallbytes(@"d:\_\demo2.png", addwatermark(file.openread(@"d:\_\watermarkdemo.png"), "水印在此").toarray());

效果也是一切正常:

.NET生成水印更好的方法实例代码

有什么区别?

system.drawing只花了14行,direct2d却需要整整60行!复杂程度惊人!为什么要舍简单求复杂呢?

因为system.drawing没有硬件加速,而且生成的图片也没有反走样(anti-aliasing),这导致使用system.drawing相比之下较慢,而且生成图片的效果稍差:

.NET生成水印更好的方法实例代码

很明显可以看出,direct2d生成的图片更平滑。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。