Golangで色んなQRコードを作成する

掲載日
更新日

はじめに

サイトにQRコード生成ツールを作りたいなと思い、調べたところいくつかライブラリがあるようです。
おそらく最もメジャーなのはQR以外のコードの生成にも対応しているboombuler/barcodeですが、今回はQRコードの中央に画像を入れたり色々出来たらいいなと思ったので別のものを探しました。

その後見つけたのが、中央に画像を入れたり、画像をQRのドット(ハーフトーン)で表現できるyeqown/go-qrcode

使い方

シンプルにQRコードを出力するときは、Quick Startに書いてあるコードをコピペして実行すればOK。

package main

import (
	"fmt"

	"github.com/yeqown/go-qrcode/v2"
	"github.com/yeqown/go-qrcode/writer/standard"
)

func main() {
	qrc, err := qrcode.New("QR Content")
	if err != nil {
		fmt.Printf("could not generate QRCode: %v", err)
		return
	}

	w, err := standard.New("[QRコードを配置したいパス]/sample.jpeg")
	if err != nil {
		fmt.Printf("standard.New failed: %v", err)
		return
	}

	if err = qrc.Save(w); err != nil {
		fmt.Printf("could not save image: %v", err)
	}
}

エンコード時のオプション

QRコードエンコード時のオプションです。オプションを使う場合、

qrcode.New("QR Content")

としていたところを以下のように変更する必要があります。

qrcode.NewWith("QR Content",
	qrcode.WithEncodingMode(qrcode.EncModeNumeric),               // エンコードモード指定
	qrcode.WithErrorCorrectionLevel(qrcode.ErrorCorrectionQuart), //
 誤り訂正の許容率
)

エンコードモード指定

QRコードにはデータの種類に応じて圧縮を行い、 効率的にデータを格納する仕組みがあるようで、それを指定できるのがエンコードモードになります。詳しくはこちら
(数字だけのデータの場合は数字モードにすることで、小さいQRコードの画像にすることができる。なので、表現するデータの種類に応じて最適なモードにすることでより小さい画像で済む。ということかなと思います。間違ってたら教えてください。)

const (
	// デフォルト設定と思われるが謎
	EncModeNone encMode = 1 << iota
	// 数字
	EncModeNumeric
	// 英数字と一部記号
	EncModeAlphanumeric
	// バイナリ
	EncModeByte
	// 漢字
	EncModeJP
)

誤り訂正の許容率

QRコードはある程度情報が欠損して(印刷が掠れていたり、経年劣化で欠けてしまって)いても読み取れるようになっています。

どの程度の欠損を許容するかのオプションが以下になります。

const (
	// Level L: 7% 
	ErrorCorrectionLow ecLevel = iota + 1
	// Level M: 15%  // Good default choice. というコメントがあるのでデフォルトではこれになってると思われる。
	ErrorCorrectionMedium
	// Level Q: 25% 
	ErrorCorrectionQuart
	// Level H: 30% 
	ErrorCorrectionHighest
)

QRコードのレイアウト

QRコードの画像のレイアウトを変更するオプションです。(色を付けたり、画像を中に加えたり。)
ここに上げるオプションはすべてこちらの例から確認できます。
オプションを指定する場合、

w, err := standard.New("[QRコードを配置したいパス]/sample.jpeg")

としていたところを、以下のように修正する必要があります。

options := []standard.ImageOption{
	// ここにオプション群...
}

w, err := standard.New("[QRコードを配置したいパス]/sample.jpeg", options...)

QRコード部分のサイズ

設定変更でQRドット部分が変わることを示す画像

QRコードはドットが描画されている部分と余白部分があります。
ドット部分のサイズを指定するオプションが以下になります。

options := []standard.ImageOption{
	standard.WithQRWidth(5),
}

数値はそのままpxにはならず、以下で基準となるpxが取得でき、それに対して指定の数字を掛け算するようです。

qrc,err := qrcode.New("QR Content")

dimension := qrc.Dimension()
fmt.Println(dimension)
// -> 21 となるので、WithQRWidthが 2 なら 21 * 2 で 42となる

qrc,err := qrcode.New("QR Content Long Sentence")
dimension := qrc.Dimension()
fmt.Println(dimension)
// -> 文章を長くしたので、29となり、この時WithQRWidthが2なら 29 * 2 で58となる

余白のサイズ

設定変更で余白部分のサイズが変わることを示す画像

前述のオプションとは逆に、余白部分のサイズも指定できます。
(なお、QRコードはある程度余白がないと読み取れないようなので、狭くし過ぎるのは厳禁。ポスターなどに余白付きで配置するなら関係ないですが。)
数値はそのままpxですが、実際は上下左右に配置されるので指定の数値の2倍の画像サイズになるので注意が必要です。
バラバラに指定することも可能です。(左は10px, 右は20px余白など、そんなシチュエーションあるのだろうか。)

options := []standard.ImageOption{
	standard.WithBorderWidth(40),
}

ドットを丸にする

QRドット部分を丸にした画像

QRのドット部分を四角から丸にすることが可能です。

options := []standard.ImageOption{
	standard.WithCircleShape(),
}

出力する画像のフォーマットを指定する

出力するQRコード画像のフォーマットをpng, jpgから選択できます。

options := []standard.ImageOption{
	// standard.WithBuiltinImageEncoder(standard.JPEG_FORMAT), // jpg
	standard.WithBuiltinImageEncoder(standard.PNG_FORMAT), //png
}

// w, err := standard.New("sample1.jpeg", options...) // こっちで拡張子変えるのを忘れず
w, err := standard.New("sample1.png", options...)

画像の背景を透過する

画像の背景を透過することができます。
なお、前述のオプションでjpgを指定していると透過できないので注意が必要です。(jpgは透過画像を扱えないため。)
また、背景を透過する場合、QRコードを配置する位置の背景色には注意が必要です。
(ドット部分とのコントラストがあまり無い背景色だと読み取れない可能性があります。)

options := []standard.ImageOption{
	standard.WithBuiltinImageEncoder(standard.PNG_FORMAT),
	standard.WithBgTransparent(),
}

QRコードの色

QRドット部分を青色に変更した画像

QRドット部分の色を設定できます。なお、前述のオプションにも書いた通り背景色とのコントラストには注意。

options := []standard.ImageOption{
	standard.WithFgColor(color.RGBA{0, 0, 255, 255}),
}

背景色

QR背景色部分を水色に変更した画像

背景色も設定できます。くどいですがドット部分とのコントラストには注意。

options := []standard.ImageOption{
	standard.WithBgColor(color.RGBA{124, 252, 0, 255}),
}

QRコードにグラデーションを付ける

QRドット部分を赤緑青のグラデーションに変更した画像

QRドット部分にグラデーションもかけられます。

stops := []standard.ColorStop{
	{Color: color.RGBA{255, 0, 0, 255}, T: 0.0}, // Tで指定の色まで変わる距離を指定できる
	{Color: color.RGBA{0, 255, 0, 255}, T: 0.5},
	{Color: color.RGBA{0, 0, 255, 255}, T: 1},
}
gradient := standard.NewGradient(45, stops...) // 45angle(角度)の指定


options := []standard.ImageOption{
	standard.WithFgGradient(gradient),
}

ハーフトーン画像を設定する

QRドット部分で指定した画像を表現したQRコード画像

ドット部分で指定した画像を表現することも出来ます。
(分かりにくいですが、Goのロゴを右下に配置した画像を読み込ませてみたのが添付画像の例です。)

halftonePath := "./halftone_sample.png"
if _, err := os.Stat(halftonePath); os.IsNotExist(err) {
	fmt.Printf("halftone image file %s not found\n", halftonePath)
	return
}

options := []standard.ImageOption{
	standard.WithHalftone(halftonePath),
}

中心に画像を表示する

中心に画像を表示したQRコード画像

QRコードの中心に画像を表示する設定が可能です。
中央にSNSのロゴマークを表示して、お店のSNSアカウントに誘導するようなQRコードをよく見かけますが、そういったものを作る際に使える一番需要のありそうな設定。
※ 指定した画像のサイズが大きい場合「WithQRWidth」の設定と調整が必要になる可能性があります。

options := []standard.ImageOption{
	standard.WithLogoImageFilePNG("sample_logo.png"),
}

終わりに

GolangでQRコードを作成するライブラリとそのオプションをまとめました。
QRコードの中心に画像を表示したり、ドット部分に色を付けたりするツールを作りたかったのでこのライブラリの存在は大変ありがたいです。

 

記事の作成者のA.W.のアイコン

この記事を書いた人

A.W.
茨城県在住Webエンジニアです。 PHPなどを業務で使用しています。 趣味ではGoやNuxt、Flutterをやってます。

Comment