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 }