golang生成二维码图片,支持图片下方增加多行居中文本
golang生成二维码图片,支持图片下方增加多行居中文本
效果
工具类代码
package Utils
import (
"bytes"
"fmt"
"github.com/golang/freetype/truetype"
"github.com/skip2/go-qrcode"
"golang.org/x/image/font"
"golang.org/x/image/math/fixed"
"image"
"image/color"
"image/draw"
"image/png"
"os"
"regexp"
)
// GenQRCodeImg 生成二维码图片 用法:err := Utils.GenQRCodeImg("https://www.example.com", []string{"设备名称1122室行", "建筑物1-3教室行文字室行室行"}, 300, 20, "D:\\simhei.ttf", "output1.png")
func GenQRCodeImg(url string, textLines []string, qrSize, fontSize int, fontPath, savePath string) error {
img, err := genQRCode(url, textLines, qrSize, fontSize, fontPath)
if err != nil {
return err
}
// 保存图片
outFile, err := os.Create(savePath)
if err != nil {
fmt.Println("Error creating output file:", err)
return err
}
defer outFile.Close()
err = png.Encode(outFile, img)
return err
}
// GenQRCodeBuffer 生成二维码图片的字节数组 用法:buffer, err := Utils.GenQRCodeBuffer("https://www.example.com", []string{"设备名称1112室行", "建筑物2-3教室行文字室行室行"}, 300, 20, "D:\\simhei.ttf")
func GenQRCodeBuffer(url string, textLines []string, qrSize, fontSize int, fontPath string) (*bytes.Buffer, error) {
img, err := genQRCode(url, textLines, qrSize, fontSize, fontPath)
if err != nil {
return nil, err
}
// 将图片编码为字节数组
var buf bytes.Buffer
err = png.Encode(&buf, img)
if err != nil {
fmt.Println("Error encoding image:", err)
return nil, err
}
return &buf, nil
}
func genQRCode(url string, textLines []string, qrSize, fontSize int, fontPath string) (*image.RGBA, error) {
// 生成二维码
qr, err := qrcode.Encode(url, qrcode.Medium, qrSize)
if err != nil {
fmt.Println("Error generating QR code:", err)
return nil, err
}
// 解码二维码图片
qrImg, _, err := image.Decode(bytes.NewReader(qr))
if err != nil {
fmt.Println("Error decoding QR code:", err)
return nil, err
}
// 创建新图片,并将二维码绘制在图片上
img := image.NewRGBA(image.Rect(0, 0, qrSize, qrSize+len(textLines)*(fontSize+10)))
draw.Draw(img, img.Bounds(), &image.Uniform{color.White}, image.Point{}, draw.Src) // 设置白色背景
draw.Draw(img, img.Bounds(), qrImg, image.Point{}, draw.Over)
// 加载字体文件
fontBytes, err := os.ReadFile(fmt.Sprintf(fontPath))
if err != nil {
fmt.Println("Error reading font file:", err)
return nil, err
}
font, err := truetype.Parse(fontBytes)
if err != nil {
fmt.Println("Error parsing font:", err)
return nil, err
}
face := truetype.NewFace(font, &truetype.Options{Size: float64(fontSize)})
// 计算文字的位置
textY := qrSize - 10 + (len(textLines)-1)*fontSize
// 绘制文字
for i, line := range textLines {
textWidth := countChineseCharacters(line)*fontSize + countNonChineseCharacters(line)*fontSize/2
textX := (qrSize - textWidth) / 2 // 计算每行文字的水平居中位置
drawText(img, line, textX, textY+i*(fontSize+10), color.Black, face) // 将文字颜色黑色
}
return img, nil
}
// 绘制文字
func drawText(img draw.Image, text string, x, y int, c color.Color, face font.Face) {
d := &font.Drawer{
Dst: img,
Src: image.NewUniform(c),
Face: face,
Dot: fixed.Point26_6{X: fixed.Int26_6(x * 64), Y: fixed.Int26_6(y * 64)},
}
d.DrawString(text)
}
// 计算中文个数
func countChineseCharacters(input string) int {
// 正则表达式,用于匹配所有中文字符
chinesePattern := regexp.MustCompile(`[\p{Han}]`)
// 找到所有匹配的中文字符
matches := chinesePattern.FindAllString(input, -1)
// 返回匹配的中文字符数量
return len(matches)
}
// 计算非中文个数
func countNonChineseCharacters(input string) int {
// 正则表达式,用于匹配非中文字符
nonChinesePattern := regexp.MustCompile(`[^\p{Han}]`)
// 找到所有匹配的非中文字符
matches := nonChinesePattern.FindAllString(input, -1)
// 返回匹配的非中文字符数量
return len(matches)
}
调用
- 注意将D:\simhei.ttf替换成自己想要的字体文件的路径
package main
import (
"Utils"
)
func main() {
Utils.GenQRCodeImg("https://www.example.com", []string{"设备名称1122室行", "建筑物1-3教室行文字室行室行"}, 300, 20, "D:\\simhei.ttf", "output1.png")
}