|
@@ -13,6 +13,7 @@ import (
|
|
|
"image/draw"
|
|
|
"image/jpeg"
|
|
|
"image/png"
|
|
|
+ "math"
|
|
|
"net/http"
|
|
|
)
|
|
|
|
|
@@ -21,15 +22,18 @@ func compositeImage(backgroundURL, qrContent string) (err error, imgByte []byte)
|
|
|
//backgroundURL := "https://images.unsplash.com/photo-1501854140801-50d01698950b" // 示例背景图片
|
|
|
//qrContent := "https://github.com/zeromicro/go-zero" // 二维码内容
|
|
|
//outputPath := "output.jpg" // 输出文件路径
|
|
|
- margin := 20 // 二维码距边缘的边距
|
|
|
- qrSize := 200 // 二维码原始大小(像素)
|
|
|
- cornerRadius := 15.0 // 二维码圆角半径
|
|
|
- borderSize := 5 // 二维码白色边框大小
|
|
|
- shadowBlur := 8.0 // 阴影模糊度
|
|
|
- shadowOpacity := 0.3 // 阴影透明度
|
|
|
+ //margin := 20 // 二维码距边缘的边距
|
|
|
+ rightMargin := 60
|
|
|
+ bottomMargin := 100
|
|
|
+ qrSize := 160 // 二维码原始大小(像素)
|
|
|
+ cornerRadius := 5.0 // 二维码圆角半径
|
|
|
+ borderCornerRadius := 10.0
|
|
|
+ borderSize := 10 // 二维码白色边框大小
|
|
|
+ shadowBlur := 0.0 // 阴影模糊度
|
|
|
+ shadowOpacity := 0.0 // 阴影透明度
|
|
|
|
|
|
// 创建带效果的二维码并合成到背景右下角
|
|
|
- imgByte, err = createQRComposite(backgroundURL, qrContent, margin, qrSize, cornerRadius, gconv.Float64(borderSize), shadowBlur, shadowOpacity)
|
|
|
+ imgByte, err = createQRComposite(backgroundURL, qrContent, rightMargin, bottomMargin, qrSize, cornerRadius, borderCornerRadius, gconv.Float64(borderSize), shadowBlur, shadowOpacity)
|
|
|
if err != nil {
|
|
|
return err, nil
|
|
|
}
|
|
@@ -37,7 +41,7 @@ func compositeImage(backgroundURL, qrContent string) (err error, imgByte []byte)
|
|
|
}
|
|
|
|
|
|
// 创建二维码合成图片
|
|
|
-func createQRComposite(backgroundURL, qrContent string, margin, qrSize int, cornerRadius, borderSize, shadowBlur, shadowOpacity float64) ([]byte, error) {
|
|
|
+func createQRComposite(backgroundURL, qrContent string, rightMargin, bottomMargin, qrSize int, cornerRadius, borderCornerRadius, borderSize, shadowBlur, shadowOpacity float64) ([]byte, error) {
|
|
|
// 1. 下载背景图片
|
|
|
bgImg, imgType, err := downloadImage(backgroundURL)
|
|
|
if err != nil {
|
|
@@ -45,7 +49,7 @@ func createQRComposite(backgroundURL, qrContent string, margin, qrSize int, corn
|
|
|
}
|
|
|
|
|
|
// 2. 生成带效果的二维码
|
|
|
- qrImg, err := generateStyledQRCode(qrContent, qrSize, color.Black, color.White, cornerRadius, borderSize, shadowBlur, shadowOpacity)
|
|
|
+ qrImg, err := generateStyledQRCode(qrContent, qrSize, color.Black, color.White, cornerRadius, borderCornerRadius, borderSize, shadowBlur, shadowOpacity)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
|
}
|
|
@@ -54,8 +58,8 @@ func createQRComposite(backgroundURL, qrContent string, margin, qrSize int, corn
|
|
|
bgBounds := bgImg.Bounds()
|
|
|
qrBounds := qrImg.Bounds()
|
|
|
pos := image.Point{
|
|
|
- X: bgBounds.Dx() - qrBounds.Dx() - margin,
|
|
|
- Y: bgBounds.Dy() - qrBounds.Dy() - margin,
|
|
|
+ X: bgBounds.Dx() - qrBounds.Dx() - rightMargin,
|
|
|
+ Y: bgBounds.Dy() - qrBounds.Dy() - bottomMargin,
|
|
|
}
|
|
|
|
|
|
// 4. 调整二维码大小(如果需要)
|
|
@@ -66,8 +70,8 @@ func createQRComposite(backgroundURL, qrContent string, margin, qrSize int, corn
|
|
|
finalQR = resize.Resize(uint(targetWidth), 0, qrImg, resize.Lanczos3)
|
|
|
// 重新计算位置
|
|
|
pos = image.Point{
|
|
|
- X: bgBounds.Dx() - finalQR.Bounds().Dx() - margin,
|
|
|
- Y: bgBounds.Dy() - finalQR.Bounds().Dy() - margin,
|
|
|
+ X: bgBounds.Dx() - finalQR.Bounds().Dx() - rightMargin,
|
|
|
+ Y: bgBounds.Dy() - finalQR.Bounds().Dy() - bottomMargin,
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -101,8 +105,7 @@ func downloadImage(url string) (image.Image, string, error) {
|
|
|
return img, imgType, nil
|
|
|
}
|
|
|
|
|
|
-// 生成带样式的二维码
|
|
|
-func generateStyledQRCode(content string, size int, fgColor, bgColor color.Color, cornerRadius, borderSize, shadowBlur, shadowOpacity float64) (image.Image, error) {
|
|
|
+func generateStyledQRCode(content string, size int, fgColor, bgColor color.Color, cornerRadius, borderCornerRadius, borderSize, shadowBlur, shadowOpacity float64) (image.Image, error) {
|
|
|
// 生成基本二维码
|
|
|
qr, err := qrcode.New(content, qrcode.Highest)
|
|
|
if err != nil {
|
|
@@ -115,28 +118,35 @@ func generateStyledQRCode(content string, size int, fgColor, bgColor color.Color
|
|
|
// 创建基本二维码图片
|
|
|
baseImg := qr.Image(size)
|
|
|
|
|
|
- // 创建带透明背景的画布
|
|
|
- dc := gg.NewContext(size, size)
|
|
|
+ // 计算带边框的总大小
|
|
|
+ borderWidth := int(math.Ceil(borderSize))
|
|
|
+ totalSize := size + 2*borderWidth
|
|
|
+
|
|
|
+ // 创建带透明背景的总画布
|
|
|
+ dc := gg.NewContext(totalSize, totalSize)
|
|
|
dc.SetColor(color.Transparent)
|
|
|
dc.Clear()
|
|
|
|
|
|
- // 绘制圆角矩形作为蒙版
|
|
|
+ // 1. 绘制圆角白色边框
|
|
|
+ dc.SetColor(color.White)
|
|
|
+ dc.DrawRoundedRectangle(0, 0, float64(totalSize), float64(totalSize), borderCornerRadius+borderSize)
|
|
|
+ dc.Fill()
|
|
|
+
|
|
|
+ // 2. 创建二维码的圆角蒙版
|
|
|
+ qrDC := gg.NewContext(size, size)
|
|
|
+ qrDC.SetColor(color.Transparent)
|
|
|
+ qrDC.Clear()
|
|
|
+
|
|
|
if cornerRadius > 0 {
|
|
|
- dc.DrawRoundedRectangle(0, 0, float64(size), float64(size), cornerRadius)
|
|
|
- dc.Clip()
|
|
|
+ qrDC.DrawRoundedRectangle(0, 0, float64(size), float64(size), cornerRadius)
|
|
|
+ qrDC.Clip()
|
|
|
}
|
|
|
|
|
|
- // 绘制二维码
|
|
|
- dc.DrawImage(baseImg, 0, 0)
|
|
|
+ // 3. 绘制二维码到蒙版
|
|
|
+ qrDC.DrawImage(baseImg, 0, 0)
|
|
|
|
|
|
- // 添加白色边框
|
|
|
- if borderSize > 0 {
|
|
|
- dc.ResetClip()
|
|
|
- dc.SetColor(color.White)
|
|
|
- dc.SetLineWidth(borderSize)
|
|
|
- dc.DrawRoundedRectangle(0, 0, float64(size), float64(size), cornerRadius)
|
|
|
- dc.Stroke()
|
|
|
- }
|
|
|
+ // 4. 将带蒙版的二维码绘制到总画布(居中)
|
|
|
+ dc.DrawImage(qrDC.Image(), borderWidth, borderWidth)
|
|
|
|
|
|
// 添加阴影效果
|
|
|
if shadowBlur > 0 && shadowOpacity > 0 {
|