Golang Gin Practice Series 15 generate two-dimensional code, merge poster
Original address: Golang Gin Practice Series 15 generate two-dimensional code, merge poster
Project Address: Https://github.com/EDDYCJY/go ...
If it helps, you're welcome to a Star.
Objective
In this section, you will implement the following functional fine-grained items:
1, generate two-dimensional code
2. Combined poster (background map + QR code)
Realize
First, you need to add the two-D code and the storage path of the poster to the APP configuration item, and we agree that the configuration item name is a QrCodeSavePath
value ofqrcode/
After multiple sections you should be able to complete, if you do not understand can refer to Go-gin-example
Generate two-dimensional code
Installation
$ go get -u github.com/boombuler/barcode
Tool Pack
Consider the creation of a QR code this action is the definition of the toolkit, and there is a common possibility to create a new Pkg/qrcode/qrcode.go file, write content:
Package Qrcodeimport ("Image/jpeg" "Github.com/boombuler/barcode" "Github.com/boombuler/barcode/qr" "GITHUB.C Om/eddycjy/go-gin-example/pkg/file "" Github.com/eddycjy/go-gin-example/pkg/setting "" github.com/EDDYCJY/ Go-gin-example/pkg/util ") type QRCode struct {URL string Width int Height int EXT string level QR.E Rrorcorrectionlevel Mode qr. Encoding}const (ext_jpg = ". JPG") func newqrcode (URL string, width, height int, level QR). Errorcorrectionlevel, mode QR. Encoding) *qrcode {return &qrcode{url:url, Width:width, height:height, Level: Level, Mode:mode, ext:ext_jpg,}}func getqrcodepath () string {return setting. Appsetting.qrcodesavepath}func Getqrcodefullpath () string {return setting. Appsetting.runtimerootpath + setting. Appsetting.qrcodesavepath}func Getqrcodefullurl (name string) string {return setting. Appsetting.prefixurl + "/" + Getqrcodepath () + Name}func GetQrcodefilename (value String) string {return util. EncodeMD5 (value)}func (q *qrcode) Getqrcodeext () string {return Q.ext}func (q *qrcode) checkencode (path string) bool { SRC: = path + getqrcodefilename (q.url) + q.getqrcodeext () if file. Checknotexist (src) = = true {return false} return True}func (q *qrcode) Encode (Path string) (string, String, Error) {Name: = Getqrcodefilename (Q.url) + q.getqrcodeext () src: = path + name if file. Checknotexist (src) = = True {code, ERR: = Qr. Encode (Q.url, Q.level, q.mode) if err! = Nil {return "", "", Err} code, err = barcode. Scale (code, q.width, q.height) if err! = Nil {return "", "", err} F, err: = file. Mustopen (name, path) if err! = Nil {return "", "", Err} defer f.close () Err = JPE G.encode (f, Code, nil) if err! = Nil {return "", "", Err}} return name, path, nil}
Here are the main focus func (q *QrCode) Encode
methods, do the following things:
- Get the QR code generation path
- Create two-dimensional code
- Zoom the QR code to the specified size
- New file to store QR code image
- Writes the image (QR code) to a file in the JPEG 4:2:0 baseline format
In addition jpeg.Encode(f, code, nil)
, the third parameter sets its image quality, with a default value of 75
// DefaultQuality is the default quality encoding parameter.const DefaultQuality = 75// Options are the encoding parameters.// Quality ranges from 1 to 100 inclusive, higher is better.type Options struct { Quality int}
Routing Methods
1, the first step
New Generatearticleposter method for interface development in Routers/api/v1/article.go
2, the second step
New routes in Routers/router.go's Apiv1 apiv1.POST("/articles/poster/generate", v1.GenerateArticlePoster)
3, the third step
Modify the Generatearticleposter method and write the corresponding build logic as follows:
const ( QRCODE_URL = "https://github.com/EDDYCJY/blog#gin%E7%B3%BB%E5%88%97%E7%9B%AE%E5%BD%95")func GenerateArticlePoster(c *gin.Context) { appG := app.Gin{c} qrc := qrcode.NewQrCode(QRCODE_URL, 300, 300, qr.M, qr.Auto) path := qrcode.GetQrCodeFullPath() _, _, err := qrc.Encode(path) if err != nil { appG.Response(http.StatusOK, e.ERROR, nil) return } appG.Response(http.StatusOK, e.SUCCESS, nil)}
Verify
Access via POST method http://127.0.0.1:8000/api/v1/articles/poster/generate?token=$token
(note $token)
Determine if the function is normal by checking two points, as follows:
1. Whether the result of access is 200
2. Whether the local directory successfully generated two-dimensional code image
Merge poster
In this section, the implementation of the two-dimensional code image and background map into a new picture, can be used for common promotional posters and other business scenarios
Background map
Save the background map as runtime/qrcode/bg.jpg (actual application, can exist in OSS or elsewhere)
Service method
Open the Service/article_service directory, create a new Article_poster.go file, and write the contents:
Package Article_serviceimport ("image" "Image/draw" "Image/jpeg" "OS" "github.com/eddycjy/go-gin-example/p Kg/file "" Github.com/eddycjy/go-gin-example/pkg/qrcode ") type Articleposter struct {postername string *article Qr *qrcode. Qrcode}func Newarticleposter (Postername string, article *article, QR *qrcode. QRCode) *articleposter {return &articleposter{postername:postername, article:article, Q R:QR,}}func Getposterflag () string {return ' poster '}func (a *articleposter) checkmergedimage (path string) BOOL {if file. Checknotexist (path+a.postername) = = true {return false} return True}func (a *articleposter) openmergedimage (Path String) (*os. File, error) {f, err: = file. Mustopen (a.postername, path) if err! = Nil {return nil, err} return F, Nil}type articleposterbg struct { Name string *articleposter *rect *pt}type Rect struct {Name string X0 int Y0 int X1 int Y1 int}type Pt struct {X int Y int}func NEWARTICLEPOSTERBG (name string, AP *articleposter, Rect *r ECT, PT *pt) *ARTICLEPOSTERBG {return &articleposterbg{name:name, Articleposter:ap, Rect:rect, Pt:pt,}}func (a *ARTICLEPOSTERBG) Generate (String, string, error) {F Ullpath: = QRCode. Getqrcodefullpath () fileName, path, err: = A.qr.encode (FullPath) if err! = Nil {return "", "", err} I F!a.checkmergedimage (path) {MERGEDF, err: = A.openmergedimage (path) if err! = Nil {return "", "", Err} defer mergedf.close () BgF, err: = file. Mustopen (a.name, path) if err! = Nil {return "", "", Err} defer bgf.close () QRF, ERR: = file. Mustopen (fileName, path) if err! = Nil {return "", "", Err} defer qrf.close () BgI Mage, err: = JPEG. Decode (BgF) if err! = Nil {return ' "," ", err} qrimage, err: = JPEG. Decode (QRF) if err! = Nil {return "", "", err} jpg: = image. Newrgba (image. Rect (a.rect.x0, A.rect.y0, a.rect.x1, a.rect.y1)) draw. Draw (jpg, jpg. Bounds (), Bgimage, Bgimage.bounds (). Min, Draw. Over) draw. Draw (jpg, jpg. Bounds (), Qrimage, Qrimage.bounds (). Min.sub (image. Pt (A.pt.x, A.pt.y)), draw. OVER) JPEG. Encode (MERGEDF, JPG, nil)} return fileName, path, nil}
Here func (a *ArticlePosterBg) Generate()
's how to focus on the method and do the following:
- Get the QR Code storage path
- Generate two-dimensional code images
- Check if the merged image (referring to the post-merge poster) exists
- If it does not exist, the image to be merged is generated MERGEDF
- Open a pre-stored background map BgF
- Open the generated QR code image QRF
- Decodes BgF and QRF returns an image. Image
- Create a new RGBA image
- Drawing a background map on an RGBA image (BgF)
- Draws a two-dimensional code image (QRF) on the specified point on an RGBA image that has a background map drawn
- Writes a well-drawn RGBA image to the merged image file (MERGEDF) in the JPEG 4:2:0 baseline format
Error code
New error code, error message
Routing Methods
Open the Routers/api/v1/article.go file, modify the Generatearticleposter method, write the final business logic (including the generated QR code and the merged poster), as follows:
Const (Qrcode_url = "https://github.com/EDDYCJY/blog#gin%E7%B3%BB%E5%88%97%E7%9B%AE%E5%BD%95") func Generatearticleposter (c *gin. Context) {appg: = App. GIN{C} article: = &article_service. article{} QR: = QRCode. Newqrcode (Qrcode_url, +, QR. M, QR. Auto)//Currently write dead Gin series path, can increase the business logic postername: = Article_service. Getposterflag () + "-" + qrcode. Getqrcodefilename (QR. URL) + QR. Getqrcodeext () Articleposter: = Article_service. Newarticleposter (Postername, article, QR) Articleposterbgservice: = Article_service. NEWARTICLEPOSTERBG ("Bg.jpg", Articleposter, &article_service. rect{x0:0, y0:0, x1:550, y1:700,}, &article_service. pt{x:125, y:298,},) _, FilePath, err: = Articleposterbgservice.generate () If ER R! = Nil {appg.response (http. Statusok, E.error_gen_article_poster_fail, nil) return} appg.response (http. Statusok, E.SUCCESS, map[string]string{"Poster_url": QRCode. Getqrcodefullurl (Postername), "Poster_save_url": FilePath + Postername,})}
This piece involves a lot of knowledge and is strongly recommended to read below, as follows:
- Image. Rect
- Image. Pt
- Image. Newrgba
- Jpeg. Encode
- Jpeg. Decode
- Draw. Op
- Draw. Draw
- Go-imagedraw-package
The libraries involved and associated are recommended to study
Staticfs
In the Routers/router.go file, add the following code:
r.StaticFS("/qrcode", http.Dir(qrcode.GetQrCodeFullPath()))
Verify
Access the full URL path, return the composite poster and sweep the QR code success is correct
Summarize
Two very common business functions are implemented in this section, namely the generation of QR codes and merged posters. I hope you can read the link I gave, this piece of knowledge, want to use good image processing function, must understand the corresponding ideas, extrapolate
Finally, I hope to help you.
Reference
Sample code for this series