码迷,mamicode.com
首页 > 其他好文 > 详细

生成二维码

时间:2018-07-26 18:44:47      阅读:154      评论:0      收藏:0      [点我收藏+]

标签:writer   add   decode   bytes   tin   freetype   Fix   class   rbo   

package main

import (
    "bytes"
    "encoding/base64"
    "encoding/json"
    "fmt"
    "image"
    "image/color"
    "image/draw"
    "image/gif"
    "image/jpeg"
    "image/png"
    "io/ioutil"
    "log"
    "net/http"

    "code.google.com/p/rsc/qr"
    "code.google.com/p/rsc/qr/web/resize"
    "github.com/golang/freetype"
    "github.com/golang/freetype/truetype"
    "golang.org/x/image/bmp"
    "golang.org/x/image/font"
    "golang.org/x/image/math/fixed"
)

type circle struct {
    p image.Point
    r int
}

func (c *circle) ColorModel() color.Model {
    return color.AlphaModel
}

func (c *circle) Bounds() image.Rectangle {
    return image.Rect(c.p.X-c.r, c.p.Y-c.r, c.p.X+c.r, c.p.Y+c.r)
}

func (c *circle) At(x, y int) color.Color {
    xx, yy, rr := float64(x-c.p.X)+0.5, float64(y-c.p.Y)+0.5, float64(c.r)
    if xx*xx+yy*yy < rr*rr {
        return color.Alpha{255}
    }
    return color.Alpha{0}
}

var (
    // bgImage 漂亮的背景
    bgImage = getNetImage("http://olcd71ai5.bkt.clouddn.com/qr/bg.png")

    // fontFile 字体文件
    fontFile = "config/Dengl.ttf"

    // fontSize 字体尺寸
    fontSize float64 = 18

    // fontDPI 屏幕每英寸的分辨率
    fontDPI float64 = 72

    // font 字体
    fontType *truetype.Font
)

func init() {
    fontBytes, err := ioutil.ReadFile(fontFile)
    if err != nil {
        panic(err)
    }
    fontType, err = freetype.ParseFont(fontBytes)
    if err != nil {
        panic(err)
    }
}

func main() {
    http.HandleFunc("/qr", qrImage)
    fmt.Println(http.ListenAndServe(":8080", nil))
}

func qrImage(w http.ResponseWriter, req *http.Request) {
    content := req.FormValue("data")
    data, err := base64.StdEncoding.DecodeString(content)
    if err != nil {
        log.Println(err)
        return
    }

    v := struct {
        URL      string `json:"url"`
        HeadURL  string `json:"headurl"`
        NickName string `json:"nickname"`
    }{}
    json.Unmarshal(data, &v)
    sx, sy, width := 110, 915, 120
    qrCode, _ := qr.Encode(v.URL, qr.L)
    pngData := qrCode.PNG()
    imgQrPng, _ := png.Decode(bytes.NewReader(pngData))
    imgQrPng = resize.Resample(imgQrPng, imgQrPng.Bounds(), width, width)
    qrBounds := imgQrPng.Bounds()
    qrDx := qrBounds.Dx()
    qrDy := qrBounds.Dy()

    img := image.NewRGBA(bgImage.Bounds())
    draw.Draw(img, bgImage.Bounds(), bgImage, image.Pt(0, 0), draw.Src)

    for x := 0; x < qrDx; x++ {
        for y := 0; y < qrDy; y++ {
            qrColor := imgQrPng.At(x, y)
            r, g, b, _ := qrColor.RGBA()
            if r == 0 || g == 0 || b == 0 {
                img.Set(sx+x, sy+y, qrColor)
            }
        }
    }

    if v.HeadURL != "" {
        headImage := getNetImage(v.HeadURL)
        headImage = resize.Resample(headImage, headImage.Bounds(), 100, 100)
        sp := image.Pt(250, 80)
        rect := headImage.Bounds().Add(sp)
        draw.DrawMask(img, rect, headImage, image.ZP, &circle{image.Pt(50, 50), 50}, image.ZP, draw.Over)
    }

    if v.NickName != "" {
        d := &font.Drawer{
            Dst: img,
            Src: image.NewUniform(color.RGBA{0xff, 0x00, 0x00, 0xff}),
            Face: truetype.NewFace(fontType, &truetype.Options{
                Size:    fontSize,
                DPI:     fontDPI,
                Hinting: font.HintingNone,
            }),
        }

        d.Dot = fixed.Point26_6{
            X: (fixed.I(600) - d.MeasureString(v.NickName)) / 2,
            Y: fixed.I(205),
        }
        d.DrawString(v.NickName)
    }

    w.Header().Set("Content-Type", "image/jpeg")
    jpeg.Encode(w, img, &jpeg.Options{Quality: 90})
}

func getNetImage(url string) image.Image {
    resp, err := http.Get(url)
    if err != nil {
        log.Println(err)
        return image.NewNRGBA(image.Rect(0, 0, 600, 400))
    }
    defer resp.Body.Close()
    data, _ := ioutil.ReadAll(resp.Body)
    contentType := http.DetectContentType(data)
    var imgBG image.Image
    if contentType == "image/png" {
        imgBG, err = png.Decode(bytes.NewReader(data))
    } else if contentType == "image/jpeg" {
        imgBG, err = jpeg.Decode(bytes.NewReader(data))
    } else if contentType == "image/gif" {
        imgBG, err = gif.Decode(bytes.NewReader(data))
    } else if contentType == "image/bmp" {
        imgBG, err = bmp.Decode(bytes.NewReader(data))
    }
    if err != nil {
        log.Println(err)
        return image.NewNRGBA(image.Rect(0, 0, 600, 400))
    }
    return imgBG
}

生成二维码

标签:writer   add   decode   bytes   tin   freetype   Fix   class   rbo   

原文地址:https://www.cnblogs.com/Csir/p/9372588.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!