You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

174 lines
5.2 KiB

4 years ago
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)
4 years ago
condition := tmpImg.Bounds().Max.X > tmpImg.Bounds().Max.Y*3
4 years ago
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
4 years ago
offsetY := item.Y - 270 + (270-tmpImg.Bounds().Max.Y)/2
4 years ago
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
}