package produce import ( "bytes" "fmt" "image" "image/color" "image/draw" "image/png" "os" "strings" "time" "github.com/fogleman/gg" ) type ImageInfo struct { dc *gg.Context } func (im *ImageInfo) Runimage(sql string) ([]byte, error) { // 创建一个新的gg.Context实例,根据字符串长度动态设置图像大小 const padding = 20 // 上下留白 const charWidth = 10 // 字符宽度 const lineHeight = 15 // 行高 const maxWidth = 2500 // 最大宽度 // 计算图像高度和行数 lines := 0 width := 0.0 height := padding * 2 lineWidth := 0.0 im.dc = gg.NewContext(1, 1) //加载字体和字体大小 if err := im.dc.LoadFontFace("/home/gtong/xugu_work/xg_autotest/assets/SimHei.ttf", 12); err != nil { fmt.Println(err.Error()) return nil, nil } //计算图像高度和行数 for _, r := range sql { w, _ := im.dc.MeasureString(string(r)) if r == '\n' || lineWidth+w > float64(maxWidth-padding*2) { fmt.Printf("\r == 'n': \n") lines++ if lineWidth > width { width = lineWidth fmt.Printf("\nwidth: %f\n", width) } lineWidth = 0.0 } lineWidth += w } lines++ if lineWidth > width { //width = lineWidth + (lineWidth * 0.2) width = lineWidth fmt.Printf("lineWidth > width : %f", width) } height += (lines) * lineHeight im.dc = gg.NewContext(int(width+float64(padding*2)), int(height)) im.dc.SetRGB(0, 0, 0) im.dc.Clear() im.dc.SetRGB(1, 1, 1) // 绘制字符串 x := padding y := padding lineWidth = 0.0 for _, r := range sql { w, _ := im.dc.MeasureString(string(r)) if r == '\n' || lineWidth+w > float64(maxWidth-padding*2) { y += lineHeight lineWidth = 0.0 if r == '\n' { continue } } im.dc.DrawString(string(r), float64(x)+lineWidth, float64(y)) lineWidth += w } // 将图像编码为PNG格式的二进制数据 var buf bytes.Buffer if err := png.Encode(&buf, im.dc.Image()); err != nil { return nil, nil } name := "/home/gtong/xugu_work/xg_autotest/file/test_pic_1.png" newfile, err := os.Create(name) if err != nil { fmt.Println(err.Error()) } defer newfile.Close() err = png.Encode(newfile, im.dc.Image()) if err != nil { fmt.Println(err.Error()) } return buf.Bytes(), nil } func (im *ImageInfo) Runimage2(sql string) ([]byte, error) { // 设置图片大小 width := 100 height := 100 // 设置字体和字体大小 fontSize := 20.0 fontPath := "/home/gtong/xugu_work/xg_autotest/assets/SimHei.ttf" // 根据字符串长度调整图片宽度和高度 dcTemp := gg.NewContext(100, 100) // 加载字体和字体大小 if err := dcTemp.LoadFontFace(fontPath, 10); err != nil { fmt.Println(err.Error()) return nil, nil } SqlLines := strings.Split(sql, "\n") // for _, v := range SqlLines { // fmt.Println("sql := ", v) // } //计算有多少行 lineHeight := 0 for _, line := range SqlLines { textWidth, _ := dcTemp.MeasureString(line) if int(textWidth) > width { width = int(textWidth) } lineHeight++ } //设置高度 height += lineHeight * int(fontSize*1.2) // 创建一个新的绘图上下文 width = int(width) * 4 // 保留一些空白边距 im.dc = gg.NewContext(width, height) // 加载字体和字体大小 if err := im.dc.LoadFontFace(fontPath, fontSize); err != nil { fmt.Println(err.Error()) return nil, nil } im.dc.SetColor(color.Black) im.dc.Clear() // 设置文本颜色为白色 im.dc.SetColor(color.White) // 在图片顶部离开 20px,左边开始绘制文本 lines := strings.Split(sql, "\n") x := 2.0 // 离左边 20px y := 20.0 // 离顶部 20px for _, line := range lines { im.dc.DrawString(line, x, y) y += fontSize * 1.2 // 增加行间距 } //返回图片的二进制数据 var buf bytes.Buffer if err := png.Encode(&buf, im.dc.Image()); err != nil { return nil, nil } return buf.Bytes(), nil } func (im *ImageInfo) SaveImage(fileName string) { // 保存图片 newfile, err := os.Create(fmt.Sprintf("%s", fileName)) if err != nil { fmt.Println(err.Error()) return } defer newfile.Close() // 将文件保存输出,并设置压缩比 //err = jpeg.Encode(newfile, dc.Image(), &jpeg.Options{Quality: 150}) err = png.Encode(newfile, im.dc.Image()) if err != nil { fmt.Println(err.Error()) return } } // 检查file文件夹是否存在,不存在则创建 func CreateFolder() string { dirName := "./file" // 检查文件夹是否存在 if _, err := os.Stat(dirName); os.IsNotExist(err) { // 文件夹不存在,创建文件夹 err := os.Mkdir(dirName, 0755) if err != nil { fmt.Println("创建文件夹失败:", err) return "" } fmt.Println("文件夹创建成功") } else if err != nil { // 其他错误,打印错误信息 fmt.Println("检查文件夹失败:", err) return "" } else { // 文件夹已经存在 fmt.Println("文件夹已经存在") } dirName = fmt.Sprintf("%s/%s", dirName, time.Now()) err := os.Mkdir(dirName, 0755) if err != nil { fmt.Println("创建文件夹失败:", err) return "" } return dirName } // 合并图片为一张 func MergeImages(imageBytes [][]byte) ([]byte, error) { var maxWidth int var totalHeight int // 计算合并后图片的宽度和高度 for _, imgData := range imageBytes { img, _, err := image.Decode(bytes.NewReader(imgData)) if err != nil { return nil, err } bounds := img.Bounds() if bounds.Dx() > maxWidth { maxWidth = bounds.Dx() } totalHeight += bounds.Dy() } // 创建一个黑色背景的图片 dst := image.NewRGBA(image.Rect(0, 0, maxWidth, totalHeight)) draw.Draw(dst, dst.Bounds(), &image.Uniform{color.Black}, image.Point{}, draw.Src) // 合并图片 var offsetY int for _, imgData := range imageBytes { img, _, err := image.Decode(bytes.NewReader(imgData)) if err != nil { return nil, err } bounds := img.Bounds() draw.Draw(dst, image.Rect(0, offsetY, bounds.Dx(), offsetY+bounds.Dy()), img, image.Point{}, draw.Src) offsetY += bounds.Dy() } // 保存合并后的图片到字节数组 var buf bytes.Buffer err := png.Encode(&buf, dst) if err != nil { return nil, err } return buf.Bytes(), nil }