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() }