需求:
1,员工签到图片加水印
2,水印文字需要有半透明的底色,避免水印看不清
3,图片宽设置在600,小于600或者大于600都需要等比例修改图片的高度,保持水印在图片中的大小和位置
4,处理后图片和原图大小不要相差太多
调用:
fileName := "display_20231229134926805_9512.jpg"
waterMark := WaterMarkInfo{
UserInfo: "1123456789-仲夏夜的梦 2023-12-28 17:23:54",
SignAddress: "[119.092868,34.887314] 中国广东省深圳市龙岗区坂田街道华为基地广东省深圳市南山区广东省深圳市南山区广东省深圳市南山区广东省深圳市南山区广东省深圳市南山区",
}
addSigninWaterMark(fileName, waterMark)
图片加水印方法:
// WaterMarkInfo 水印信息
type WaterMarkInfo struct {
UserInfo string //用户信息
SignAddress string //签到地址
}
// 增加打卡水印
func addSigninWaterMark(fileName string, waterMarkInfo WaterMarkInfo) error {
//接口异常捕获
defer func() {
if err := recover(); err != nil {
sbjlog.ExcLog("100", "addSigninWaterMark-图片增加水印异常:err=%v", err)
}
}()
//需要加水印的图片
imgfile, err := os.Open(tempImgDir + fileName)
if err != nil {
sbjlog.Debug("addSigninWaterMark os.Open ERROR:%v \r\n", err)
return err
}
defer imgfile.Close()
jpgimg, err := jpeg.Decode(imgfile)
if err != nil {
sbjlog.Debug("addSigninWaterMark jpeg.Decode ERROR:%v \r\n", err)
return err
}
//对图片进行大小变更,图片的宽必须是600,水印文字长度是按照600来设置的
imgWidth := uint(600)
imgHeight := uint(800)
if uint(jpgimg.Bounds().Dx()) != imgWidth {
imgHeight = uint(imgWidth) * uint(jpgimg.Bounds().Dy()) / uint(jpgimg.Bounds().Dx())
jpgimg = resize.Resize(600, imgHeight, jpgimg, resize.Bilinear)
}
//新建空白图层
img := image.NewRGBA64(jpgimg.Bounds())
pic2FramePadding := 20
waterMarkHeight := 80
waterMarkWidth := 600
//新建空白白色图层
transparentImg := image.NewRGBA64(image.Rect(0, 0, waterMarkWidth-pic2FramePadding/2, waterMarkHeight))
//设置空白白色图层的大小
draw.Draw(transparentImg,
image.Rect(pic2FramePadding/2, pic2FramePadding/2, transparentImg.Bounds().Dx(), transparentImg.Bounds().Dy()),
image.White,
image.Point{},
draw.Over)
//把原来的图片画到空白图层上
draw.Draw(img, jpgimg.Bounds(), jpgimg, jpgimg.Bounds().Min, draw.Over)
//设置白色图层透明度,color.Alpha值在0-255之间,越靠近0越来透明
mask := image.NewUniform(color.Alpha{180})
//把空白图层画到空白图层上
draw.DrawMask(img, img.Bounds().Add(image.Pt(0, jpgimg.Bounds().Dy()-waterMarkHeight-pic2FramePadding/2)), transparentImg, image.ZP, mask, image.Point{}, draw.Over)
//给空白图层加水印
err = addWaterMarkToImage(img, waterMarkInfo)
if err != nil {
return err
}
//保存到新文件中
newfile, err := os.Create(tempImgDir + fileName)
//在尽量不损失图片质量的情况下,保证绘制后图片和原图片一样大:jpeg.Options{94}
err = jpeg.Encode(newfile, img, &jpeg.Options{94})
if err != nil {
fmt.Println(err)
}
return nil
}
图片加文字:
func addWaterMarkToImage(newTemplateImage *image.RGBA64, waterMarkInfo WaterMarkInfo) error {
// 在写入之前有一些准备工作
content := freetype.NewContext()
fontTtf, err := loadFont("runtime/fonts/simsun.ttc")
if err != nil {
sbjlog.Debug("addWaterMarkToImage loadFont ERROR:%v \r\n", err)
return err
}
content.SetClip(newTemplateImage.Bounds())
content.SetDst(newTemplateImage)
content.SetSrc(image.Black) // 设置字体颜色
content.SetDPI(72) // 设置字体分辨率
content.SetFontSize(14) // 设置字体大小
content.SetFont(fontTtf) // 设置字体样式,就是我们上面加载的字体
// 正式写入文字
// 参数1:要写入的文字
// 参数2:文字坐标
//dx := newTemplateImage.Bounds().Dx()
dy := newTemplateImage.Bounds().Dy()
topSignAddress := waterMarkInfo.SignAddress
endSignAddress := ""
if len(waterMarkInfo.SignAddress) > 100 {
topSignAddress = xstring.SubString(waterMarkInfo.SignAddress, 100)
endSignAddress = waterMarkInfo.SignAddress[len(topSignAddress):]
}
pic2FramePadding := 20
markHeiht := dy - pic2FramePadding*3
content.DrawString(waterMarkInfo.UserInfo, freetype.Pt(pic2FramePadding, markHeiht))
markHeiht = markHeiht + 20
content.DrawString(topSignAddress, freetype.Pt(pic2FramePadding, markHeiht))
markHeiht = markHeiht + 20
content.DrawString(endSignAddress, freetype.Pt(pic2FramePadding, markHeiht))
return nil
}
加载字体:
// 根据路径加载字体文件
// path 字体的路径
func loadFont(path string) (font *truetype.Font, err error) {
var fontBytes []byte
fontBytes, err = ioutil.ReadFile(path) // 读取字体文件
if err != nil {
err = fmt.Errorf("加载字体文件出错:%s", err.Error())
return
}
font, err = freetype.ParseFont(fontBytes) // 解析字体文件
if err != nil {
err = fmt.Errorf("解析字体文件出错,%s", err.Error())
return
}
return
}