Skip to content

Commit

Permalink
Add DisableBorder option to disable the QR Code quiet zone entirely, …
Browse files Browse the repository at this point in the history
…thus no more margins/borders. Defaults to borders for compatibility.
  • Loading branch information
skip2 committed Oct 17, 2019
1 parent f409379 commit cb3bf7b
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 10 deletions.
22 changes: 22 additions & 0 deletions example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ package qrcode

import (
"fmt"
"image/color"
"os"
"testing"
)
Expand All @@ -29,3 +30,24 @@ func TestExampleWriteFile(t *testing.T) {
}
}
}

func TestExampleEncodeWithColourAndWithoutBorder(t *testing.T) {
q, err := New("https://example.org", Medium)
if err != nil {
t.Errorf("Error: %s", err)
return
}

// Optionally, disable the QR Code border.
q.DisableBorder = true

// Optionally, set the colours.
q.ForegroundColor = color.RGBA{R: 0x33, G: 0x33, B: 0x66, A: 0xff}
q.BackgroundColor = color.RGBA{R: 0xef, G: 0xef, B: 0xef, A: 0xff}

err = q.WriteFile(256, "example2.png")
if err != nil {
t.Errorf("Error: %s", err)
return
}
}
22 changes: 15 additions & 7 deletions qrcode.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,9 @@ type QRCode struct {
ForegroundColor color.Color
BackgroundColor color.Color

// Disable the QR Code border.
DisableBorder bool

encoder *dataEncoder
version qrCodeVersion

Expand Down Expand Up @@ -193,8 +196,6 @@ func New(content string, level RecoveryLevel) (*QRCode, error) {
version: *chosenVersion,
}

q.encode(chosenVersion.numTerminatorBitsRequired(encoded.Len()))

return q, nil
}

Expand Down Expand Up @@ -239,8 +240,6 @@ func newWithForcedVersion(content string, version int, level RecoveryLevel) (*QR
version: *chosenVersion,
}

q.encode(chosenVersion.numTerminatorBitsRequired(encoded.Len()))

return q, nil
}

Expand All @@ -251,6 +250,9 @@ func newWithForcedVersion(content string, version int, level RecoveryLevel) (*QR
// The bitmap includes the required "quiet zone" around the QR Code to aid
// decoding.
func (q *QRCode) Bitmap() [][]bool {
// Build QR code.
q.encode()

return q.symbol.bitmap()
}

Expand All @@ -268,6 +270,9 @@ func (q *QRCode) Bitmap() [][]bool {
// negative number to increase the scale of the image. e.g. a size of -5 causes
// each module (QR Code "pixel") to be 5px in size.
func (q *QRCode) Image(size int) image.Image {
// Build QR code.
q.encode()

// Minimum pixels (both width and height) required.
realSize := q.symbol.size

Expand Down Expand Up @@ -296,11 +301,12 @@ func (q *QRCode) Image(size int) image.Image {
// Map each image pixel to the nearest QR code module.
modulesPerPixel := float64(realSize) / float64(size)
for y := 0; y < size; y++ {
y2 := int(float64(y) * modulesPerPixel)
for x := 0; x < size; x++ {
y2 := int(float64(y) * modulesPerPixel)
x2 := int(float64(x) * modulesPerPixel)

v := bitmap[y2][x2]

if v {
pos := img.PixOffset(x, y)
img.Pix[pos] = fgClr
Expand Down Expand Up @@ -368,7 +374,9 @@ func (q *QRCode) WriteFile(size int, filename string) error {
// encode completes the steps required to encode the QR Code. These include
// adding the terminator bits and padding, splitting the data into blocks and
// applying the error correction, and selecting the best data mask.
func (q *QRCode) encode(numTerminatorBits int) {
func (q *QRCode) encode() {
numTerminatorBits := q.version.numTerminatorBitsRequired(q.data.Len())

q.addTerminatorBits(numTerminatorBits)
q.addPadding()

Expand All @@ -381,7 +389,7 @@ func (q *QRCode) encode(numTerminatorBits int) {
var s *symbol
var err error

s, err = buildRegularSymbol(q.version, mask, encoded)
s, err = buildRegularSymbol(q.version, mask, encoded, !q.DisableBorder)

if err != nil {
log.Panic(err.Error())
Expand Down
5 changes: 5 additions & 0 deletions qrcode/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ func main() {
size := flag.Int("s", 256, "image size (pixel)")
textArt := flag.Bool("t", false, "print as text-art on stdout")
negative := flag.Bool("i", false, "invert black and white")
disableBorder := flag.Bool("d", false, "disable QR Code border")
flag.Usage = func() {
fmt.Fprintf(os.Stderr, `qrcode -- QR Code encoder in Go
https://github.com/skip2/go-qrcode
Expand Down Expand Up @@ -52,6 +53,10 @@ Usage:
q, err = qrcode.New(content, qrcode.Highest)
checkError(err)

if *disableBorder {
q.DisableBorder = true
}

if *textArt {
art := q.ToString(*negative)
fmt.Println(art)
Expand Down
2 changes: 2 additions & 0 deletions qrcode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,8 @@ func TestQRCodeISOAnnexIExample(t *testing.T) {
err.Error())
}

q.encode()

const expectedMask int = 2

if q.mask != 2 {
Expand Down
10 changes: 8 additions & 2 deletions regular_symbol.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,19 @@ var (
)

func buildRegularSymbol(version qrCodeVersion, mask int,
data *bitset.Bitset) (*symbol, error) {
data *bitset.Bitset, includeQuietZone bool) (*symbol, error) {

quietZoneSize := 0
if includeQuietZone {
quietZoneSize = version.quietZoneSize()
}

m := &regularSymbol{
version: version,
mask: mask,
data: data,

symbol: newSymbol(version.symbolSize(), version.quietZoneSize()),
symbol: newSymbol(version.symbolSize(), quietZoneSize),
size: version.symbolSize(),
}

Expand Down
2 changes: 1 addition & 1 deletion regular_symbol_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ func TestBuildRegularSymbol(t *testing.T) {
data.AppendNumBools(8, false)
}

s, err := buildRegularSymbol(*v, k, data)
s, err := buildRegularSymbol(*v, k, data, false)

if err != nil {
fmt.Println(err.Error())
Expand Down

0 comments on commit cb3bf7b

Please sign in to comment.