Go 绘制图片

Go 绘制图片,第1张

本文介绍使用 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
// }

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/996088.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存