140 lines
3.4 KiB
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()
|
|
}
|