基于golang制作倾斜图片水印保护图片来源
一、前言
在我的上一篇文章中,我们学会了使用
- 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. 整体倾斜水印图像
实现思路如下
- 新建一个空白图片,尺寸和原图一致
- 平铺水印图片到空白图片上
- 整体倾斜空白图片
代码层面要注意点 ,转换图像的是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. 调整水印区域和透明度
这里处理问题的解决思路是
- 计算因为倾斜导致多出来的宽高
- 图片叠加修改透明度
- 整理图片叠加顺序
处理代码如下
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
这里的逻辑比一开始想到的要复杂
DrawMask
来实现带透明度的水印图片写入- 图片倾斜角度之后,水印生成的图片的大小需要调整
效果图如下
这已经是一个很完善的水印图了。
四、最后成品代码
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
- 点赞
- 收藏
- 关注作者
评论(0)