package dao import ( "bufio" "bytes" "context" "fmt" "image" "image/color" "image/draw" "image/jpeg" "image/png" "io/ioutil" "net/http" "os" "regexp" "go-common/app/admin/openplatform/sug/model" "go-common/library/log" "code.google.com/p/graphics-go/graphics" "errors" "github.com/golang/freetype" "golang.org/x/image/font" "golang.org/x/image/math/fixed" ) const ( _Width = 1125 _Height = 234 _HeaderLength = 168 ) var ( _RGBA = []int{244, 245, 247, 255} _HeadArea = []int{36, 33, 204, 201} _LabelArea = []int{234, 156, 348, 201} _BriefText = []int{234, 72} _NameText = []int{234, 129} _BriefSize = 44 _NameSize = 36 _BriefRGBA = []int{33, 33, 33, 255} _NameRGBA = []int{153, 153, 153, 255} _BriefLimit = 1000 _NameLimit = 1000 ) // CreateItemPNG make a pic func (d *Dao) CreateItemPNG(item model.Item) (location string, err error) { var r *image.NRGBA64 if r, err = d.makeBoard(item.Img); err != nil { log.Error("Create picture board error(%v)", err) return } if item.Brief == "" { item.Brief = item.Name } r = d.drawText(r, item.Brief, item.Name) buf := new(bytes.Buffer) png.Encode(buf, r) bufReader := bufio.NewReader(buf) if location, err = d.Upload(context.TODO(), "image/png", fmt.Sprintf("season_sug_%s/%d.png", d.c.Env, item.ItemsID), bufReader); err != nil { log.Error("Upload pic png error (%v)", err) return } reg, _ := regexp.CompilePOSIX(`//(.*)+`) location = reg.FindString(location) return } func (d *Dao) makeBoard(headerURL string) (board *image.NRGBA64, err error) { var header image.Image radius, _ := os.Open(d.c.SourcePath + "radius.png") label, _ := os.Open(d.c.SourcePath + "label.png") defer radius.Close() defer label.Close() resp, err := http.Get("http:" + headerURL) if err != nil { log.Error("http get error(%v)(%s)", "http:"+headerURL) return } bs, err := ioutil.ReadAll(resp.Body) if err != nil { log.Error("ioutil.ReadAll img error(%v)", err) return } imgType := http.DetectContentType(bs) buf := bytes.NewBuffer(bs) resp.Body = ioutil.NopCloser(buf) if err != nil { log.Error("http download head img error(%v)", err) return } defer resp.Body.Close() switch imgType { case "image/png": header, err = png.Decode(resp.Body) if err != nil { log.Error("png picture decode error(%v)", err) return } case "image/jpeg", "image/jpg": header, err = jpeg.Decode(resp.Body) if err != nil { log.Error("jpg picture decode err(%v)", err) return } default: err = errors.New("invaild picture type") log.Error("invaild picture type (%s)", headerURL) return } board = image.NewNRGBA64(image.Rect(0, 0, _Width, _Height)) draw.Draw(board, board.Bounds(), image.White, image.ZP, draw.Src) radiusPNG, _ := png.Decode(radius) cover := image.NewRGBA64(image.Rect(0, 0, _HeaderLength, _HeaderLength)) border := image.NewNRGBA64(image.Rect(0, 0, _HeaderLength, _HeaderLength)) headBoard := image.NewRGBA64(image.Rect(0, 0, _HeaderLength, _HeaderLength)) 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) graphics.Thumbnail(border, radiusPNG) graphics.Thumbnail(cover, header) labelPNG, _ := png.Decode(label) draw.Draw(headBoard, headBoard.Bounds(), cover, image.ZP, draw.Over) draw.Draw(headBoard, headBoard.Bounds(), border, image.ZP, draw.Over) draw.Draw(board, image.Rect(_HeadArea[0], _HeadArea[1], _HeadArea[2], _HeadArea[3]), headBoard, image.ZP, draw.Over) draw.Draw(board, image.Rect(_LabelArea[0], _LabelArea[1], _LabelArea[2], _LabelArea[3]), labelPNG, image.ZP, draw.Over) return } func (d *Dao) drawText(r *image.NRGBA64, brief string, name string) *image.NRGBA64 { ptBrief := fixed.P(_BriefText[0], _BriefText[1]) ptName := fixed.P(_NameText[0], _NameText[1]) freetypeC := d.Context(r) 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)) 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)) return r } // Context make object for write letters func (d *Dao) Context(r *image.NRGBA64) (c *freetype.Context) { c = freetype.NewContext() c.SetClip(r.Bounds()) c.SetDst(r) c.SetHinting(font.HintingNone) return } // Text write letters func (d *Dao) Text(c *freetype.Context, s string, pt *fixed.Point26_6, size int, color image.Image, length fixed.Int26_6) (err error) { c.SetFontSize(float64(size)) c.SetSrc(color) ttf, _ := ioutil.ReadFile(d.c.SourcePath + "font.ttf") font, _ := freetype.ParseFont(ttf) c.SetFont(font) for _, r := range s { c.DrawString(string(r), *pt) pt.X += font.HMetric(fixed.Int26_6(size*64), font.Index(r)).AdvanceWidth if pt.X > length { break } } return }