前言

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

本文首先演示了基于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);
 }
}

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

附: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());

效果也是一切正常:

有什么区别?

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

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

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

总结

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