前言

好久没发文章了,最近登录看到有朋友评论了golang生成二维码的文章,想了解下生成个性二维码的解决方案!

实现思路 ,网上搜相关资料几乎没有, 没有那就就自己想吧,就去看了下草料二维码;

然后突然就有感觉了 不就是把像素的颜色替换嘛 这还不简单

1 打开二维码图片
2 打开要填充的图片
3 将要填充的图片剪裁成和二维码一样大小
4 分析二维码的每个像素 替换成图片的像素就行了

以下是生成的例子:

例子

20200510163912.png
20200510163927.png
20200510164130.png
20200510164014.png

代码

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())
    }

孤独的根号3
1.8k 声望368 粉丝

提升就是一个不懂到懂的过程;