前言
好久没发文章了,最近登录看到有朋友评论了golang生成二维码的文章,想了解下生成个性二维码的解决方案!
实现思路 ,网上搜相关资料几乎没有, 没有那就就自己想吧,就去看了下草料二维码;
然后突然就有感觉了 不就是把像素的颜色替换嘛 这还不简单
1 打开二维码图片
2 打开要填充的图片
3 将要填充的图片剪裁成和二维码一样大小
4 分析二维码的每个像素 替换成图片的像素就行了
以下是生成的例子:
例子
代码
package main
import (
"fmt"
"github.com/nfnt/resize"
"image"
"image/color"
"image/draw"
"log"
"os"
"time"
_ "image/jpeg"
_ "image/gif"
"image/png"
)
func main() {
// 打开二维码图片
qrFile, err := os.Open("img/qr.png")
if err != nil {
log.Fatalf("打开二维码失败 %s", err.Error())
return
}
defer qrFile.Close()
// 将二维码文件接码成图片
img, _, err := image.Decode(qrFile)
if err != nil {
log.Fatalf("image decode error %s", err.Error())
return
}
// 获取二维码的宽高
width, height := img.Bounds().Max.X, img.Bounds().Max.Y
// 打开要填充的图片
bgFile, err := os.Open("bg/7.jpg")
if err != nil {
log.Fatalf("打开填充图失败 %s", err.Error())
return
}
defer bgFile.Close()
// 将填充图解码成png图片
bgImg, _, err := image.Decode(bgFile)
if err != nil {
log.Fatalf("填充图解码失败 %s", err.Error())
return
}
// 获取填充图的宽高
bgWidth, bgHeight := bgImg.Bounds().Max.X, bgImg.Bounds().Max.Y
// 检测二维码和填充图宽高是否一致
if width != bgWidth || height != bgHeight {
// 如果不一致将填充图剪裁
bgImg = ImageResize(bgImg, width, height)
}
// 开始填充二维码
for y := 0; y < img.Bounds().Max.X; y++ {
for x := 0; x < img.Bounds().Max.X; x++ {
qrImgColor := img.At(x, y)
// 检测图片颜色 如果rgb值是 255 255 255 255 则像素点为白色 跳过
// 如果rgba值是 0 0 0 0 则为透明色 跳过
switch img.(type) {
case *image.NRGBA:
c := qrImgColor.(color.NRGBA)
if (c.R == 0 && c.G == 0 && c.B == 0 && c.A == 0) || (c.R == 255 && c.G == 255 && c.B == 255 && c.A == 255) {
continue
}
case *image.RGBA:
c := qrImgColor.(color.RGBA)
if (c.R == 0 && c.G == 0 && c.B == 0 && c.A == 0) || (c.R == 255 && c.G == 255 && c.B == 255 && c.A == 255) {
continue
}
}
// 获取要填充的图片的颜色
bgImgColor := bgImg.At(x, y)
// 填充颜色
switch bgImg.(type) {
case *image.RGBA64:
c := bgImgColor.(color.RGBA64)
img.(draw.Image).Set(x, y, color.RGBA64{R: c.R, G: c.G, B: c.B, A: c.A})
case *image.NRGBA:
c := bgImgColor.(color.NRGBA)
img.(draw.Image).Set(x, y, color.NRGBA{R: c.R, G: c.G, B: c.B, A: c.A})
case *image.RGBA:
c := bgImgColor.(color.RGBA)
img.(draw.Image).Set(x, y, color.RGBA{R: c.R, G: c.G, B: c.B, A: c.A})
case *image.YCbCr:
c := bgImgColor.(color.YCbCr)
img.(draw.Image).Set(x, y, color.YCbCr{Y: c.Y, Cb: c.Cb, Cr: c.Cr})
default:
fmt.Println("error")
}
}
}
filename := fmt.Sprintf("%s.png", time.Now().Format("20060102150405"))
// 写入文件
outFile, err := os.Create(filename)
if err != nil {
log.Fatal(err)
}
defer outFile.Close()
_ = png.Encode(outFile, img)
}
func ImageResize(src image.Image, w, h int) image.Image {
return resize.Resize(uint(w), uint(h), src, resize.Lanczos3)
}
注意
1 尽量用png的二维码和填充图
2 案例中png和jpg gif图片都可以填充 其他格式的图片自己加就行了
代码地址
https://github.com/lihaotian0607/qr
其他
另外附上封装好的
https://github.com/lihaotian0607/qrcode
生成普通二维码
var qr, err = qrcode.New("https://www.xxx.com/", qrcode.Highest)
设置头像
qr.SetAvatar(&qrcode.Avatar{
Src: "../static/1.jpg",
Width: 60,
Height: 60,
Round: 10,
})
设置背景图
qr.SetBackground(&qrcode.Background{
Src: "../static/3.png",
X: 70,
Y: 55,
Width: 270,
Height: 270,
})
设置前景图
qr.SetForeground("../static/2.png")
写入文件
img, err := qr.Generate(300)
if err != nil {
log.Fatal(err.Error())
return
}
file, err := os.Create("out.png")
if err != nil {
log.Fatalf("创建文件失败 %s", err.Error())
return
}
err = png.Encode(file, img)
if err != nil {
log.Fatalf("文件写入失败 %s", err.Error())
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。