image.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. package dao
  2. import (
  3. "bufio"
  4. "bytes"
  5. "context"
  6. "fmt"
  7. "go-common/app/admin/openplatform/sug/model"
  8. "go-common/library/log"
  9. "image"
  10. "image/color"
  11. "image/draw"
  12. "image/jpeg"
  13. "image/png"
  14. "io/ioutil"
  15. "net/http"
  16. "os"
  17. "regexp"
  18. "code.google.com/p/graphics-go/graphics"
  19. "github.com/golang/freetype"
  20. "golang.org/x/image/font"
  21. "golang.org/x/image/math/fixed"
  22. )
  23. const (
  24. _Width = 1125
  25. _Height = 234
  26. _HeaderLength = 168
  27. )
  28. var (
  29. _RGBA = []int{244, 245, 247, 255}
  30. _HeadArea = []int{36, 33, 204, 201}
  31. _LabelArea = []int{234, 156, 348, 201}
  32. _BriefText = []int{234, 72}
  33. _NameText = []int{234, 129}
  34. _BriefSize = 44
  35. _NameSize = 36
  36. _BriefRGBA = []int{33, 33, 33, 255}
  37. _NameRGBA = []int{153, 153, 153, 255}
  38. _BriefLimit = 1000
  39. _NameLimit = 1000
  40. )
  41. // CreateItemPNG make a pic for sug
  42. func (d *Dao) CreateItemPNG(item model.Item) (location string, err error) {
  43. var r *image.NRGBA64
  44. if r, err = d.makeBoard(item.Img); err != nil {
  45. log.Error("Create picture board error(%v)", err)
  46. return
  47. }
  48. if item.Brief == "" {
  49. item.Brief = item.Name
  50. }
  51. r = d.drawText(r, item.Brief, item.Name)
  52. buf := new(bytes.Buffer)
  53. png.Encode(buf, r)
  54. bufReader := bufio.NewReader(buf)
  55. if location, err = d.Upload(context.TODO(), "image/png", fmt.Sprintf("season_sug_%s/%d.png", d.c.Env, item.ItemsID), bufReader); err != nil {
  56. log.Error("Upload pic png error (%v)", err)
  57. return
  58. }
  59. reg, _ := regexp.CompilePOSIX(`//(.*)+`)
  60. location = reg.FindString(location)
  61. return
  62. }
  63. func (d *Dao) makeBoard(headerURL string) (board *image.NRGBA64, err error) {
  64. var header image.Image
  65. radius, _ := os.Open(d.c.SourcePath + "radius.png")
  66. label, _ := os.Open(d.c.SourcePath + "label.png")
  67. defer radius.Close()
  68. defer label.Close()
  69. resp, err := http.Get("http:" + headerURL)
  70. bs, err := ioutil.ReadAll(resp.Body)
  71. if err != nil {
  72. log.Error("ioutil.ReadAll img error(%v)", err)
  73. return
  74. }
  75. imgType := http.DetectContentType(bs)
  76. buf := bytes.NewBuffer(bs)
  77. resp.Body = ioutil.NopCloser(buf)
  78. if err != nil {
  79. log.Error("http download head img error(%v)", err)
  80. return
  81. }
  82. defer resp.Body.Close()
  83. switch imgType {
  84. case "image/png":
  85. header, err = png.Decode(resp.Body)
  86. if err != nil {
  87. log.Error("png picture decode error(%v)", err)
  88. return
  89. }
  90. case "image/jpeg", "image/jpg":
  91. header, err = jpeg.Decode(resp.Body)
  92. if err != nil {
  93. log.Error("jpg picture decode err(%v)", err)
  94. return
  95. }
  96. default:
  97. log.Error("invaild picture type (%s)", headerURL)
  98. return
  99. }
  100. board = image.NewNRGBA64(image.Rect(0, 0, _Width, _Height))
  101. draw.Draw(board, board.Bounds(), image.White, image.ZP, draw.Src)
  102. radiusPNG, _ := png.Decode(radius)
  103. cover := image.NewRGBA64(image.Rect(0, 0, _HeaderLength, _HeaderLength))
  104. border := image.NewNRGBA64(image.Rect(0, 0, _HeaderLength, _HeaderLength))
  105. headBoard := image.NewRGBA64(image.Rect(0, 0, _HeaderLength, _HeaderLength))
  106. draw.Draw(headBoard, headBoard.Bounds(), image.NewUniform(color.NRGBA{uint8(_RGBA[0]), uint8(_RGBA[1]), uint8(_RGBA[2]), uint8(_RGBA[3])}), image.ZP, draw.Over)
  107. graphics.Thumbnail(border, radiusPNG)
  108. graphics.Thumbnail(cover, header)
  109. labelPNG, _ := png.Decode(label)
  110. draw.Draw(headBoard, headBoard.Bounds(), cover, image.ZP, draw.Over)
  111. draw.Draw(headBoard, headBoard.Bounds(), border, image.ZP, draw.Over)
  112. draw.Draw(board, image.Rect(_HeadArea[0], _HeadArea[1], _HeadArea[2], _HeadArea[3]), headBoard, image.ZP, draw.Over)
  113. draw.Draw(board, image.Rect(_LabelArea[0], _LabelArea[1], _LabelArea[2], _LabelArea[3]), labelPNG, image.ZP, draw.Over)
  114. return
  115. }
  116. func (d *Dao) drawText(r *image.NRGBA64, brief string, name string) *image.NRGBA64 {
  117. ptBrief := fixed.P(_BriefText[0], _BriefText[1])
  118. ptName := fixed.P(_NameText[0], _NameText[1])
  119. freetypeC := d.Context(r)
  120. d.Text(freetypeC, brief, &ptBrief, _BriefSize, image.NewUniform(color.NRGBA{uint8(_BriefRGBA[0]), uint8(_BriefRGBA[1]), uint8(_BriefRGBA[2]), uint8(_BriefRGBA[3])}), fixed.I(_BriefLimit))
  121. d.Text(freetypeC, name, &ptName, _NameSize, image.NewUniform(color.NRGBA{uint8(_NameRGBA[0]), uint8(_NameRGBA[1]), uint8(_NameRGBA[2]), uint8(_RGBA[3])}), fixed.I(_NameLimit))
  122. return r
  123. }
  124. // Context get font for drawing
  125. func (d *Dao) Context(r *image.NRGBA64) (c *freetype.Context) {
  126. c = freetype.NewContext()
  127. c.SetClip(r.Bounds())
  128. c.SetDst(r)
  129. c.SetHinting(font.HintingNone)
  130. return
  131. }
  132. // Text draw letters on pic
  133. func (d *Dao) Text(c *freetype.Context, s string, pt *fixed.Point26_6, size int, color image.Image, length fixed.Int26_6) (err error) {
  134. c.SetFontSize(float64(size))
  135. c.SetSrc(color)
  136. ttf, _ := ioutil.ReadFile(d.c.SourcePath + "font.ttf")
  137. font, _ := freetype.ParseFont(ttf)
  138. c.SetFont(font)
  139. for _, r := range s {
  140. c.DrawString(string(r), *pt)
  141. pt.X += font.HMetric(fixed.Int26_6(size*64), font.Index(r)).AdvanceWidth
  142. if pt.X > length {
  143. break
  144. }
  145. }
  146. return
  147. }