package utils import ( "bytes" "fmt" "image" "image/color" "image/draw" "image/gif" "image/jpeg" "image/png" "io/ioutil" "net/http" "os" "github.com/golang/freetype" "github.com/golang/freetype/truetype" "golang.org/x/image/font" ) //DrawTextInfo 图片绘字信息 type DrawTextInfo struct { Text string X int Y int FontSize int } //DrawRectInfo 图片画框信息 type DrawRectInfo struct { X1 int Y1 int X2 int Y2 int } //TextBrush 字体相关 type TextBrush struct { FontType *truetype.Font FontSize float64 FontColor *image.Uniform TextWidth int } //NewTextBrush 新生成笔刷 func NewTextBrush(FontFilePath string, FontSize float64, FontColor *image.Uniform, textWidth int) (*TextBrush, error) { fontFile, err := ioutil.ReadFile(FontFilePath) if err != nil { return nil, err } fontType, err := truetype.Parse(fontFile) if err != nil { return nil, err } if textWidth <= 0 { textWidth = 20 } return &TextBrush{FontType: fontType, FontSize: FontSize, FontColor: FontColor, TextWidth: textWidth}, nil } //DrawFontOnRGBA 图片插入文字 func (fb *TextBrush) DrawFontOnRGBA(rgba *image.RGBA, pt image.Point, content string) { c := freetype.NewContext() c.SetDPI(72) c.SetFont(fb.FontType) c.SetHinting(font.HintingFull) c.SetFontSize(fb.FontSize) c.SetClip(rgba.Bounds()) c.SetDst(rgba) c.SetSrc(fb.FontColor) c.DrawString(content, freetype.Pt(pt.X, pt.Y)) } //Image2RGBA Image2RGBA func Image2RGBA(img image.Image) *image.RGBA { baseSrcBounds := img.Bounds().Max newWidth := baseSrcBounds.X newHeight := baseSrcBounds.Y des := image.NewRGBA(image.Rect(0, 0, newWidth, newHeight)) // 底板 //首先将一个图片信息存入jpg draw.Draw(des, des.Bounds(), img, img.Bounds().Min, draw.Over) return des } type FontRGBA struct { R uint8 G uint8 B uint8 A uint8 } //DrawStringOnImageAndSave 图片上写文字 func DrawStringOnImageAndSave(imagePath string, imageData []byte, infos []*DrawTextInfo, colorRGBA FontRGBA) (err error) { //判断图片类型 var backgroud image.Image filetype := http.DetectContentType(imageData) switch filetype { case "image/jpeg", "image/jpg": backgroud, err = jpeg.Decode(bytes.NewReader(imageData)) if err != nil { fmt.Println("jpeg error") return err } case "image/gif": backgroud, err = gif.Decode(bytes.NewReader(imageData)) if err != nil { return err } case "image/png": backgroud, err = png.Decode(bytes.NewReader(imageData)) if err != nil { return err } default: return err } des := Image2RGBA(backgroud) //新建笔刷 ttfPath := "static/ttf/songti.ttf" textBrush, _ := NewTextBrush(ttfPath, 25, image.Black, 50) //Px Py 绘图开始坐标 text要绘制的文字 //调整颜色 c := freetype.NewContext() c.SetDPI(72) c.SetFont(textBrush.FontType) c.SetHinting(font.HintingFull) c.SetFontSize(textBrush.FontSize) c.SetClip(des.Bounds()) c.SetDst(des) textBrush.FontColor = image.NewUniform(color.RGBA{ R: colorRGBA.R, G: colorRGBA.G, B: colorRGBA.B, A: colorRGBA.A, }) c.SetSrc(textBrush.FontColor) for _, info := range infos { c.DrawString(info.Text, freetype.Pt(info.X, info.Y)) } //保存图片 fSave, err := os.Create(imagePath) if err != nil { return err } defer fSave.Close() err = jpeg.Encode(fSave, des, nil) if err != nil { return err } return nil } //DrawRectOnImageAndSave 图片上画多个框 func DrawRectOnImageAndSave(imagePath string, imageData []byte, infos []*DrawRectInfo) (err error) { //判断图片类型 var backgroud image.Image filetype := http.DetectContentType(imageData) switch filetype { case "image/jpeg", "image/jpg": backgroud, err = jpeg.Decode(bytes.NewReader(imageData)) if err != nil { fmt.Println("jpeg error") return err } case "image/gif": backgroud, err = gif.Decode(bytes.NewReader(imageData)) if err != nil { return err } case "image/png": backgroud, err = png.Decode(bytes.NewReader(imageData)) if err != nil { return err } default: return err } des := Image2RGBA(backgroud) //新建笔刷 textBrush, _ := NewTextBrush("arial.ttf", 15, image.Black, 15) for _, info := range infos { var c *freetype.Context c = freetype.NewContext() c.SetDPI(72) c.SetFont(textBrush.FontType) c.SetHinting(font.HintingFull) c.SetFontSize(textBrush.FontSize) c.SetClip(des.Bounds()) c.SetDst(des) cGreen := image.NewUniform(color.RGBA{ R: 0, G: 0xFF, B: 0, A: 255, }) c.SetSrc(cGreen) for i := info.X1; i < info.X2; i++ { c.DrawString("·", freetype.Pt(i, info.Y1)) c.DrawString("·", freetype.Pt(i, info.Y2)) } for j := info.Y1; j < info.Y2; j++ { c.DrawString("·", freetype.Pt(info.X1, j)) c.DrawString("·", freetype.Pt(info.X2, j)) } } //保存图片 fSave, err := os.Create(imagePath) if err != nil { return err } defer fSave.Close() err = jpeg.Encode(fSave, des, nil) if err != nil { return err } return nil } //DrawStringOnImage 生成图片 func DrawStringOnImage(imageData []byte, infos []*DrawTextInfo, colorRGBA FontRGBA, fontSize float64, fontWidth int) (picBytes bytes.Buffer, err error) { //判断图片类型 var backgroud image.Image filetype := http.DetectContentType(imageData) switch filetype { case "image/jpeg", "image/jpg": backgroud, err = jpeg.Decode(bytes.NewReader(imageData)) if err != nil { fmt.Println("jpeg error") return } case "image/gif": backgroud, err = gif.Decode(bytes.NewReader(imageData)) if err != nil { return } case "image/png": backgroud, err = png.Decode(bytes.NewReader(imageData)) if err != nil { return } default: return } des := Image2RGBA(backgroud) //新建笔刷 ttfPath := "static/ttf/songti.ttf" textBrush, _ := NewTextBrush(ttfPath, fontSize, image.Black, fontWidth) //Px Py 绘图开始坐标 text要绘制的文字 //调整颜色 c := freetype.NewContext() c.SetDPI(72) c.SetFont(textBrush.FontType) c.SetHinting(font.HintingFull) c.SetFontSize(textBrush.FontSize) c.SetClip(des.Bounds()) c.SetDst(des) textBrush.FontColor = image.NewUniform(color.RGBA{ R: colorRGBA.R, G: colorRGBA.G, B: colorRGBA.B, A: colorRGBA.A, }) c.SetSrc(textBrush.FontColor) for _, info := range infos { c.DrawString(info.Text, freetype.Pt(info.X, info.Y)) } err = jpeg.Encode(&picBytes, des, nil) return } // DrawStringRowsOnImage 生成图片 func DrawStringRowsOnImage(imageData []byte, infos []*DrawTextInfo, colorRGBA FontRGBA, fontSize float64, fontWidth int) (picBytes bytes.Buffer, err error) { //判断图片类型 var backgroud image.Image filetype := http.DetectContentType(imageData) switch filetype { case "image/jpeg", "image/jpg": backgroud, err = jpeg.Decode(bytes.NewReader(imageData)) if err != nil { fmt.Println("jpeg error") return } case "image/gif": backgroud, err = gif.Decode(bytes.NewReader(imageData)) if err != nil { return } case "image/png": backgroud, err = png.Decode(bytes.NewReader(imageData)) if err != nil { return } default: return } des := Image2RGBA(backgroud) //新建笔刷 ttfPath := "static/ttf/songti.ttf" textBrush, _ := NewTextBrush(ttfPath, fontSize, image.Black, fontWidth) //Px Py 绘图开始坐标 text要绘制的文字 //调整颜色 for _, info := range infos { c := freetype.NewContext() c.SetDPI(72) c.SetFont(textBrush.FontType) c.SetHinting(font.HintingFull) c.SetFontSize(float64(info.FontSize)) c.SetClip(des.Bounds()) c.SetDst(des) textBrush.FontColor = image.NewUniform(color.RGBA{ R: colorRGBA.R, G: colorRGBA.G, B: colorRGBA.B, A: colorRGBA.A, }) c.SetSrc(textBrush.FontColor) c.DrawString(info.Text, freetype.Pt(info.X, info.Y)) } err = jpeg.Encode(&picBytes, des, nil) return }