主要功能:
Resize: 调整图像大小。Crop: 裁剪图像。Rotate: 旋转图像。Blur: 模糊图像。Sharpen: 锐化图像。Adjust: 调整亮度、对比度、饱和度等。github.com/fogleman/gggg 是一个简单的 2D 绘图库,基于 cairo 提供了更方便的 API,用于生成和操作图形。它特别适合生成图表、图形叠加、文字和图形组合等任务。
主要功能:

font 提供了与字体相关的功能,包括字体加载、字体渲染等。这个包定义了字体的基本接口和数据结构。
主要功能:
Font face: 定义和处理字体面。Drawers: 用于在图像上绘制文本。Glyph: 提供了处理字体字形的基本操作golang.org/x/image/font/opentypeopentype 专门用于处理 OpenType 字体格式,提供了加载和渲染 OpenType 字体的功能。
主要功能:
Parse: 解析 OpenType 字体文件。NewFace: 创建字体面,以便于字体渲染。Font metrics: 提供字体的度量信息(如升部、降部、行高等)。image/colorimage/color 包定义了表示颜色的接口和类型。它提供了各种颜色模型和用于转换颜色的实用函数。
主要功能:
Color model: 提供 RGBA、NRGBA、YCbCr、Gray 等颜色模型。色彩转换: 在不同颜色模型之间进行转换。颜色定义: 定义基本颜色如黑色、白色、红色等。实现个小小需求实现一个按钮,要求是椭圆型,文字居中。
参数信息:boxW := 600boxH := 300boxColor := color.RGBA{R: 255, G: 255, B: 255, A: 1}buttonW := 200buttonH := 100ButtonColor := "#8650ac"fontSize := 48fontDpi := 96.0buttonText := "按钮"fontColor := "#ffffff"buttonImg := "./img/button.jpg"
物料:
下载字体资源文件:
技术方案先拿一张宣纸(设定一个大的画布)开始画椭圆(先画长方形,然后四个角加弧度,填充背景色)拿个计算器,开始计算X,Y(计算文字行高)拿起毛笔,开始在椭圆中心写字(加载字体,文字居中渲染)按钮再覆盖到大的宣纸上(小画布和大画布相结合)小demo实现
代码实现package mainimport ("context""fmt""github.com/disintegration/imaging""github.com/fogleman/gg""golang.org/x/image/font""golang.org/x/image/font/opentype""image/color""os")type DrawText struct {}type drawText interface {// DrawButton 绘制按钮DrawButton(ctx context.Context, w, y float64, color string, boxColor color.Color) (data gg.Context, err error)// LoadFont 加载字体LoadFont(fontSize float64, dpi float64) (fontFace font.Face, err error)// PxToPt PxToPtPxToPt(px float64, dpi float64) float64// SaveImg 保存图片SaveImg(dc gg.Context, fileName string) bool}func NewDrawText(ctx context.Context) drawText {return &DrawText{}}func main() {boxW := 600boxH := 300boxColor := color.RGBA{R: 255, G: 255, B: 255, A: 1}buttonW := 200buttonH := 100ButtonColor := "#8650ac"fontSize := 48fontDpi := 96.0buttonText := "按钮"fontColor := "#ffffff"buttonImg := "./img/button.jpg"d := NewDrawText(context.Background())// 创建一个大的画布dc := gg.NewContext(boxW, boxH)dc.SetColor(boxColor) // Set background colordc.Clear()// 绘制色块dcButton, err := d.DrawButton(context.Background(), float64(buttonW), float64(buttonH), ButtonColor, boxColor)if err != nil {panic(err)return}// 加载字体fontFace, err := d.LoadFont(d.PxToPt(float64(fontSize), fontDpi), fontDpi)if err != nil {panic(err)return}defer fontFace.Close()// 设置字体参数、颜色dcButton.SetFontFace(fontFace)dcButton.SetHexColor(fontColor)// 字体文案,计算x,y 居中位置buttonTextW, buttonTextH := dcButton.MeasureString(buttonText)dcButton.DrawString(buttonText, (float64(buttonW)-buttonTextW)/2, (float64(buttonH)+buttonTextH)2/5)// 按钮绘制到画布上dc.DrawImage(dcButton.Image(), (boxW-buttonW)/2, (boxH-buttonH)/2)if d.SaveImg(dc, buttonImg) {return}fmt.Println("done")return}func (d DrawText) SaveImg(dc gg.Context, fileName string) bool {if err := imaging.Save(dc.Image(), fileName); err != nil {panic(err)return true}fmt.Printf("保持为jpg图片:%s\n", fileName)return false}// LoadFont 加载字体func (d DrawText) LoadFont(fontSize float64, dpi float64) (fontFace font.Face, err error) {fontBytes, err := os.ReadFile("./assets/Source_Han_Sans_SC_Normal_Normal.otf")if err != nil {return nil, fmt.Errorf("failed to read font file: %w", err)}fontVal, err := opentype.Parse(fontBytes)if err != nil {return nil, fmt.Errorf("failed to parse font: %w", err)}fontFace, err = opentype.NewFace(fontVal, &opentype.FaceOptions{Size: fontSize,DPI: dpi,Hinting: font.HintingFull,})if err != nil {return nil, fmt.Errorf("failed to create font face: %w", err)}return fontFace, nil}// DrawButton 绘制色块func (d DrawText) DrawButton(ctx context.Context, w, y float64, color string, boxColor color.Color) (data gg.Context, err error) {// 创建一个上下文来绘制色块dc := gg.NewContext(int(w), int(y))// 设置背景颜色 同画布颜色dc.SetColor(boxColor)// 填充颜色dc.Clear()// 设置圆角dc.SetHexColor(color)dc.DrawRoundedRectangle(0, 0, w, y, 20)dc.Fill()return dc, nil}func (d DrawText) PxToPt(px float64, dpi float64) float64 {return px (72 / dpi)}
效果图
效果图
麻雀虽小,五脏俱全。想实现其他功能,自由组合。
总结:海报图生成,最麻烦的就是计算,从始至终,就是拿着计算器计算,调整X,Y坐标。还有一点就是,px和pt的转化,不同的设备,分辨率展示出的效果不同。前端可以获取到客户端的设备信息,服务端拿不到这些数据,只能按照经验值去设定。
轻松一刻我为人人,人人为我。美美与共,天下大同。