You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

130 lines
2.6 KiB

package goqc
import (
"bytes"
"context"
"embed"
_ "embed"
"github.com/fogleman/gg"
"github.com/golang/freetype/truetype"
"github.com/nfnt/resize"
"github.com/skip2/go-qrcode"
"image/png"
"io"
"path/filepath"
)
//go:embed simhei.ttf
var fontContent embed.FS
var fontPath = "simhei.ttf"
var fontSize = 16.0
func loadFontPath(dc *gg.Context) error {
// 设置字体和文本属性
err := dc.LoadFontFace(fontPath, fontSize)
if err != nil {
return err
}
return nil
}
func loadFontEmbed(dc *gg.Context) error {
// 读取嵌入的字体文件
fontBytes, err := fontContent.ReadFile(fontPath)
if err != nil {
return err
}
// 设置字体
f, err := truetype.Parse(fontBytes)
if err != nil {
return err
}
// 文本属性
face := truetype.NewFace(f, &truetype.Options{
Size: fontSize,
})
dc.SetFontFace(face)
return nil
}
// QrCodeOperation 二维码操作
type QrCodeOperation struct {
ctx context.Context
dc *gg.Context
}
// QrCodeText 生成二维码带文本
func QrCodeText(ctx context.Context, textContent string, qcContent string, qcLevel qrcode.RecoveryLevel) (*QrCodeOperation, error) {
// 生成二维码
qr, err := qrcode.New(qcContent, qcLevel)
if err != nil {
return nil, err
}
// 设置二维码图片的大小
qrSize := 256
// 生成二维码图片
qrImage := qr.Image(qrSize)
// 调整二维码图片大小
qrImage = resize.Resize(uint(qrSize), uint(qrSize), qrImage, resize.Lanczos3)
// 使用 github.com/fogleman/gg 绘制文本
dc := gg.NewContext(qrSize, qrSize)
dc.DrawImage(qrImage, 0, 0)
// 设置字体和文本属性
err = loadFontEmbed(dc)
if err != nil {
return nil, err
}
// 设置文本颜色
dc.SetRGB(0, 0, 0)
// 计算文本尺寸
textWidth, textHeight := dc.MeasureString(textContent)
// 计算文本位置
x := (float64(qrSize) - textWidth) / 2
y := (float64(qrSize+qrSize) + textHeight - textHeight) / 2
// 绘制文本
dc.DrawStringAnchored(textContent, x, y-6, 0, 0)
return &QrCodeOperation{ctx: ctx, dc: dc}, err
}
// SavePNG 保存图片
func (o *QrCodeOperation) SavePNG(filePath, fileName string) error {
if fileName == "" {
return o.dc.SavePNG(filePath)
} else {
path := filepath.Join(filePath, "/", fileName)
return o.dc.SavePNG(path)
}
}
// Encode 返回图片字节
func (o *QrCodeOperation) Encode() ([]byte, error) {
img := o.dc.Image()
encoder := png.Encoder{CompressionLevel: png.BestCompression}
var b bytes.Buffer
err := encoder.Encode(&b, img)
if err != nil {
return nil, err
}
return b.Bytes(), nil
}
// EncodePNG 返回图片编码
func (o *QrCodeOperation) EncodePNG(w io.Writer) error {
return o.dc.EncodePNG(w)
}