draw.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. package drawimg
  2. import (
  3. "errors"
  4. "image"
  5. "image/color"
  6. "image/draw"
  7. "io/ioutil"
  8. "strconv"
  9. "strings"
  10. "go-common/library/log"
  11. "github.com/golang/freetype/truetype"
  12. "golang.org/x/image/math/fixed"
  13. )
  14. // DrawImg create img info.
  15. type DrawImg struct {
  16. size int
  17. CanvasWidth int
  18. CanvasHeight int
  19. File string
  20. txtWidth int
  21. srcImg image.Image
  22. Canvas *image.NRGBA
  23. c *Context
  24. f *truetype.Font
  25. }
  26. // NewDrawImg create new img.
  27. func NewDrawImg(fontfile string, size int) (w *DrawImg) {
  28. w = &DrawImg{
  29. size: size,
  30. }
  31. f, err := w.readFont(fontfile, size)
  32. if err != nil {
  33. return
  34. }
  35. if f == nil {
  36. return
  37. }
  38. w.f = f
  39. return
  40. }
  41. //ReadSrcImg read an image
  42. func (w *DrawImg) ReadSrcImg(path string) (img image.Image, err error) {
  43. if img, err = Open(path); err != nil {
  44. log.Error("readSrcImg error(%v)", err)
  45. }
  46. return
  47. }
  48. func (w *DrawImg) readFont(path string, size int) (f *truetype.Font, err error) {
  49. fbs, err := ioutil.ReadFile(path)
  50. if err != nil {
  51. log.Error("readFont error(%v)", err)
  52. return
  53. }
  54. f, err = ParseFont(fbs)
  55. if err != nil {
  56. log.Error("error(%v)", err)
  57. }
  58. cxt := NewContext()
  59. if cxt == nil {
  60. return
  61. }
  62. w.c = cxt
  63. w.c.SetFont(f)
  64. w.c.SetFontSize(float64(size))
  65. return
  66. }
  67. func (w *DrawImg) imgWidth() int {
  68. return w.srcImg.Bounds().Max.X
  69. }
  70. func (w *DrawImg) imgHeight() int {
  71. return w.srcImg.Bounds().Max.Y
  72. }
  73. func (w *DrawImg) newImgWidth() int {
  74. return w.txtWidth + w.imgWidth()
  75. }
  76. func (w *DrawImg) newCanvas(width, height int) *image.NRGBA {
  77. return NewNRGBA(width, height, color.RGBA{255, 0, 0, 0})
  78. }
  79. func (w *DrawImg) fillColor(r, g, b, a int32) image.Image {
  80. return &image.Uniform{color.NRGBA{uint8(r), uint8(g), uint8(b), uint8(a)}}
  81. }
  82. func (w *DrawImg) textWidth(text string) (err error) {
  83. defer func() {
  84. if err := recover(); err != nil {
  85. log.Error("draw set textWidth text(%s)|error(%v)", text, err)
  86. }
  87. }()
  88. box, err := w.c.FontBox(text, w.pt(3, 5))
  89. if err != nil {
  90. log.Error("set textWidth text(%s)|error(%v)", text, err)
  91. return
  92. }
  93. widthStr := strings.Split(Int26_6ToString(box.X), ":")[0]
  94. wid, err := strconv.ParseInt(widthStr, 10, 64)
  95. if err != nil {
  96. log.Error("strconv.ParseInt widthStr(%+v)|error(%v)", widthStr, err)
  97. return
  98. }
  99. w.txtWidth = int(wid)
  100. return
  101. }
  102. func (w *DrawImg) pt(x, y int) fixed.Point26_6 {
  103. return Pt(x, y+int(w.c.PointToFixed(float64(w.size))>>6))
  104. }
  105. func (w *DrawImg) setFont(text string, dstRgba *image.NRGBA, fsrc image.Image, pt fixed.Point26_6) (err error) {
  106. w.c.SetClip(w.Canvas.Bounds())
  107. w.c.SetDst(dstRgba)
  108. w.c.SetSrc(fsrc)
  109. _, err = w.c.DrawString(text, pt)
  110. if err != nil {
  111. log.Error("setFont error(%v)", err)
  112. }
  113. return
  114. }
  115. func (w *DrawImg) composite(dstCanvas *image.NRGBA, src image.Image, isLeft bool) {
  116. var p image.Point
  117. if isLeft {
  118. p = image.Point{-int(w.txtWidth), 0}
  119. } else {
  120. p = image.ZP
  121. }
  122. draw.Draw(dstCanvas, image.Rect(0, 0, w.newImgWidth(), w.imgHeight()), src, p, draw.Over)
  123. }
  124. // Draw write text to the left or right of img.
  125. func (w *DrawImg) Draw(text, savepath string, isLeft bool) (err error) {
  126. if text == "" {
  127. err = errors.New("draw: DrawText called with a empty text")
  128. return
  129. }
  130. w.textWidth(text)
  131. w.CanvasWidth = w.newImgWidth()
  132. w.CanvasHeight = w.imgHeight()
  133. w.Canvas = w.newCanvas(w.CanvasWidth, w.CanvasHeight)
  134. if w.c == nil || w.Canvas == nil {
  135. err = errors.New("draw: DrawText w.c or w.Canvas is nil")
  136. return
  137. }
  138. draw.Draw(w.Canvas, w.Canvas.Bounds(), w.Canvas, image.ZP, draw.Src)
  139. var pt fixed.Point26_6
  140. if isLeft {
  141. pt = w.pt(3, 5)
  142. } else {
  143. pt = w.pt(w.imgWidth(), 8)
  144. }
  145. black := w.fillColor(0, 0, 0, 125)
  146. w.setFont(text, w.Canvas, black, pt)
  147. blurRgba := Blur(w.Canvas, 6, 3.5)
  148. white := w.fillColor(255, 255, 255, 180)
  149. w.setFont(text, blurRgba, white, pt)
  150. w.composite(blurRgba, w.srcImg, isLeft)
  151. Save(blurRgba, savepath)
  152. return
  153. }