Skip to content

Commit 421bee6

Browse files
committed
add golang gin-16 .md
1 parent 38b8896 commit 421bee6

File tree

1 file changed

+176
-0
lines changed

1 file changed

+176
-0
lines changed
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
# Golang Gin实践 连载十六 在图片上绘制文字
2+
3+
4+
本章节是 [连载十五](https://github.com/EDDYCJY/blog/blob/master/golang/gin/2018-07-04-Gin%E5%AE%9E%E8%B7%B5-%E8%BF%9E%E8%BD%BD%E5%8D%81%E4%BA%94-%E7%94%9F%E6%88%90%E4%BA%8C%E7%BB%B4%E7%A0%81-%E5%90%88%E5%B9%B6%E6%B5%B7%E6%8A%A5.md) 的补充内容,建议一同食用
5+
6+
## 前言
7+
主要实现**合并后的海报上绘制文字**的功能(这个需求也是常见的很了),内容比较简单
8+
9+
## 实现
10+
11+
这里使用的是 [微软雅黑](https://github.com/EDDYCJY/go-gin-example/blob/master/runtime/fonts/msyhbd.ttc) 的字体,请点击进行下载并**存放到 runtime/fonts 目录**下(字体文件占 16 MB 大小)
12+
13+
### 安装
14+
15+
```
16+
$ go get -u github.com/golang/freetype
17+
```
18+
19+
### 绘制文字
20+
21+
打开 service/article_service/article_poster.go 文件,增加绘制文字的业务逻辑,如下:
22+
23+
```
24+
type DrawText struct {
25+
JPG draw.Image
26+
Merged *os.File
27+
28+
Title string
29+
X0 int
30+
Y0 int
31+
Size0 float64
32+
33+
SubTitle string
34+
X1 int
35+
Y1 int
36+
Size1 float64
37+
}
38+
39+
func (a *ArticlePosterBg) DrawPoster(d *DrawText, fontName string) error {
40+
fontSource := setting.AppSetting.RuntimeRootPath + setting.AppSetting.FontSavePath + fontName
41+
fontSourceBytes, err := ioutil.ReadFile(fontSource)
42+
if err != nil {
43+
return err
44+
}
45+
46+
trueTypeFont, err := freetype.ParseFont(fontSourceBytes)
47+
if err != nil {
48+
return err
49+
}
50+
51+
fc := freetype.NewContext()
52+
fc.SetDPI(72)
53+
fc.SetFont(trueTypeFont)
54+
fc.SetFontSize(d.Size0)
55+
fc.SetClip(d.JPG.Bounds())
56+
fc.SetDst(d.JPG)
57+
fc.SetSrc(image.Black)
58+
59+
pt := freetype.Pt(d.X0, d.Y0)
60+
_, err = fc.DrawString(d.Title, pt)
61+
if err != nil {
62+
return err
63+
}
64+
65+
fc.SetFontSize(d.Size1)
66+
_, err = fc.DrawString(d.SubTitle, freetype.Pt(d.X1, d.Y1))
67+
if err != nil {
68+
return err
69+
}
70+
71+
err = jpeg.Encode(d.Merged, d.JPG, nil)
72+
if err != nil {
73+
return err
74+
}
75+
76+
return nil
77+
}
78+
```
79+
80+
这里主要使用了 freetype 包,分别涉及如下细项:
81+
82+
1、freetype.NewContext:创建一个新的 Context,会对其设置一些默认值
83+
84+
```
85+
func NewContext() *Context {
86+
return &Context{
87+
r: raster.NewRasterizer(0, 0),
88+
fontSize: 12,
89+
dpi: 72,
90+
scale: 12 << 6,
91+
}
92+
}
93+
```
94+
95+
2、fc.SetDPI:设置屏幕每英寸的分辨率
96+
97+
3、fc.SetFont:设置用于绘制文本的字体
98+
99+
4、fc.SetFontSize:以磅为单位设置字体大小
100+
101+
5、fc.SetClip:设置剪裁矩形以进行绘制
102+
103+
6、fc.SetDst:设置目标图像
104+
105+
7、fc.SetSrc:设置绘制操作的源图像,通常为 [image.Uniform](https://golang.org/pkg/image/#Uniform)
106+
107+
```
108+
var (
109+
// Black is an opaque black uniform image.
110+
Black = NewUniform(color.Black)
111+
// White is an opaque white uniform image.
112+
White = NewUniform(color.White)
113+
// Transparent is a fully transparent uniform image.
114+
Transparent = NewUniform(color.Transparent)
115+
// Opaque is a fully opaque uniform image.
116+
Opaque = NewUniform(color.Opaque)
117+
)
118+
```
119+
120+
8、fc.DrawString:根据 Pt 的坐标值绘制给定的文本内容
121+
122+
### 业务逻辑
123+
124+
打开 service/article_service/article_poster.go 方法,在 Generate 方法增加绘制文字的代码逻辑,如下:
125+
126+
```
127+
func (a *ArticlePosterBg) Generate() (string, string, error) {
128+
fullPath := qrcode.GetQrCodeFullPath()
129+
fileName, path, err := a.Qr.Encode(fullPath)
130+
if err != nil {
131+
return "", "", err
132+
}
133+
134+
if !a.CheckMergedImage(path) {
135+
...
136+
137+
draw.Draw(jpg, jpg.Bounds(), bgImage, bgImage.Bounds().Min, draw.Over)
138+
draw.Draw(jpg, jpg.Bounds(), qrImage, qrImage.Bounds().Min.Sub(image.Pt(a.Pt.X, a.Pt.Y)), draw.Over)
139+
140+
err = a.DrawPoster(&DrawText{
141+
JPG: jpg,
142+
Merged: mergedF,
143+
144+
Title: "Golang Gin 系列文章",
145+
X0: 80,
146+
Y0: 160,
147+
Size0: 42,
148+
149+
SubTitle: "---煎鱼",
150+
X1: 320,
151+
Y1: 220,
152+
Size1: 36,
153+
}, "msyhbd.ttc")
154+
155+
if err != nil {
156+
return "", "", err
157+
}
158+
}
159+
160+
return fileName, path, nil
161+
}
162+
```
163+
164+
## 验证
165+
166+
访问生成文章海报的接口 `$HOST/api/v1/articles/poster/generate?token=$token`,检查其生成结果,如下图
167+
168+
![image](https://i.imgur.com/qaaG0LE.jpg)
169+
170+
## 总结
171+
172+
在本章节在 [连载十五](https://github.com/EDDYCJY/blog/blob/master/golang/gin/2018-07-04-Gin%E5%AE%9E%E8%B7%B5-%E8%BF%9E%E8%BD%BD%E5%8D%81%E4%BA%94-%E7%94%9F%E6%88%90%E4%BA%8C%E7%BB%B4%E7%A0%81-%E5%90%88%E5%B9%B6%E6%B5%B7%E6%8A%A5.md) 的功能上增加了绘制文字,在实现上并不困难,而这两块需求一般会同时出现,大家可以多加练习,了解里面的逻辑和其他 API 😁
173+
174+
## 参考
175+
### 本系列示例代码
176+
- [go-gin-example](https://github.com/EDDYCJY/go-gin-example)

0 commit comments

Comments
 (0)