// 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.bsd 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<= 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) }