image.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. package produce
  2. import (
  3. "bytes"
  4. "fmt"
  5. "image"
  6. "image/color"
  7. "image/draw"
  8. "image/png"
  9. "os"
  10. "strings"
  11. "time"
  12. "github.com/fogleman/gg"
  13. )
  14. type ImageInfo struct {
  15. dc *gg.Context
  16. }
  17. func (im *ImageInfo) testRunimage(sql string) ([]byte, error) {
  18. // 创建一个新的gg.Context实例,根据字符串长度动态设置图像大小
  19. const padding = 20 // 上下留白
  20. const charWidth = 10 // 字符宽度
  21. const lineHeight = 15 // 行高
  22. const maxWidth = 2500 // 最大宽度
  23. // 计算图像高度和行数
  24. lines := 0
  25. width := 0.0
  26. height := padding * 2
  27. lineWidth := 0.0
  28. im.dc = gg.NewContext(1, 1)
  29. //加载字体和字体大小
  30. if err := im.dc.LoadFontFace("/home/gtong/xugu_work/xg_autotest/assets/SimHei.ttf", 12); err != nil {
  31. fmt.Println(err.Error())
  32. return nil, nil
  33. }
  34. //计算图像高度和行数
  35. for _, r := range sql {
  36. w, _ := im.dc.MeasureString(string(r))
  37. if r == '\n' || lineWidth+w > float64(maxWidth-padding*2) {
  38. fmt.Printf("\r == 'n': \n")
  39. lines++
  40. if lineWidth > width {
  41. width = lineWidth
  42. fmt.Printf("\nwidth: %f\n", width)
  43. }
  44. lineWidth = 0.0
  45. }
  46. lineWidth += w
  47. }
  48. lines++
  49. if lineWidth > width {
  50. //width = lineWidth + (lineWidth * 0.2)
  51. width = lineWidth
  52. fmt.Printf("lineWidth > width : %f", width)
  53. }
  54. height += (lines) * lineHeight
  55. im.dc = gg.NewContext(int(width+float64(padding*2)), int(height))
  56. im.dc.SetRGB(0, 0, 0)
  57. im.dc.Clear()
  58. im.dc.SetRGB(1, 1, 1)
  59. // 绘制字符串
  60. x := padding
  61. y := padding
  62. lineWidth = 0.0
  63. for _, r := range sql {
  64. w, _ := im.dc.MeasureString(string(r))
  65. if r == '\n' || lineWidth+w > float64(maxWidth-padding*2) {
  66. y += lineHeight
  67. lineWidth = 0.0
  68. if r == '\n' {
  69. continue
  70. }
  71. }
  72. im.dc.DrawString(string(r), float64(x)+lineWidth, float64(y))
  73. lineWidth += w
  74. }
  75. // 将图像编码为PNG格式的二进制数据
  76. var buf bytes.Buffer
  77. if err := png.Encode(&buf, im.dc.Image()); err != nil {
  78. return nil, nil
  79. }
  80. name := "/home/gtong/xugu_work/xg_autotest/file/test_pic_1.png"
  81. newfile, err := os.Create(name)
  82. if err != nil {
  83. fmt.Println(err.Error())
  84. }
  85. defer newfile.Close()
  86. err = png.Encode(newfile, im.dc.Image())
  87. if err != nil {
  88. fmt.Println(err.Error())
  89. }
  90. return buf.Bytes(), nil
  91. }
  92. func (im *ImageInfo) Runimage(sql string) ([]byte, error) {
  93. // 设置图片大小
  94. width := 100
  95. height := 100
  96. // 设置字体和字体大小
  97. fontSize := 20.0
  98. fontPath := "./assets/SimHei.ttf"
  99. // 根据字符串长度调整图片宽度和高度
  100. dcTemp := gg.NewContext(100, 100)
  101. // 加载字体和字体大小
  102. if err := dcTemp.LoadFontFace(fontPath, 10); err != nil {
  103. fmt.Println(err.Error())
  104. return nil, nil
  105. }
  106. SqlLines := strings.Split(sql, "\n")
  107. // for _, v := range SqlLines {
  108. // fmt.Println("sql := ", v)
  109. // }
  110. //计算有多少行
  111. lineHeight := 0
  112. for _, line := range SqlLines {
  113. textWidth, _ := dcTemp.MeasureString(line)
  114. if int(textWidth) > width {
  115. width = int(textWidth)
  116. }
  117. lineHeight++
  118. }
  119. //设置高度
  120. height += lineHeight*int(fontSize*1.2) - 65
  121. // 创建一个新的绘图上下文
  122. width = int(width) * 2 // 保留一些空白边距
  123. im.dc = gg.NewContext(width, height)
  124. // 加载字体和字体大小
  125. if err := im.dc.LoadFontFace(fontPath, fontSize); err != nil {
  126. fmt.Println(err.Error())
  127. return nil, nil
  128. }
  129. im.dc.SetColor(color.Black)
  130. im.dc.Clear()
  131. // 设置文本颜色为白色
  132. im.dc.SetColor(color.White)
  133. // 在图片顶部离开 20px,左边开始绘制文本
  134. lines := strings.Split(sql, "\n")
  135. x := 2.0 // 离左边 20px
  136. y := 20.0 // 离顶部 20px
  137. for _, line := range lines {
  138. im.dc.DrawString(line, x, y)
  139. y += fontSize * 1.2 // 增加行间距
  140. }
  141. //返回图片的二进制数据
  142. var buf bytes.Buffer
  143. if err := png.Encode(&buf, im.dc.Image()); err != nil {
  144. return nil, nil
  145. }
  146. return buf.Bytes(), nil
  147. }
  148. func (im *ImageInfo) SaveImage(fileName string) {
  149. // 保存图片
  150. newfile, err := os.Create(fmt.Sprintf("%s", fileName))
  151. if err != nil {
  152. fmt.Println(err.Error())
  153. return
  154. }
  155. defer newfile.Close()
  156. // 将文件保存输出,并设置压缩比
  157. //err = jpeg.Encode(newfile, dc.Image(), &jpeg.Options{Quality: 150})
  158. err = png.Encode(newfile, im.dc.Image())
  159. if err != nil {
  160. fmt.Println(err.Error())
  161. return
  162. }
  163. }
  164. // 检查file文件夹是否存在,不存在则创建
  165. func CreateFolder() string {
  166. dirName := "./file"
  167. // 检查文件夹是否存在
  168. if _, err := os.Stat(dirName); os.IsNotExist(err) {
  169. // 文件夹不存在,创建文件夹
  170. err := os.Mkdir(dirName, 0755)
  171. if err != nil {
  172. fmt.Println("创建文件夹失败:", err)
  173. return ""
  174. }
  175. fmt.Println("文件夹创建成功")
  176. } else if err != nil {
  177. // 其他错误,打印错误信息
  178. fmt.Println("检查文件夹失败:", err)
  179. return ""
  180. } else {
  181. // 文件夹已经存在
  182. fmt.Println("文件夹已经存在")
  183. }
  184. dirName = fmt.Sprintf("%s/%s", dirName, time.Now())
  185. err := os.Mkdir(dirName, 0755)
  186. if err != nil {
  187. fmt.Println("创建文件夹失败:", err)
  188. return ""
  189. }
  190. return dirName
  191. }
  192. // 合并图片为一张
  193. func MergeImages(imageBytes [][]byte) ([]byte, error) {
  194. var maxWidth int
  195. var totalHeight int
  196. // 计算合并后图片的宽度和高度
  197. for _, imgData := range imageBytes {
  198. img, _, err := image.Decode(bytes.NewReader(imgData))
  199. if err != nil {
  200. return nil, err
  201. }
  202. bounds := img.Bounds()
  203. if bounds.Dx() > maxWidth {
  204. maxWidth = bounds.Dx()
  205. }
  206. totalHeight += bounds.Dy()
  207. }
  208. // 创建一个黑色背景的图片
  209. dst := image.NewRGBA(image.Rect(0, 0, maxWidth, totalHeight))
  210. draw.Draw(dst, dst.Bounds(), &image.Uniform{color.Black}, image.Point{}, draw.Src)
  211. // 合并图片
  212. var offsetY int
  213. for _, imgData := range imageBytes {
  214. img, _, err := image.Decode(bytes.NewReader(imgData))
  215. if err != nil {
  216. return nil, err
  217. }
  218. bounds := img.Bounds()
  219. draw.Draw(dst, image.Rect(0, offsetY, bounds.Dx(), offsetY+bounds.Dy()), img, image.Point{}, draw.Src)
  220. offsetY += bounds.Dy()
  221. }
  222. // 保存合并后的图片到字节数组
  223. var buf bytes.Buffer
  224. err := png.Encode(&buf, dst)
  225. if err != nil {
  226. return nil, err
  227. }
  228. return buf.Bytes(), nil
  229. }