drawtext.go 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. package utils
  2. import (
  3. "bytes"
  4. "fmt"
  5. "image"
  6. "image/color"
  7. "image/draw"
  8. "image/gif"
  9. "image/jpeg"
  10. "image/png"
  11. "io/ioutil"
  12. "net/http"
  13. "os"
  14. "github.com/golang/freetype"
  15. "github.com/golang/freetype/truetype"
  16. "golang.org/x/image/font"
  17. )
  18. //DrawTextInfo 图片绘字信息
  19. type DrawTextInfo struct {
  20. Text string
  21. X int
  22. Y int
  23. FontSize int
  24. }
  25. //DrawRectInfo 图片画框信息
  26. type DrawRectInfo struct {
  27. X1 int
  28. Y1 int
  29. X2 int
  30. Y2 int
  31. }
  32. //TextBrush 字体相关
  33. type TextBrush struct {
  34. FontType *truetype.Font
  35. FontSize float64
  36. FontColor *image.Uniform
  37. TextWidth int
  38. }
  39. //NewTextBrush 新生成笔刷
  40. func NewTextBrush(FontFilePath string, FontSize float64, FontColor *image.Uniform, textWidth int) (*TextBrush, error) {
  41. fontFile, err := ioutil.ReadFile(FontFilePath)
  42. if err != nil {
  43. return nil, err
  44. }
  45. fontType, err := truetype.Parse(fontFile)
  46. if err != nil {
  47. return nil, err
  48. }
  49. if textWidth <= 0 {
  50. textWidth = 20
  51. }
  52. return &TextBrush{FontType: fontType, FontSize: FontSize, FontColor: FontColor, TextWidth: textWidth}, nil
  53. }
  54. //DrawFontOnRGBA 图片插入文字
  55. func (fb *TextBrush) DrawFontOnRGBA(rgba *image.RGBA, pt image.Point, content string) {
  56. c := freetype.NewContext()
  57. c.SetDPI(72)
  58. c.SetFont(fb.FontType)
  59. c.SetHinting(font.HintingFull)
  60. c.SetFontSize(fb.FontSize)
  61. c.SetClip(rgba.Bounds())
  62. c.SetDst(rgba)
  63. c.SetSrc(fb.FontColor)
  64. c.DrawString(content, freetype.Pt(pt.X, pt.Y))
  65. }
  66. //Image2RGBA Image2RGBA
  67. func Image2RGBA(img image.Image) *image.RGBA {
  68. baseSrcBounds := img.Bounds().Max
  69. newWidth := baseSrcBounds.X
  70. newHeight := baseSrcBounds.Y
  71. des := image.NewRGBA(image.Rect(0, 0, newWidth, newHeight)) // 底板
  72. //首先将一个图片信息存入jpg
  73. draw.Draw(des, des.Bounds(), img, img.Bounds().Min, draw.Over)
  74. return des
  75. }
  76. type FontRGBA struct {
  77. R uint8
  78. G uint8
  79. B uint8
  80. A uint8
  81. }
  82. //DrawStringOnImageAndSave 图片上写文字
  83. func DrawStringOnImageAndSave(imagePath string, imageData []byte, infos []*DrawTextInfo, colorRGBA FontRGBA) (err error) {
  84. //判断图片类型
  85. var backgroud image.Image
  86. filetype := http.DetectContentType(imageData)
  87. switch filetype {
  88. case "image/jpeg", "image/jpg":
  89. backgroud, err = jpeg.Decode(bytes.NewReader(imageData))
  90. if err != nil {
  91. fmt.Println("jpeg error")
  92. return err
  93. }
  94. case "image/gif":
  95. backgroud, err = gif.Decode(bytes.NewReader(imageData))
  96. if err != nil {
  97. return err
  98. }
  99. case "image/png":
  100. backgroud, err = png.Decode(bytes.NewReader(imageData))
  101. if err != nil {
  102. return err
  103. }
  104. default:
  105. return err
  106. }
  107. des := Image2RGBA(backgroud)
  108. //新建笔刷
  109. ttfPath := "static/ttf/songti.ttf"
  110. textBrush, _ := NewTextBrush(ttfPath, 25, image.Black, 50)
  111. //Px Py 绘图开始坐标 text要绘制的文字
  112. //调整颜色
  113. c := freetype.NewContext()
  114. c.SetDPI(72)
  115. c.SetFont(textBrush.FontType)
  116. c.SetHinting(font.HintingFull)
  117. c.SetFontSize(textBrush.FontSize)
  118. c.SetClip(des.Bounds())
  119. c.SetDst(des)
  120. textBrush.FontColor = image.NewUniform(color.RGBA{
  121. R: colorRGBA.R,
  122. G: colorRGBA.G,
  123. B: colorRGBA.B,
  124. A: colorRGBA.A,
  125. })
  126. c.SetSrc(textBrush.FontColor)
  127. for _, info := range infos {
  128. c.DrawString(info.Text, freetype.Pt(info.X, info.Y))
  129. }
  130. //保存图片
  131. fSave, err := os.Create(imagePath)
  132. if err != nil {
  133. return err
  134. }
  135. defer fSave.Close()
  136. err = jpeg.Encode(fSave, des, nil)
  137. if err != nil {
  138. return err
  139. }
  140. return nil
  141. }
  142. //DrawRectOnImageAndSave 图片上画多个框
  143. func DrawRectOnImageAndSave(imagePath string, imageData []byte, infos []*DrawRectInfo) (err error) {
  144. //判断图片类型
  145. var backgroud image.Image
  146. filetype := http.DetectContentType(imageData)
  147. switch filetype {
  148. case "image/jpeg", "image/jpg":
  149. backgroud, err = jpeg.Decode(bytes.NewReader(imageData))
  150. if err != nil {
  151. fmt.Println("jpeg error")
  152. return err
  153. }
  154. case "image/gif":
  155. backgroud, err = gif.Decode(bytes.NewReader(imageData))
  156. if err != nil {
  157. return err
  158. }
  159. case "image/png":
  160. backgroud, err = png.Decode(bytes.NewReader(imageData))
  161. if err != nil {
  162. return err
  163. }
  164. default:
  165. return err
  166. }
  167. des := Image2RGBA(backgroud)
  168. //新建笔刷
  169. textBrush, _ := NewTextBrush("arial.ttf", 15, image.Black, 15)
  170. for _, info := range infos {
  171. var c *freetype.Context
  172. c = freetype.NewContext()
  173. c.SetDPI(72)
  174. c.SetFont(textBrush.FontType)
  175. c.SetHinting(font.HintingFull)
  176. c.SetFontSize(textBrush.FontSize)
  177. c.SetClip(des.Bounds())
  178. c.SetDst(des)
  179. cGreen := image.NewUniform(color.RGBA{
  180. R: 0,
  181. G: 0xFF,
  182. B: 0,
  183. A: 255,
  184. })
  185. c.SetSrc(cGreen)
  186. for i := info.X1; i < info.X2; i++ {
  187. c.DrawString("·", freetype.Pt(i, info.Y1))
  188. c.DrawString("·", freetype.Pt(i, info.Y2))
  189. }
  190. for j := info.Y1; j < info.Y2; j++ {
  191. c.DrawString("·", freetype.Pt(info.X1, j))
  192. c.DrawString("·", freetype.Pt(info.X2, j))
  193. }
  194. }
  195. //保存图片
  196. fSave, err := os.Create(imagePath)
  197. if err != nil {
  198. return err
  199. }
  200. defer fSave.Close()
  201. err = jpeg.Encode(fSave, des, nil)
  202. if err != nil {
  203. return err
  204. }
  205. return nil
  206. }
  207. //DrawStringOnImage 生成图片
  208. func DrawStringOnImage(imageData []byte, infos []*DrawTextInfo, colorRGBA FontRGBA, fontSize float64, fontWidth int) (picBytes bytes.Buffer, err error) {
  209. //判断图片类型
  210. var backgroud image.Image
  211. filetype := http.DetectContentType(imageData)
  212. switch filetype {
  213. case "image/jpeg", "image/jpg":
  214. backgroud, err = jpeg.Decode(bytes.NewReader(imageData))
  215. if err != nil {
  216. fmt.Println("jpeg error")
  217. return
  218. }
  219. case "image/gif":
  220. backgroud, err = gif.Decode(bytes.NewReader(imageData))
  221. if err != nil {
  222. return
  223. }
  224. case "image/png":
  225. backgroud, err = png.Decode(bytes.NewReader(imageData))
  226. if err != nil {
  227. return
  228. }
  229. default:
  230. return
  231. }
  232. des := Image2RGBA(backgroud)
  233. //新建笔刷
  234. ttfPath := "static/ttf/songti.ttf"
  235. textBrush, _ := NewTextBrush(ttfPath, fontSize, image.Black, fontWidth)
  236. //Px Py 绘图开始坐标 text要绘制的文字
  237. //调整颜色
  238. c := freetype.NewContext()
  239. c.SetDPI(72)
  240. c.SetFont(textBrush.FontType)
  241. c.SetHinting(font.HintingFull)
  242. c.SetFontSize(textBrush.FontSize)
  243. c.SetClip(des.Bounds())
  244. c.SetDst(des)
  245. textBrush.FontColor = image.NewUniform(color.RGBA{
  246. R: colorRGBA.R,
  247. G: colorRGBA.G,
  248. B: colorRGBA.B,
  249. A: colorRGBA.A,
  250. })
  251. c.SetSrc(textBrush.FontColor)
  252. for _, info := range infos {
  253. c.DrawString(info.Text, freetype.Pt(info.X, info.Y))
  254. }
  255. err = jpeg.Encode(&picBytes, des, nil)
  256. return
  257. }
  258. // DrawStringRowsOnImage 生成图片
  259. func DrawStringRowsOnImage(imageData []byte, infos []*DrawTextInfo, colorRGBA FontRGBA, fontSize float64, fontWidth int) (picBytes bytes.Buffer, err error) {
  260. //判断图片类型
  261. var backgroud image.Image
  262. filetype := http.DetectContentType(imageData)
  263. switch filetype {
  264. case "image/jpeg", "image/jpg":
  265. backgroud, err = jpeg.Decode(bytes.NewReader(imageData))
  266. if err != nil {
  267. fmt.Println("jpeg error")
  268. return
  269. }
  270. case "image/gif":
  271. backgroud, err = gif.Decode(bytes.NewReader(imageData))
  272. if err != nil {
  273. return
  274. }
  275. case "image/png":
  276. backgroud, err = png.Decode(bytes.NewReader(imageData))
  277. if err != nil {
  278. return
  279. }
  280. default:
  281. return
  282. }
  283. des := Image2RGBA(backgroud)
  284. //新建笔刷
  285. ttfPath := "static/ttf/songti.ttf"
  286. textBrush, _ := NewTextBrush(ttfPath, fontSize, image.Black, fontWidth)
  287. //Px Py 绘图开始坐标 text要绘制的文字
  288. //调整颜色
  289. for _, info := range infos {
  290. c := freetype.NewContext()
  291. c.SetDPI(72)
  292. c.SetFont(textBrush.FontType)
  293. c.SetHinting(font.HintingFull)
  294. c.SetFontSize(float64(info.FontSize))
  295. c.SetClip(des.Bounds())
  296. c.SetDst(des)
  297. textBrush.FontColor = image.NewUniform(color.RGBA{
  298. R: colorRGBA.R,
  299. G: colorRGBA.G,
  300. B: colorRGBA.B,
  301. A: colorRGBA.A,
  302. })
  303. c.SetSrc(textBrush.FontColor)
  304. c.DrawString(info.Text, freetype.Pt(info.X, info.Y))
  305. }
  306. err = jpeg.Encode(&picBytes, des, nil)
  307. return
  308. }