使用GO语言的DrawString函数将日语绘制到图像上

我在Go语言中研究了如何绘制日语文字到图像上。由于找不到类似的文章,所以我决定发表一篇。

得出结论

通过加载包含日语字符的外部字体文件,我们可以绘制日语字符。

    ftBinary, err := ioutil.ReadFile("Koruri-Bold.ttf")
    ft, err := truetype.Parse(ftBinary)

为什么无法用日语绘制?

我想要绘制日本语,并参考了下面的文章,粗略地制作了一个能在图像中绘制日本语的源代码。

参考: 使用Go语言和彩色表情符号合成图像

然而,出现了熟悉的乱码问题。

mojibake.png

文字化けソース全文的意思是“文字乱码源代码”的全部内容。

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.png

全文源代码

: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())
}

广告
将在 10 秒后关闭
bannerAds