vision/watermark.go

140 lines
3.4 KiB
Go

package vision
import (
"image"
"image/color"
"image/draw"
)
// Position 水印位置
type Position int
const (
TopLeft Position = iota
TopCenter
TopRight
LeftCenter
Center
RightCenter
BottomLeft
BottomCenter
BottomRight
)
// Watermark 给画布添加图片水印
// mark: 水印画布
// pos: 位置
// opacity: 透明度 (0.0 - 1.0)
// padding: 边距
// angle: 旋转角度 (弧度)
func (c *Canvas) Watermark(mark *Canvas, pos Position, opacity float64, padding int, angle ...float64) {
if mark == nil || opacity < 0.01 {
return
}
w, h := c.Width(), c.Height()
mw, mh := mark.Width(), mark.Height()
var x, y int
switch pos {
case TopLeft:
x, y = padding, padding
case TopCenter:
x, y = (w-mw)/2, padding
case TopRight:
x, y = w-mw-padding, padding
case LeftCenter:
x, y = padding, (h-mh)/2
case Center:
x, y = (w-mw)/2, (h-mh)/2
case RightCenter:
x, y = w-mw-padding, (h-mh)/2
case BottomLeft:
x, y = padding, h-mh-padding
case BottomCenter:
x, y = (w-mw)/2, h-mh-padding
case BottomRight:
x, y = w-mw-padding, h-mh-padding
}
c.dc.Push()
if len(angle) > 0 && angle[0] != 0 {
c.dc.RotateAbout(angle[0], float64(x+mw/2), float64(y+mh/2))
}
// 处理透明度
if opacity >= 0.99 {
c.dc.DrawImage(mark.dc.Image(), x, y)
} else {
mask := image.NewUniform(color.Alpha{uint8(255 * opacity)})
draw.DrawMask(c.dc.Image().(draw.Image), mark.dc.Image().Bounds().Add(image.Pt(x, y)), mark.dc.Image(), image.Point{}, mask, image.Point{}, draw.Over)
}
c.dc.Pop()
}
// TileWatermark 平铺图片水印
// spacing: 间距
// angle: 旋转角度 (弧度)
func (c *Canvas) TileWatermark(mark *Canvas, opacity float64, spacing int, angle float64) {
if mark == nil || opacity < 0.01 {
return
}
mw, mh := mark.Width(), mark.Height()
w, h := c.Width(), c.Height()
stepX := mw + spacing
stepY := mh + spacing
for y := -mh; y < h+mh; y += stepY {
for x := -mw; x < w+mw; x += stepX {
c.dc.Push()
c.dc.RotateAbout(angle, float64(x+mw/2), float64(y+mh/2))
if opacity >= 0.99 {
c.dc.DrawImage(mark.dc.Image(), x, y)
} else {
mask := image.NewUniform(color.Alpha{uint8(255 * opacity)})
draw.DrawMask(c.dc.Image().(draw.Image), mark.dc.Image().Bounds().Add(image.Pt(x, y)), mark.dc.Image(), image.Point{}, mask, image.Point{}, draw.Over)
}
c.dc.Pop()
}
}
}
// TextWatermark 给画布添加文字水印
func (c *Canvas) TextWatermark(text string, pos Position, style *DrawStyle, opacity float64, padding int, angle ...float64) {
// 创建一个临时画布来渲染文字,然后调用 Watermark
c.dc.Push()
tw, th := c.dc.MeasureString(text)
temp := New(int(tw)+4, int(th)+4)
if style != nil && style.FillColor != "" {
temp.dc.SetColor(ParseColor(style.FillColor))
} else {
temp.dc.SetColor(color.Black)
}
temp.dc.DrawString(text, 2, th+2)
ang := 0.0
if len(angle) > 0 {
ang = angle[0]
}
c.Watermark(temp, pos, opacity, padding, ang)
c.dc.Pop()
}
// TileTextWatermark 平铺文字水印
func (c *Canvas) TileTextWatermark(text string, style *DrawStyle, opacity float64, spacing int, angle float64) {
c.dc.Push()
tw, th := c.dc.MeasureString(text)
temp := New(int(tw)+4, int(th)+4)
if style != nil && style.FillColor != "" {
temp.dc.SetColor(ParseColor(style.FillColor))
} else {
temp.dc.SetColor(color.Black)
}
temp.dc.DrawString(text, 2, th+2)
c.TileWatermark(temp, opacity, spacing, angle)
c.dc.Pop()
}