本文介绍使用 go 绘制图片,插入图片,插入文字。
文字需要一套字体库
package canvas
import (
"bytes"
"errors"
"image"
"image/color"
"image/draw"
"image/jpeg"
"image/png"
"io"
"os"
"strings"
"github.com/golang/freetype"
"github.com/nfnt/resize"
)
type Canvas struct {
*image.RGBA
}
type Position struct {
Width, Height, Top, Left int
}
// 初始化字体库
func init() {
go InitFont()
}
func InitFont() {
var err error
//读取字体数据
fontBytes, err := ioutil.ReadFile("/usr/local/fonts/思源黑体.ttf")
if err != nil {
log.Println("ERROR 警告:未下载字体,仅影响绘图功能,可忽略", err)
return
}
//载入字体数据
font, err = freetype.ParseFont(fontBytes)
if err != nil {
log.Println("ERROR 加载字体失败", err)
}
}
// 使用一张图片生成画布
func NewByImg(imgpath string) (*Canvas, error) {
img, _, err := GetImage(imgpath)
if err != nil {
return nil, err
}
r := Canvas{}
r.RGBA = image.NewRGBA(img.Bounds())
draw.Draw(r, img.Bounds(), img, image.Pt(0, 0), draw.Over)
return &r, nil
}
// 生成一个尺寸的画布
func NewBySize(width, height int) *Canvas {
cvs := Canvas{}
cvs.RGBA = image.NewRGBA(image.Rectangle{Max: image.Point{width, height}})
return &cvs
}
// 嵌入图片 - 本地路径
func (cvs *Canvas) DrawImageByPath(imgpath string, position Position) error {
img, _, err := GetImage(imgpath)
if err != nil {
return err
}
return cvs.DrawImage(img, position)
}
// 嵌入图片 - io.Reader
func (cvs *Canvas) DrawImageByReader(reader io.Reader, position Position) error {
img, _, err := image.Decode(reader)
if err != nil {
return err
}
return cvs.DrawImage(img, position)
}
// 嵌入图片 - image.Image
func (cvs *Canvas) DrawImage(img image.Image, position Position) error {
if img.Bounds().Dx() != position.Width || img.Bounds().Dy() != position.Height {
img = resize.Resize(uint(position.Width), uint(position.Height), img, resize.Lanczos3)
}
rectangle := image.Rectangle{
Min: image.Point{position.Left, position.Top},
Max: image.Point{position.Left + position.Width, position.Top + position.Height},
}
draw.Draw(cvs, rectangle, img, image.Pt(0, 0), draw.Over)
return nil
}
// 嵌入文字 ,注意这个RGBA的A应该是255噢
func (cvs *Canvas) DrawText(str string, size int, rgba color.Color, left, top int) (err error) {
f := freetype.NewContext()
//设置分辨率
f.SetDPI(70)
//设置字体
f.SetFont(font)
//设置尺寸
f.SetFontSize(float64(size))
f.SetClip(cvs.Bounds())
//设置输出的图片
f.SetDst(cvs)
//设置字体颜色
f.SetSrc(image.NewUniform(rgba))
//设置字体的位置
pt := freetype.Pt(left, top)
_, err = f.DrawString(str, pt)
return
}
// 转为图片reader
func (cvs *Canvas) ToReader(fomat string) io.Reader {
var buffer bytes.Buffer
switch fomat {
case "png":
png.Encode(&buffer, cvs)
case "jpg":
fallthrough
case "jpeg":
jpeg.Encode(&buffer, cvs, &jpeg.Options{Quality: 100})
default:
panic("不支持的格式")
}
return &buffer
}
// 获取图片
func GetImage(imgpath string) (img image.Image, suffix string, err error) {
var f *os.File
if f, err = os.Open(imgpath); err != nil {
return
}
defer f.Close()
idx := strings.LastIndexByte(imgpath, '.')
suffix = imgpath[idx+1:]
switch suffix {
case "png":
img, err = png.Decode(f)
case "jpg":
fallthrough
case "jpeg":
img, err = jpeg.Decode(f)
default:
err = errors.New("不支持" + suffix + "格式")
}
return
}
// 等比压缩
func Resize(img image.Image, width int) image.Image {
return resize.Resize(uint(width), 0, img, resize.Lanczos3)
}
// 保存
// func (cvs *Canvas) Save(filepath string) error {
// outFile, err := os.Create(filepath)
// if err != nil {
// return err
// }
// defer outFile.Close()
// var writer bytes.Buffer
// if err := png.Encode(&writer, cvs); err != nil {
// return err
// }
// return nil
// }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)