|
|
package images
|
|
|
|
|
|
import (
|
|
|
"fmt"
|
|
|
"github.com/golang/freetype"
|
|
|
"github.com/nfnt/resize"
|
|
|
"image"
|
|
|
"image/draw"
|
|
|
_ "image/gif"
|
|
|
"image/jpeg"
|
|
|
_ "image/png"
|
|
|
"io"
|
|
|
"io/ioutil"
|
|
|
"log"
|
|
|
"os"
|
|
|
)
|
|
|
|
|
|
type ContentItem struct {
|
|
|
Content string
|
|
|
FontSizt float64
|
|
|
X int
|
|
|
Y int
|
|
|
MaxWidth int
|
|
|
}
|
|
|
|
|
|
type FileItem struct {
|
|
|
File string
|
|
|
X int
|
|
|
Y int
|
|
|
Width uint
|
|
|
Height uint
|
|
|
}
|
|
|
|
|
|
func WaterMark(imgPath string, ttf string, outPath string, contentList []ContentItem, fileLIst []FileItem) error {
|
|
|
imgfile, _ := os.Open(imgPath)
|
|
|
defer imgfile.Close()
|
|
|
jpgimg, a, b := image.Decode(imgfile)
|
|
|
log.Println(a, b)
|
|
|
img := image.NewNRGBA(jpgimg.Bounds())
|
|
|
|
|
|
for y := 0; y < img.Bounds().Dy(); y++ {
|
|
|
for x := 0; x < img.Bounds().Dx(); x++ {
|
|
|
img.Set(x, y, jpgimg.At(x, y))
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 文字水印
|
|
|
fontbyte, err := ioutil.ReadFile(ttf)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
font, err := freetype.ParseFont(fontbyte)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
// 创建一个新的上下文
|
|
|
context := freetype.NewContext()
|
|
|
context.SetDPI(72) // 设置屏幕分辨率,单位为每英寸点数。
|
|
|
context.SetFont(font) //设置用于绘制文本的字体。
|
|
|
context.SetClip(jpgimg.Bounds()) //设置用于绘制的剪辑矩形。
|
|
|
context.SetDst(img) //设置绘制操作的目标图像。
|
|
|
context.SetSrc(image.Black) //设置用于绘制操作的源图像
|
|
|
|
|
|
context1 := freetype.NewContext()
|
|
|
context1.SetDPI(72) // 设置屏幕分辨率,单位为每英寸点数。
|
|
|
context1.SetFont(font) //设置用于绘制文本的字体。
|
|
|
context1.SetDst(img) //设置绘制操作的目标图像。
|
|
|
for _, item := range contentList {
|
|
|
if item.FontSizt <= 0 {
|
|
|
item.FontSizt = 16
|
|
|
}
|
|
|
context.SetFontSize(item.FontSizt) //以点为单位设置字体大小(如“12点字体”)。
|
|
|
if item.MaxWidth > 0 {
|
|
|
context1.SetFontSize(item.FontSizt)
|
|
|
drawString1, _ := context1.DrawString(item.Content, freetype.Pt(item.X, item.Y))
|
|
|
context.DrawString(item.Content, freetype.Pt(item.X+(item.MaxWidth-(drawString1.X.Round()-item.X))/2, item.Y))
|
|
|
} else {
|
|
|
context.DrawString(item.Content, freetype.Pt(item.X, item.Y))
|
|
|
}
|
|
|
}
|
|
|
for _, item := range fileLIst {
|
|
|
open, _ := os.Open(item.File)
|
|
|
defer open.Close()
|
|
|
tmpImg, _, _ := image.Decode(open)
|
|
|
|
|
|
//把水印写在右下角,并向0坐标偏移10个像素
|
|
|
tmpImg = resize.Resize(item.Width, item.Height, tmpImg, resize.Lanczos3)
|
|
|
offset := image.Pt(item.X-tmpImg.Bounds().Max.X, item.Y-tmpImg.Bounds().Max.Y)
|
|
|
//image.ZP代表Point结构体,目标的源点,即(0,0)
|
|
|
draw.Draw(img, tmpImg.Bounds().Add(offset), tmpImg, image.ZP, draw.Over)
|
|
|
}
|
|
|
|
|
|
//创建图片
|
|
|
file, err := os.Create(outPath)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
defer file.Close()
|
|
|
// 将图像写入file
|
|
|
//&jpeg.Options{100} 取值范围[1,100],越大图像编码质量越高
|
|
|
jpeg.Encode(file, img, &jpeg.Options{Quality: 100})
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
func WaterMarkOut(imgPath string, ttf string, w io.Writer, contentList []ContentItem, fileList []FileItem) error {
|
|
|
imgFile, _ := os.Open(imgPath)
|
|
|
defer imgFile.Close()
|
|
|
jpgImg, a, b := image.Decode(imgFile)
|
|
|
log.Println(a, b)
|
|
|
img := image.NewNRGBA(jpgImg.Bounds())
|
|
|
|
|
|
for y := 0; y < img.Bounds().Dy(); y++ {
|
|
|
for x := 0; x < img.Bounds().Dx(); x++ {
|
|
|
img.Set(x, y, jpgImg.At(x, y))
|
|
|
}
|
|
|
}
|
|
|
|
|
|
// 文字水印
|
|
|
fontByte, err := ioutil.ReadFile(ttf)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
font, err := freetype.ParseFont(fontByte)
|
|
|
if err != nil {
|
|
|
return err
|
|
|
}
|
|
|
// 创建一个新的上下文
|
|
|
context := freetype.NewContext()
|
|
|
context.SetDPI(72) // 设置屏幕分辨率,单位为每英寸点数。
|
|
|
context.SetFont(font) //设置用于绘制文本的字体。
|
|
|
context.SetClip(jpgImg.Bounds()) //设置用于绘制的剪辑矩形。
|
|
|
context.SetDst(img) //设置绘制操作的目标图像。
|
|
|
context.SetSrc(image.Black) //设置用于绘制操作的源图像
|
|
|
|
|
|
context1 := freetype.NewContext()
|
|
|
context1.SetDPI(72) // 设置屏幕分辨率,单位为每英寸点数。
|
|
|
context1.SetFont(font) //设置用于绘制文本的字体。
|
|
|
context1.SetDst(img) //设置绘制操作的目标图像。
|
|
|
for _, item := range contentList {
|
|
|
context.SetFontSize(item.FontSizt) //以点为单位设置字体大小(如“12点字体”)。
|
|
|
if item.MaxWidth > 0 {
|
|
|
context1.SetFontSize(item.FontSizt)
|
|
|
drawString1, _ := context1.DrawString(item.Content, freetype.Pt(item.X, item.Y))
|
|
|
context.DrawString(item.Content, freetype.Pt(item.X+(item.MaxWidth-(drawString1.X.Round()-item.X))/2, item.Y))
|
|
|
} else {
|
|
|
context.DrawString(item.Content, freetype.Pt(item.X, item.Y))
|
|
|
}
|
|
|
}
|
|
|
for _, item := range fileList {
|
|
|
open, _ := os.Open(item.File)
|
|
|
defer open.Close()
|
|
|
tmpImg, _, _ := image.Decode(open)
|
|
|
|
|
|
condition := tmpImg.Bounds().Max.X > tmpImg.Bounds().Max.Y*3
|
|
|
if condition {
|
|
|
item.Width = 810
|
|
|
item.Height = 0
|
|
|
}
|
|
|
|
|
|
tmpImg = resize.Resize(item.Width, item.Height, tmpImg, resize.Lanczos3)
|
|
|
offsetX := item.X - tmpImg.Bounds().Max.X
|
|
|
offsetY := item.Y - 270 + (270-tmpImg.Bounds().Max.Y)/2
|
|
|
|
|
|
offset := image.Pt(offsetX, offsetY)
|
|
|
fmt.Println(offsetX, offsetY)
|
|
|
|
|
|
//image.Point{}代表Point结构体,目标的源点,即(0,0)
|
|
|
draw.Draw(img, tmpImg.Bounds().Add(offset), tmpImg, image.Point{}, draw.Over)
|
|
|
}
|
|
|
|
|
|
_ = jpeg.Encode(w, img, &jpeg.Options{Quality: 100})
|
|
|
return nil
|
|
|
}
|