基于golang制作倾斜图片水印保护图片来源

举报
小雨青年 发表于 2022/03/29 00:45:08 2022/03/29
【摘要】 目录 一、前言二、核心实现思路三、完整实现步骤1. 平铺水印图像2. 整体倾斜水印图像3. 调整水印区域和透明度 四、最后成品代码 一、前言 在我的上一篇文章中,我们学会了使用 im...

一、前言

在我的上一篇文章中,我们学会了使用

  • image/draw
  • image/jpeg和image/png

的库给图片添加水印。

在这里插入图片描述
但是这样做还是有些问题,因为这种处于角落的水印非常容易被人通过软件去掉。

所以我们的目标是给图片打成行的倾斜水印,带透明度的倾斜水印不影响视觉,并且不容易通过去水印工具去掉。

二、核心实现思路

go的image/draw库并没有原生的倾斜写入的方法,而网上的采取的方式则是获取图像数据,遍历像素进行输出。

我这里采用的方式是引入第三方库。

go get github.com/anthonynsimon/bild

  
 
  • 1

用到的方法是,倾斜图片

imgwatermark = transform.Rotate(imgwatermark, -45.0, nil)

  
 
  • 1

三、完整实现步骤

1. 平铺水印图像

一般来说,水印图会比要加载的图片要小很多,所以我们采用的方式一般是把水印图片平铺在现有图像上。

在这里插入图片描述
将水印图片铺满整个屏幕,每个水印之间保留一些像素点。

具体思路为

1.获取原图尺寸
2. 获取水印图尺寸
3. 遍历原图尺寸,给出第一个偏移量,初始化第一个水印图的位置
4. 设定每个水印图的x轴偏移量,在写入水印+偏移量之后,判断第一行是否写入完成
5. 第一行写完之后,y轴偏移量=初始偏移量+水印高度+水印行间距,再写入下一行
6. 判断当前坐标的点是否还在图像上,如果已经不在图像上,则说明水印图片平铺完成

这部分的核心代码如下所示

	x, y := 0, 0
	for y <= m.Bounds().Max.Y {
		for x <= m.Bounds().Max.X {
			offset := image.Pt(x, y)
			draw.Draw(m, imgwatermark.Bounds().Add(offset), imgwatermark, image.ZP, draw.Over)
			x += imgwatermark.Bounds().Dx()
		}
		y += imgwatermark.Bounds().Dy()
		x = 0
	}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

最终得到的结果如下

在这里插入图片描述

这样就达到了平铺水印的效果啦!!!

2. 整体倾斜水印图像

实现思路如下

  1. 新建一个空白图片,尺寸和原图一致
  2. 平铺水印图片到空白图片上
  3. 整体倾斜空白图片

代码层面要注意点 ,转换图像的是image.Image而合并图像的是image.NewNRGBA,需要用下面转换下再进行图片倾斜

m2 := image.Image(m)

  
 
  • 1

倾斜并存储的代码如下

	m2 := image.Image(m)
	m2 = transform.Rotate(m2, 30.0, nil)

	//输出图像
	imgw, _ := os.Create("new.jpg")
	jpeg.Encode(imgw, m2, &jpeg.Options{100})

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

效果如下

在这里插入图片描述

3. 调整水印区域和透明度

这里处理问题的解决思路是

  1. 计算因为倾斜导致多出来的宽高
  2. 图片叠加修改透明度
  3. 整理图片叠加顺序

处理代码如下

b := imgbinfo.Bounds()
	watermarkbg := image.NewNRGBA(image.Rect(0, 0, b.Dx()*4, b.Dy()*4))

	m := image.NewNRGBA(b) //按原图生成新图

	draw.Draw(m, b, imgbinfo, image.ZP, draw.Src) //写入原图

	x, y := 0, 0
	offsetX, offsetY := 2, 25
	maxX := watermarkbg.Bounds().Max.X * 4
	maxY := watermarkbg.Bounds().Max.Y * 4
	for y <= maxY {
		for x <= maxX {
			offset := image.Pt(x, y)
			draw.Draw(watermarkbg, imgwatermark.Bounds().Add(offset), imgwatermark, image.ZP, draw.Over)
			x += imgwatermark.Bounds().Dx()
			x += offsetX
		}
		y += imgwatermark.Bounds().Dy()
		y += offsetY
		x = 0
	}

	watermarkbg2 := image.Image(watermarkbg)
	watermarkbg2 = transform.Rotate(watermarkbg2, -40.0, nil)
	mask := image.NewUniform(color.Alpha{30})
	draw.DrawMask(m, watermarkbg2.Bounds().Add(image.Pt(-watermarkbg2.Bounds().Dx()/2, 0)), watermarkbg2, image.ZP, mask, image.Point{-100, -100}, draw.Over)
	imgw, _ := os.Create("new.jpg")
	jpeg.Encode(imgw, m, &jpeg.Options{100})

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

这里的逻辑比一开始想到的要复杂

  1. DrawMask来实现带透明度的水印图片写入
  2. 图片倾斜角度之后,水印生成的图片的大小需要调整

效果图如下

在这里插入图片描述
这已经是一个很完善的水印图了。

四、最后成品代码

package main

import (
	"image"
	"image/color"
	"image/draw"
	"image/jpeg"
	"image/png"
	"os"

	imgtype "codechina.csdn.net/diandianxiyu/goimgtype"
	"github.com/anthonynsimon/bild/transform"
)

func main() {
	var imgdiandianxiyu_geek string = `./bg.jpg`
	imgb, err := os.Open(imgdiandianxiyu_geek)
	if err != nil {
		panic(err)
	}
	defer imgb.Close()

	datatype, err2 := imgtype.Get(imgdiandianxiyu_geek)
	var imgtype string = ""
	if err2 != nil {
		imgtype = ""
	} else {
		// 根据文件类型执行响应的操作
		switch datatype {
		case `image/jpeg`:
			imgtype = "jpeg"
		case `image/png`:
			imgtype = "png"
		}
	}
	if imgtype == "" {
		panic("暂不支持文件类型")
	}

	var imgbinfo image.Image
	if imgtype == "jpeg" {
		imgbinfo, _ = jpeg.Decode(imgb)
	} else {
		imgbinfo, _ = png.Decode(imgb)
	}

	//读取水印图片
	watermark, err := os.Open("watermark.png")
	if err != nil {
		panic(err)
	}
	defer watermark.Close()
	imgwatermark, err := png.Decode(watermark)
	if err != nil {
		panic(err)
	}

	b := imgbinfo.Bounds()
	watermarkbg := image.NewNRGBA(image.Rect(0, 0, b.Dx()*4, b.Dy()*4))

	m := image.NewNRGBA(b) //按原图生成新图

	draw.Draw(m, b, imgbinfo, image.ZP, draw.Src) //写入原图

	x, y := 0, 0
	offsetX, offsetY := 2, 25
	maxX := watermarkbg.Bounds().Max.X * 4
	maxY := watermarkbg.Bounds().Max.Y * 4
	for y <= maxY {
		for x <= maxX {
			offset := image.Pt(x, y)
			draw.Draw(watermarkbg, imgwatermark.Bounds().Add(offset), imgwatermark, image.ZP, draw.Over)
			x += imgwatermark.Bounds().Dx()
			x += offsetX
		}
		y += imgwatermark.Bounds().Dy()
		y += offsetY
		x = 0
	}

	watermarkbg2 := image.Image(watermarkbg)
	watermarkbg2 = transform.Rotate(watermarkbg2, -40.0, nil)
	mask := image.NewUniform(color.Alpha{30})
	draw.DrawMask(m, watermarkbg2.Bounds().Add(image.Pt(-watermarkbg2.Bounds().Dx()/2, 0)), watermarkbg2, image.ZP, mask, image.Point{-100, -100}, draw.Over)
	imgw, _ := os.Create("new.jpg")
	jpeg.Encode(imgw, m, &jpeg.Options{100})

}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89

文章来源: coderfix.blog.csdn.net,作者:小雨青年,版权归原作者所有,如需转载,请联系作者。

原文链接:coderfix.blog.csdn.net/article/details/119546482

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。