diff --git a/example/with-halftone/README.md b/example/with-halftone/README.md index e11e4e9..a53be2b 100644 --- a/example/with-halftone/README.md +++ b/example/with-halftone/README.md @@ -4,16 +4,33 @@ > the gap between qr blocks could mislead the recognizer. ```go + +var ( + transparent = flag.Bool("transparent", false, "set background to transparent") +) + func main() { qrc, err := qrcode.New("https://github.com/yeqown/go-qrcode") if err != nil { panic(err) } - - w0, err := standard.New("./repository_qrcode.png", + + options := []standard.ImageOption{ standard.WithHalftone("./test.jpeg"), standard.WithQRWidth(21), - ) + } + filename := "./halftone-qr.png" + + if *transparent { + options = append( + options, + standard.WithBuiltinImageEncoder(standard.PNG_FORMAT), + standard.WithBgTransparent(), + ) + filename = "./halftone-qr-transparent.png" + } + + w0, err := standard.New(filename, options...) handleErr(err) err = qrc.Save(w0) handleErr(err) @@ -26,4 +43,5 @@ func main() { #### output image - \ No newline at end of file + + diff --git a/example/with-halftone/halftone-qr-transparent.png b/example/with-halftone/halftone-qr-transparent.png new file mode 100644 index 0000000..1ef970c Binary files /dev/null and b/example/with-halftone/halftone-qr-transparent.png differ diff --git a/example/with-halftone/halftone-qr.jpeg b/example/with-halftone/halftone-qr.png similarity index 100% rename from example/with-halftone/halftone-qr.jpeg rename to example/with-halftone/halftone-qr.png diff --git a/example/with-halftone/main.go b/example/with-halftone/main.go index 3a06021..e629068 100644 --- a/example/with-halftone/main.go +++ b/example/with-halftone/main.go @@ -1,20 +1,40 @@ package main import ( + "flag" + "github.com/yeqown/go-qrcode/v2" "github.com/yeqown/go-qrcode/writer/standard" ) +var ( + transparent = flag.Bool("transparent", false, "set background to transparent") +) + func main() { + flag.Parse() + qrc, err := qrcode.New("https://github.com/yeqown/go-qrcode") if err != nil { panic(err) } - w0, err := standard.New("./repository_qrcode.png", + options := []standard.ImageOption{ standard.WithHalftone("./test.jpeg"), standard.WithQRWidth(21), - ) + } + filename := "./halftone-qr.png" + + if *transparent { + options = append( + options, + standard.WithBuiltinImageEncoder(standard.PNG_FORMAT), + standard.WithBgTransparent(), + ) + filename = "./halftone-qr-transparent.png" + } + + w0, err := standard.New(filename, options...) handleErr(err) err = qrc.Save(w0) handleErr(err) diff --git a/writer/standard/writer.go b/writer/standard/writer.go index 5f8f13a..b5c2581 100644 --- a/writer/standard/writer.go +++ b/writer/standard/writer.go @@ -139,7 +139,7 @@ func draw(mat qrcode.Matrix, opt *outputImageOptions) image.Image { 60, ) - //_ = imgkit.Save(halftoneImg, "mask.jpeg") + // _ = imgkit.Save(halftoneImg, "mask.jpeg") } // iterate the matrix to Draw each pixel @@ -168,10 +168,10 @@ func draw(mat qrcode.Matrix, opt *outputImageOptions) image.Image { for i := 0; i < 3; i++ { for j := 0; j < 3; j++ { ctx2.x, ctx2.y = ctx.x+float64(i)*halftoneW, ctx.y+float64(j)*halftoneW - ctx2.color = halftoneImg.At(x*3+i, y*3+j) if i == 1 && j == 1 { ctx2.color = ctx.color - // only center block keep the origin color. + } else { + ctx2.color = halftoneColor(halftoneImg, opt.bgTransparent, x*3+i, y*3+j) } shape.Draw(ctx2) } @@ -197,13 +197,34 @@ func draw(mat qrcode.Matrix, opt *outputImageOptions) image.Image { } // DONE(@yeqown): calculate the xOffset and yOffset which point(xOffset, yOffset) - //should icon upper-left to start + // should icon upper-left to start dc.DrawImage(opt.logoImage(), (w-logoWidth)/2, (h-logoHeight)/2) } done: return dc.Image() } +// halftoneImage is an image.Gray type image, which At(x, y) return color.Gray. +// black equals to color.Gray{0}, white equals to color.Gray{255}. +func halftoneColor(halftoneImage image.Image, transparent bool, x, y int) color.Color { + + c0 := halftoneImage.At(x, y) + c1, ok := halftoneImage.At(x, y).(color.Gray) + if !ok { + log.Printf("halftoneColor: not a gray image, got: %T\n", c0) + return c0 + } + + if c1.Y == 255 { + if transparent { + return color.RGBA{} + } + return color.RGBA{R: 255, G: 255, B: 255, A: 255} + } + + return color.RGBA{A: 255} +} + func validLogoImage(qrWidth, qrHeight, logoWidth, logoHeight, logoSizeMultiplier int) bool { return qrWidth >= logoSizeMultiplier*logoWidth && qrHeight >= logoSizeMultiplier*logoHeight }