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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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
}