使用GO语言的DrawString函数将日语绘制到图像上
我在Go语言中研究了如何绘制日语文字到图像上。由于找不到类似的文章,所以我决定发表一篇。
得出结论
通过加载包含日语字符的外部字体文件,我们可以绘制日语字符。
ftBinary, err := ioutil.ReadFile("Koruri-Bold.ttf")
ft, err := truetype.Parse(ftBinary)
为什么无法用日语绘制?
我想要绘制日本语,并参考了下面的文章,粗略地制作了一个能在图像中绘制日本语的源代码。
参考: 使用Go语言和彩色表情符号合成图像
然而,出现了熟悉的乱码问题。

文字化けソース全文的意思是“文字乱码源代码”的全部内容。
package main
import (
"bytes"
"fmt"
"image"
"image/png"
"os"
"github.com/golang/freetype/truetype"
"golang.org/x/image/font"
"golang.org/x/image/font/gofont/gobold"
"golang.org/x/image/math/fixed"
)
func main() {
// フォントの読み込み
ft, err := truetype.Parse(gobold.TTF)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
opt := truetype.Options{
Size: 90,
DPI: 0,
Hinting: 0,
GlyphCacheEntries: 0,
SubPixelsX: 0,
SubPixelsY: 0,
}
imageWidth := 100
imageHeight := 100
textTopMargin := 90
text := "あ"
img := image.NewRGBA(image.Rect(0, 0, imageWidth, imageHeight))
face := truetype.NewFace(ft, &opt)
dr := &font.Drawer{
Dst: img,
Src: image.Black,
Face: face,
Dot: fixed.Point26_6{},
}
dr.Dot.X = (fixed.I(imageWidth) - dr.MeasureString(text)) / 2
dr.Dot.Y = fixed.I(textTopMargin)
dr.DrawString(text)
buf := &bytes.Buffer{}
err = png.Encode(buf, img)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
file, err := os.Create(`test.png`)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
defer file.Close()
file.Write(buf.Bytes())
}
truetype.Parse(gobold.TTF) 在做什么?
我查看了源代码,了解了 truetype.Parse(gobold.TTF) 函数是用来加载字体文件的操作。
引用自Gobold.TTF字体文件
// generated by go run gen.go; DO NOT EDIT
// Package gobold provides the "Go Bold" TrueType font
// from the Go font family. It is a proportional-width, sans-serif font.
//
// See https://blog.golang.org/go-fonts for details.
package gobold
// TTF is the data for the "Go Bold" TrueType font.
var TTF = []byte{
0x00, 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x80, 0x00, 0x03, 0x00, 0x60, 0x4f, 0x53, 0x2f, 0x32,
// 以下略
我发现在评论中,Go Bold True Type 字体的二进制数据数组被注册为gobold.TTF。
查看评论中提到的The Go Blog – Go字体。
Go字体是WGL4字符集,并不包含日语。
因此,可以推测出由于没有相应的字符而出现乱码。
如果加载了包含日语字符的外部字体,就不会出现乱码。
正如前面所提到的,只要加载外部字体文件,就可以正确显示日语而不会出现乱码。
我使用了Koruri字体在日语字体上。(我预先下载好,并与GO二进制文件放在同一位置。)
ftBinary, err := ioutil.ReadFile("Koruri-Bold.ttf")
ft, err := truetype.Parse(ftBinary)
可以绘制日语的图像

全文源代码
:nihongook.go
package main
import (
"bytes"
"fmt"
"image"
"image/png"
"os"
"github.com/golang/freetype/truetype"
"golang.org/x/image/font"
"golang.org/x/image/font/gofont/gobold"
"golang.org/x/image/math/fixed"
)
func main() {
// フォントファイルを読み込み
ftBinary, err := ioutil.ReadFile("Koruri-Bold.ttf")
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
ft, err := truetype.Parse(ftBinary)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
opt := truetype.Options{
Size: 90,
DPI: 0,
Hinting: 0,
GlyphCacheEntries: 0,
SubPixelsX: 0,
SubPixelsY: 0,
}
imageWidth := 100
imageHeight := 100
textTopMargin := 90
text := "あ"
img := image.NewRGBA(image.Rect(0, 0, imageWidth, imageHeight))
face := truetype.NewFace(ft, &opt)
dr := &font.Drawer{
Dst: img,
Src: image.Black,
Face: face,
Dot: fixed.Point26_6{},
}
dr.Dot.X = (fixed.I(imageWidth) - dr.MeasureString(text)) / 2
dr.Dot.Y = fixed.I(textTopMargin)
dr.DrawString(text)
buf := &bytes.Buffer{}
err = png.Encode(buf, img)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
file, err := os.Create(`test.png`)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
defer file.Close()
file.Write(buf.Bytes())
}