Go中操作图片需要使用到库,github.com/disintegration/imaging

代码和效果图如下:

1563699357187

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package main

import (
"fmt"
"github.com/bregydoc/gtranslate"
"image"
"image/color"
"io/ioutil"
"unicode/utf8"

"github.com/disintegration/imaging"
"github.com/golang/freetype"
"github.com/golang/freetype/truetype"
"golang.org/x/image/font"
)

const (
FontSize = 20
SquareHeight = 200
)

func main() {
HandleUserImage()
}

// HandleUserImage paste user image onto background
func HandleUserImage() (string, error) {
m, err := imaging.Open("target.png")
if err != nil {
fmt.Println("open file failed", err)
return "", err
}

bm, err := imaging.Open("bg.jpg")
if err != nil {
fmt.Println("open file failed", err)
return "", err
}

// 图片按比例缩放
dst := imaging.Resize(m, bm.Bounds().Max.X, SquareHeight, imaging.Lanczos)
// 将图片粘贴到背景图的固定位置 最后的参数控制虚化程度
result := imaging.Overlay(bm, dst, image.Pt(0, bm.Bounds().Max.Y-SquareHeight), 0.3)
writeOnImage(result)

fileName := fmt.Sprintf("%d.jpg", 1234)
err = imaging.Save(result, fileName)
if err != nil {
return "", err
}

return fileName, nil
}

func writeOnImage(target *image.NRGBA) {
c := freetype.NewContext()

// 设置屏幕每英寸的分辨率
c.SetDPI(256)
// 背景
c.SetClip(target.Bounds())
// 设置目标图像
c.SetDst(target)
c.SetHinting(font.HintingFull)

// 设置文字颜色、字体、字大小
c.SetSrc(image.NewUniform(color.RGBA{R: 220, G: 220, B: 220, A: 220}))
// 以磅为单位设置字体大小
c.SetFontSize(FontSize)
fontFam, err := getFontFamily()
if err != nil {
fmt.Println("get font family error")
}
// 设置用于绘制文本的字体
c.SetFont(fontFam)

drawStr := "你好,世界"

// 获取字体的尺寸大小
fixed := c.PointToFixed(FontSize)
// fixed.Ceil() 字体大小
// utf8.RuneCountInString(drawStr) 获取字符串的实际大小,而不是以byte算
pt := freetype.Pt(target.Rect.Max.X/2-(utf8.RuneCountInString(drawStr)/2)*fixed.Ceil(), target.Rect.Max.Y-SquareHeight+SquareHeight/2)

fontPin, err := c.DrawString(drawStr, pt)
if err != nil {
fmt.Printf("draw error: %v \n", err)
return
}

// 翻译文字,附加一行,以增强国际化(big)
translated, err := gtranslate.TranslateWithFromTo(
drawStr,
gtranslate.FromTo{
From: "zh-cn",
To: "ja",
},
)
if err != nil {
fmt.Printf("translate error: %v \n", err)
return
}

_, err = c.DrawString(translated, freetype.Pt(target.Rect.Max.X/2-(utf8.RuneCountInString(translated)/2)*fixed.Ceil(), fontPin.Y.Ceil()+fixed.Ceil()))
if err != nil {
fmt.Printf("draw error: %v \n", err)
return
}
}

// 获取字符集,仅调用一次
func getFontFamily() (*truetype.Font, error) {
// 这里需要读取中文字体,否则中文文字会变成方格
fontBytes, err := ioutil.ReadFile("msyh.ttc")
if err != nil {
fmt.Println("read file error:", err)
return &truetype.Font{}, err
}

f, err := freetype.ParseFont(fontBytes)
if err != nil {
fmt.Println("parse font error:", err)
return &truetype.Font{}, err
}

return f, err
}