Skip to content

Commit

Permalink
support rMQR
Browse files Browse the repository at this point in the history
  • Loading branch information
shogo82148 committed Dec 19, 2022
1 parent f13727f commit b434369
Show file tree
Hide file tree
Showing 2 changed files with 134 additions and 0 deletions.
29 changes: 29 additions & 0 deletions cmd/qr/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/shogo82148/qrcode"
"github.com/shogo82148/qrcode/microqr"
"github.com/shogo82148/qrcode/rmqr"
)

func main() {
Expand All @@ -25,6 +26,8 @@ func main() {
encodeQR(level, filename)
} else if micro {
encodeMicroQR(level, filename)
} else if rmqr {
encodeRMQR(level, filename)
}
}

Expand Down Expand Up @@ -85,3 +88,29 @@ func encodeMicroQR(level, filename string) {
log.Fatal(err)
}
}

func encodeRMQR(level, filename string) {
var lv rmqr.Level
switch level {
case "m", "M":
lv = rmqr.LevelM
case "h", "H":
lv = rmqr.LevelH
}

data, err := io.ReadAll(os.Stdin)
if err != nil {
log.Fatal(err)
}
img, err := rmqr.Encode(data, rmqr.WithLevel(lv))
if err != nil {
log.Fatal(err)
}
var buf bytes.Buffer
if err := png.Encode(&buf, img); err != nil {
log.Fatal(err)
}
if err := os.WriteFile(filename, buf.Bytes(), 0o644); err != nil {
log.Fatal(err)
}
}
105 changes: 105 additions & 0 deletions rmqr/encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ package rmqr
import (
"errors"
"fmt"
"image"
"image/color"
"math"

"github.com/shogo82148/qrcode/bitmap"
Expand Down Expand Up @@ -210,6 +212,109 @@ LOOP:
return 0, false
}

type EncodeOptions interface {
apply(opts *encodeOptions)
}

type encodeOptions struct {
QuiteZone int
ModuleSize float64
Level Level
}

func newEncodeOptions(opts ...EncodeOptions) encodeOptions {
myopts := encodeOptions{
QuiteZone: 2,
ModuleSize: 1,
Level: LevelM,
}
for _, o := range opts {
o.apply(&myopts)
}
return myopts
}

type withModuleSize float64

func (opt withModuleSize) apply(opts *encodeOptions) {
opts.ModuleSize = float64(opt)
}

func WithModuleSize(size float64) EncodeOptions {
return withModuleSize(size)
}

type withQuiteZone int

func (opt withQuiteZone) apply(opts *encodeOptions) {
opts.QuiteZone = int(opt)
}

func WithQuiteZone(n int) EncodeOptions {
return withQuiteZone(n)
}

type withLevel Level

func (opt withLevel) apply(opts *encodeOptions) {
opts.Level = Level(opt)
}

func WithLevel(lv Level) EncodeOptions {
return withLevel(lv)
}

func Encode(data []byte, opts ...EncodeOptions) (image.Image, error) {
myopts := newEncodeOptions(opts...)

qr, err := New(myopts.Level, data)
if err != nil {
return nil, err
}
return qr.Encode(opts...)
}

func (qr *QRCode) Encode(opts ...EncodeOptions) (image.Image, error) {
myopts := newEncodeOptions(opts...)

binimg, err := qr.EncodeToBitmap()
if err != nil {
return nil, err
}

w := binimg.Bounds().Dx() + myopts.QuiteZone*2
W := int(math.Ceil(float64(w) * myopts.ModuleSize))
h := binimg.Bounds().Dy() + myopts.QuiteZone*2
H := int(math.Ceil(float64(h) * myopts.ModuleSize))
scale := myopts.ModuleSize
dX := float64(myopts.QuiteZone) * scale
dY := float64(myopts.QuiteZone) * scale

// create new paletted image
palette := color.Palette{
color.White, color.Black,
}
white := uint8(0)
black := uint8(1)
bounds := image.Rect(0, 0, W, H)
img := image.NewPaletted(bounds, palette)

// convert bitmap to image
for Y := bounds.Min.Y; Y < bounds.Max.Y; Y++ {
y := int(math.Floor((float64(Y) - dY) / scale))
for X := bounds.Min.X; X < bounds.Max.X; X++ {
x := int(math.Floor((float64(X) - dX) / scale))
c := binimg.BinaryAt(x, y)
if c {
img.SetColorIndex(X, Y, black)
} else {
img.SetColorIndex(X, Y, white)
}
}
}
return img, nil
}

func (qr *QRCode) EncodeToBitmap() (*bitmap.Image, error) {
var buf bitstream.Buffer
if err := qr.encodeToBits(&buf); err != nil {
Expand Down

0 comments on commit b434369

Please sign in to comment.