You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
400 lines
8.5 KiB
400 lines
8.5 KiB
// Copyright 2011 The Go Authors. All rights reserved. |
|
// Use of this source code is governed by a BSD-style |
|
// license that can be found in the LICENSE file. |
|
|
|
package qr |
|
|
|
// PNG writer for QR codes. |
|
|
|
import ( |
|
"bytes" |
|
"encoding/binary" |
|
"hash" |
|
"hash/crc32" |
|
) |
|
|
|
// PNG returns a PNG image displaying the code. |
|
// |
|
// PNG uses a custom encoder tailored to QR codes. |
|
// Its compressed size is about 2x away from optimal, |
|
// but it runs about 20x faster than calling png.Encode |
|
// on c.Image(). |
|
func (c *Code) PNG() []byte { |
|
var p pngWriter |
|
return p.encode(c) |
|
} |
|
|
|
type pngWriter struct { |
|
tmp [16]byte |
|
wctmp [4]byte |
|
buf bytes.Buffer |
|
zlib bitWriter |
|
crc hash.Hash32 |
|
} |
|
|
|
var pngHeader = []byte("\x89PNG\r\n\x1a\n") |
|
|
|
func (w *pngWriter) encode(c *Code) []byte { |
|
scale := c.Scale |
|
siz := c.Size |
|
|
|
w.buf.Reset() |
|
|
|
// Header |
|
w.buf.Write(pngHeader) |
|
|
|
// Header block |
|
binary.BigEndian.PutUint32(w.tmp[0:4], uint32((siz+8)*scale)) |
|
binary.BigEndian.PutUint32(w.tmp[4:8], uint32((siz+8)*scale)) |
|
w.tmp[8] = 1 // 1-bit |
|
w.tmp[9] = 0 // gray |
|
w.tmp[10] = 0 |
|
w.tmp[11] = 0 |
|
w.tmp[12] = 0 |
|
w.writeChunk("IHDR", w.tmp[:13]) |
|
|
|
// Comment |
|
w.writeChunk("tEXt", comment) |
|
|
|
// Data |
|
w.zlib.writeCode(c) |
|
w.writeChunk("IDAT", w.zlib.bytes.Bytes()) |
|
|
|
// End |
|
w.writeChunk("IEND", nil) |
|
|
|
return w.buf.Bytes() |
|
} |
|
|
|
var comment = []byte("Software\x00QR-PNG http://qr.swtch.com/") |
|
|
|
func (w *pngWriter) writeChunk(name string, data []byte) { |
|
if w.crc == nil { |
|
w.crc = crc32.NewIEEE() |
|
} |
|
binary.BigEndian.PutUint32(w.wctmp[0:4], uint32(len(data))) |
|
w.buf.Write(w.wctmp[0:4]) |
|
w.crc.Reset() |
|
copy(w.wctmp[0:4], name) |
|
w.buf.Write(w.wctmp[0:4]) |
|
w.crc.Write(w.wctmp[0:4]) |
|
w.buf.Write(data) |
|
w.crc.Write(data) |
|
crc := w.crc.Sum32() |
|
binary.BigEndian.PutUint32(w.wctmp[0:4], crc) |
|
w.buf.Write(w.wctmp[0:4]) |
|
} |
|
|
|
func (b *bitWriter) writeCode(c *Code) { |
|
const ftNone = 0 |
|
|
|
b.adler32.Reset() |
|
b.bytes.Reset() |
|
b.nbit = 0 |
|
|
|
scale := c.Scale |
|
siz := c.Size |
|
|
|
// zlib header |
|
b.tmp[0] = 0x78 |
|
b.tmp[1] = 0 |
|
b.tmp[1] += uint8(31 - (uint16(b.tmp[0])<<8+uint16(b.tmp[1]))%31) |
|
b.bytes.Write(b.tmp[0:2]) |
|
|
|
// Start flate block. |
|
b.writeBits(1, 1, false) // final block |
|
b.writeBits(1, 2, false) // compressed, fixed Huffman tables |
|
|
|
// White border. |
|
// First row. |
|
b.byte(ftNone) |
|
n := (scale*(siz+8) + 7) / 8 |
|
b.byte(255) |
|
b.repeat(n-1, 1) |
|
// 4*scale rows total. |
|
b.repeat((4*scale-1)*(1+n), 1+n) |
|
|
|
for i := 0; i < 4*scale; i++ { |
|
b.adler32.WriteNByte(ftNone, 1) |
|
b.adler32.WriteNByte(255, n) |
|
} |
|
|
|
row := make([]byte, 1+n) |
|
for y := 0; y < siz; y++ { |
|
row[0] = ftNone |
|
j := 1 |
|
var z uint8 |
|
nz := 0 |
|
for x := -4; x < siz+4; x++ { |
|
// Raw data. |
|
for i := 0; i < scale; i++ { |
|
z <<= 1 |
|
if !c.Black(x, y) { |
|
z |= 1 |
|
} |
|
if nz++; nz == 8 { |
|
row[j] = z |
|
j++ |
|
nz = 0 |
|
} |
|
} |
|
} |
|
if j < len(row) { |
|
row[j] = z |
|
} |
|
for _, z := range row { |
|
b.byte(z) |
|
} |
|
|
|
// Scale-1 copies. |
|
b.repeat((scale-1)*(1+n), 1+n) |
|
|
|
b.adler32.WriteN(row, scale) |
|
} |
|
|
|
// White border. |
|
// First row. |
|
b.byte(ftNone) |
|
b.byte(255) |
|
b.repeat(n-1, 1) |
|
// 4*scale rows total. |
|
b.repeat((4*scale-1)*(1+n), 1+n) |
|
|
|
for i := 0; i < 4*scale; i++ { |
|
b.adler32.WriteNByte(ftNone, 1) |
|
b.adler32.WriteNByte(255, n) |
|
} |
|
|
|
// End of block. |
|
b.hcode(256) |
|
b.flushBits() |
|
|
|
// adler32 |
|
binary.BigEndian.PutUint32(b.tmp[0:], b.adler32.Sum32()) |
|
b.bytes.Write(b.tmp[0:4]) |
|
} |
|
|
|
// A bitWriter is a write buffer for bit-oriented data like deflate. |
|
type bitWriter struct { |
|
bytes bytes.Buffer |
|
bit uint32 |
|
nbit uint |
|
|
|
tmp [4]byte |
|
adler32 adigest |
|
} |
|
|
|
func (b *bitWriter) writeBits(bit uint32, nbit uint, rev bool) { |
|
// reverse, for huffman codes |
|
if rev { |
|
br := uint32(0) |
|
for i := uint(0); i < nbit; i++ { |
|
br |= ((bit >> i) & 1) << (nbit - 1 - i) |
|
} |
|
bit = br |
|
} |
|
b.bit |= bit << b.nbit |
|
b.nbit += nbit |
|
for b.nbit >= 8 { |
|
b.bytes.WriteByte(byte(b.bit)) |
|
b.bit >>= 8 |
|
b.nbit -= 8 |
|
} |
|
} |
|
|
|
func (b *bitWriter) flushBits() { |
|
if b.nbit > 0 { |
|
b.bytes.WriteByte(byte(b.bit)) |
|
b.nbit = 0 |
|
b.bit = 0 |
|
} |
|
} |
|
|
|
func (b *bitWriter) hcode(v int) { |
|
/* |
|
Lit Value Bits Codes |
|
--------- ---- ----- |
|
0 - 143 8 00110000 through |
|
10111111 |
|
144 - 255 9 110010000 through |
|
111111111 |
|
256 - 279 7 0000000 through |
|
0010111 |
|
280 - 287 8 11000000 through |
|
11000111 |
|
*/ |
|
switch { |
|
case v <= 143: |
|
b.writeBits(uint32(v)+0x30, 8, true) |
|
case v <= 255: |
|
b.writeBits(uint32(v-144)+0x190, 9, true) |
|
case v <= 279: |
|
b.writeBits(uint32(v-256)+0, 7, true) |
|
case v <= 287: |
|
b.writeBits(uint32(v-280)+0xc0, 8, true) |
|
default: |
|
panic("invalid hcode") |
|
} |
|
} |
|
|
|
func (b *bitWriter) byte(x byte) { |
|
b.hcode(int(x)) |
|
} |
|
|
|
func (b *bitWriter) codex(c int, val int, nx uint) { |
|
b.hcode(c + val>>nx) |
|
b.writeBits(uint32(val)&(1<<nx-1), nx, false) |
|
} |
|
|
|
func (b *bitWriter) repeat(n, d int) { |
|
for ; n >= 258+3; n -= 258 { |
|
b.repeat1(258, d) |
|
} |
|
if n > 258 { |
|
// 258 < n < 258+3 |
|
b.repeat1(10, d) |
|
b.repeat1(n-10, d) |
|
return |
|
} |
|
if n < 3 { |
|
panic("invalid flate repeat") |
|
} |
|
b.repeat1(n, d) |
|
} |
|
|
|
func (b *bitWriter) repeat1(n, d int) { |
|
/* |
|
Extra Extra Extra |
|
Code Bits Length(s) Code Bits Lengths Code Bits Length(s) |
|
---- ---- ------ ---- ---- ------- ---- ---- ------- |
|
257 0 3 267 1 15,16 277 4 67-82 |
|
258 0 4 268 1 17,18 278 4 83-98 |
|
259 0 5 269 2 19-22 279 4 99-114 |
|
260 0 6 270 2 23-26 280 4 115-130 |
|
261 0 7 271 2 27-30 281 5 131-162 |
|
262 0 8 272 2 31-34 282 5 163-194 |
|
263 0 9 273 3 35-42 283 5 195-226 |
|
264 0 10 274 3 43-50 284 5 227-257 |
|
265 1 11,12 275 3 51-58 285 0 258 |
|
266 1 13,14 276 3 59-66 |
|
*/ |
|
switch { |
|
case n <= 10: |
|
b.codex(257, n-3, 0) |
|
case n <= 18: |
|
b.codex(265, n-11, 1) |
|
case n <= 34: |
|
b.codex(269, n-19, 2) |
|
case n <= 66: |
|
b.codex(273, n-35, 3) |
|
case n <= 130: |
|
b.codex(277, n-67, 4) |
|
case n <= 257: |
|
b.codex(281, n-131, 5) |
|
case n == 258: |
|
b.hcode(285) |
|
default: |
|
panic("invalid repeat length") |
|
} |
|
|
|
/* |
|
Extra Extra Extra |
|
Code Bits Dist Code Bits Dist Code Bits Distance |
|
---- ---- ---- ---- ---- ------ ---- ---- -------- |
|
0 0 1 10 4 33-48 20 9 1025-1536 |
|
1 0 2 11 4 49-64 21 9 1537-2048 |
|
2 0 3 12 5 65-96 22 10 2049-3072 |
|
3 0 4 13 5 97-128 23 10 3073-4096 |
|
4 1 5,6 14 6 129-192 24 11 4097-6144 |
|
5 1 7,8 15 6 193-256 25 11 6145-8192 |
|
6 2 9-12 16 7 257-384 26 12 8193-12288 |
|
7 2 13-16 17 7 385-512 27 12 12289-16384 |
|
8 3 17-24 18 8 513-768 28 13 16385-24576 |
|
9 3 25-32 19 8 769-1024 29 13 24577-32768 |
|
*/ |
|
if d <= 4 { |
|
b.writeBits(uint32(d-1), 5, true) |
|
} else if d <= 32768 { |
|
nbit := uint(16) |
|
for d <= 1<<(nbit-1) { |
|
nbit-- |
|
} |
|
v := uint32(d - 1) |
|
v &^= 1 << (nbit - 1) // top bit is implicit |
|
code := uint32(2*nbit - 2) // second bit is low bit of code |
|
code |= v >> (nbit - 2) |
|
v &^= 1 << (nbit - 2) |
|
b.writeBits(code, 5, true) |
|
// rest of bits follow |
|
b.writeBits(uint32(v), nbit-2, false) |
|
} else { |
|
panic("invalid repeat distance") |
|
} |
|
} |
|
|
|
func (b *bitWriter) run(v byte, n int) { |
|
if n == 0 { |
|
return |
|
} |
|
b.byte(v) |
|
if n-1 < 3 { |
|
for i := 0; i < n-1; i++ { |
|
b.byte(v) |
|
} |
|
} else { |
|
b.repeat(n-1, 1) |
|
} |
|
} |
|
|
|
type adigest struct { |
|
a, b uint32 |
|
} |
|
|
|
func (d *adigest) Reset() { d.a, d.b = 1, 0 } |
|
|
|
const amod = 65521 |
|
|
|
func aupdate(a, b uint32, pi byte, n int) (aa, bb uint32) { |
|
// TODO(rsc): 6g doesn't do magic multiplies for b %= amod, |
|
// only for b = b%amod. |
|
|
|
// invariant: a, b < amod |
|
if pi == 0 { |
|
b += uint32(n%amod) * a |
|
b = b % amod |
|
return a, b |
|
} |
|
|
|
// n times: |
|
// a += pi |
|
// b += a |
|
// is same as |
|
// b += n*a + n*(n+1)/2*pi |
|
// a += n*pi |
|
m := uint32(n) |
|
b += (m % amod) * a |
|
b = b % amod |
|
b += (m * (m + 1) / 2) % amod * uint32(pi) |
|
b = b % amod |
|
a += (m % amod) * uint32(pi) |
|
a = a % amod |
|
return a, b |
|
} |
|
|
|
func afinish(a, b uint32) uint32 { |
|
return b<<16 | a |
|
} |
|
|
|
func (d *adigest) WriteN(p []byte, n int) { |
|
for i := 0; i < n; i++ { |
|
for _, pi := range p { |
|
d.a, d.b = aupdate(d.a, d.b, pi, 1) |
|
} |
|
} |
|
} |
|
|
|
func (d *adigest) WriteNByte(pi byte, n int) { |
|
d.a, d.b = aupdate(d.a, d.b, pi, n) |
|
} |
|
|
|
func (d *adigest) Sum32() uint32 { return afinish(d.a, d.b) }
|
|
|