golang 生成個性二維碼

前言

很久沒發文章了,最近登陸看到有朋友評論了golang生成二維碼的文章,想了解下生成個性二維碼的解決方案!git

實現思路 ,網上搜相關資料幾乎沒有, 沒有那就就本身想吧,就去看了下草料二維碼; github

而後忽然就有感受了 不就是把像素的顏色替換嘛 這還不簡單golang

1 打開二維碼圖片
2 打開要填充的圖片
3 將要填充的圖片剪裁成和二維碼同樣大小
4 分析二維碼的每一個像素 替換成圖片的像素就好了ui

如下是生成的例子:spa

例子

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圖片均可以填充 其餘格式的圖片本身加就好了code

代碼地址

https://github.com/lihaotian0607/qrorm

相關文章
相關標籤/搜索