qrcode.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476
  1. // go-qrcode
  2. // Copyright 2014 Tom Harwood
  3. /*
  4. Package qrcode implements a QR Code encoder.
  5. A QR Code is a matrix (two-dimensional) barcode. Arbitrary content may be
  6. encoded.
  7. A QR Code contains error recovery information to aid reading damaged or
  8. obscured codes. There are four levels of error recovery: qrcode.{Low, Medium,
  9. High, Highest}. QR Codes with a higher recovery level are more robust to damage,
  10. at the cost of being physically larger.
  11. Two functions cover most use cases:
  12. - Create a PNG image:
  13. var png []byte
  14. png, err := qrcode.Encode("https://example.org", qrcode.Medium, 256)
  15. - Create a PNG image and write to a file:
  16. err := qrcode.WriteFile("https://example.org", qrcode.Medium, 256, "qr.png")
  17. Both examples use the qrcode.Medium error Recovery Level and create a 256x256
  18. pixel, black on white QR Code.
  19. The maximum capacity of a QR Code varies according to the content encoded and
  20. the error recovery level. The maximum capacity is 2,953 bytes, 4,296
  21. alphanumeric characters, 7,089 numeric digits, or a combination of these.
  22. This package implements a subset of QR Code 2005, as defined in ISO/IEC
  23. 18004:2006.
  24. */
  25. package qrcode
  26. import (
  27. "bytes"
  28. "errors"
  29. "image"
  30. "image/color"
  31. "image/png"
  32. "io"
  33. "io/ioutil"
  34. "log"
  35. "os"
  36. bitset "github.com/skip2/go-qrcode/bitset"
  37. reedsolomon "github.com/skip2/go-qrcode/reedsolomon"
  38. )
  39. // Encode a QR Code and return a raw PNG image.
  40. //
  41. // size is both the image width and height in pixels. If size is too small then
  42. // a larger image is silently returned.
  43. //
  44. // To serve over HTTP, remember to send a Content-Type: image/png header.
  45. func Encode(content string, level RecoveryLevel, size int) ([]byte, error) {
  46. var q *QRCode
  47. q, err := New(content, level)
  48. if err != nil {
  49. return nil, err
  50. }
  51. return q.PNG(size)
  52. }
  53. // WriteFile encodes, then writes a QR Code to the given filename in PNG format.
  54. //
  55. // size is both the width and height in pixels. If size is too small then a
  56. // larger image is silently written.
  57. func WriteFile(content string, level RecoveryLevel, size int, filename string) error {
  58. var q *QRCode
  59. q, err := New(content, level)
  60. if err != nil {
  61. return err
  62. }
  63. return q.WriteFile(size, filename)
  64. }
  65. // A QRCode represents a valid encoded QRCode.
  66. type QRCode struct {
  67. // Original content encoded.
  68. Content string
  69. // QR Code type.
  70. Level RecoveryLevel
  71. VersionNumber int
  72. // User settable drawing options.
  73. ForegroundColor color.Color
  74. BackgroundColor color.Color
  75. encoder *dataEncoder
  76. version qrCodeVersion
  77. data *bitset.Bitset
  78. symbol *symbol
  79. mask int
  80. }
  81. // New constructs a QRCode.
  82. //
  83. // var q *qrcode.QRCode
  84. // q, err := qrcode.New("my content", qrcode.Medium)
  85. //
  86. // An error occurs if the content is too long.
  87. func New(content string, level RecoveryLevel) (*QRCode, error) {
  88. encoders := []dataEncoderType{dataEncoderType1To9, dataEncoderType10To26,
  89. dataEncoderType27To40}
  90. var encoder *dataEncoder
  91. var encoded *bitset.Bitset
  92. var chosenVersion *qrCodeVersion
  93. var err error
  94. for _, t := range encoders {
  95. encoder = newDataEncoder(t)
  96. encoded, err = encoder.encode([]byte(content))
  97. if err != nil {
  98. continue
  99. }
  100. chosenVersion = chooseQRCodeVersion(level, encoder, encoded.Len())
  101. if chosenVersion != nil {
  102. break
  103. }
  104. }
  105. if err != nil {
  106. return nil, err
  107. } else if chosenVersion == nil {
  108. return nil, errors.New("content too long to encode")
  109. }
  110. q := &QRCode{
  111. Content: content,
  112. Level: level,
  113. VersionNumber: chosenVersion.version,
  114. ForegroundColor: color.Black,
  115. BackgroundColor: color.White,
  116. encoder: encoder,
  117. data: encoded,
  118. version: *chosenVersion,
  119. }
  120. q.encode(chosenVersion.numTerminatorBitsRequired(encoded.Len()))
  121. return q, nil
  122. }
  123. func newWithForcedVersion(content string, version int, level RecoveryLevel) (*QRCode, error) {
  124. var encoder *dataEncoder
  125. switch {
  126. case version >= 1 && version <= 9:
  127. encoder = newDataEncoder(dataEncoderType1To9)
  128. case version >= 10 && version <= 26:
  129. encoder = newDataEncoder(dataEncoderType10To26)
  130. case version >= 27 && version <= 40:
  131. encoder = newDataEncoder(dataEncoderType27To40)
  132. default:
  133. log.Fatalf("Invalid version %d (expected 1-40 inclusive)", version)
  134. }
  135. var encoded *bitset.Bitset
  136. encoded, err := encoder.encode([]byte(content))
  137. if err != nil {
  138. return nil, err
  139. }
  140. chosenVersion := getQRCodeVersion(level, version)
  141. if chosenVersion == nil {
  142. return nil, errors.New("cannot find QR Code version")
  143. }
  144. q := &QRCode{
  145. Content: content,
  146. Level: level,
  147. VersionNumber: chosenVersion.version,
  148. ForegroundColor: color.Black,
  149. BackgroundColor: color.White,
  150. encoder: encoder,
  151. data: encoded,
  152. version: *chosenVersion,
  153. }
  154. q.encode(chosenVersion.numTerminatorBitsRequired(encoded.Len()))
  155. return q, nil
  156. }
  157. // Bitmap returns the QR Code as a 2D array of 1-bit pixels.
  158. //
  159. // bitmap[y][x] is true if the pixel at (x, y) is set.
  160. //
  161. // The bitmap includes the required "quiet zone" around the QR Code to aid
  162. // decoding.
  163. func (q *QRCode) Bitmap() [][]bool {
  164. return q.symbol.bitmap()
  165. }
  166. // Image returns the QR Code as an image.Image.
  167. //
  168. // size is both the width and height in pixels.
  169. func (q *QRCode) Image(size int) image.Image {
  170. // Minimum pixels (both width and height) required.
  171. realSize := q.symbol.size
  172. // Actual pixels available to draw the symbol. Automatically increase the
  173. // image size if it's not large enough.
  174. if size < realSize {
  175. size = realSize
  176. }
  177. // Size of each module drawn.
  178. pixelsPerModule := size / realSize
  179. // Center the symbol within the image.
  180. offset := (size - realSize*pixelsPerModule) / 2
  181. rect := image.Rectangle{Min: image.Point{0, 0}, Max: image.Point{size, size}}
  182. img := image.NewRGBA(rect)
  183. for i := 0; i < size; i++ {
  184. for j := 0; j < size; j++ {
  185. img.Set(i, j, q.BackgroundColor)
  186. }
  187. }
  188. bitmap := q.symbol.bitmap()
  189. for y, row := range bitmap {
  190. for x, v := range row {
  191. if v {
  192. startX := x*pixelsPerModule + offset
  193. startY := y*pixelsPerModule + offset
  194. for i := startX; i < startX+pixelsPerModule; i++ {
  195. for j := startY; j < startY+pixelsPerModule; j++ {
  196. img.Set(i, j, q.ForegroundColor)
  197. }
  198. }
  199. }
  200. }
  201. }
  202. return img
  203. }
  204. // PNG returns the QR Code as a PNG image.
  205. //
  206. // size is both the image width and height in pixels. If size is too small then
  207. // a larger image is silently returned.
  208. func (q *QRCode) PNG(size int) ([]byte, error) {
  209. img := q.Image(size)
  210. var b bytes.Buffer
  211. err := png.Encode(&b, img)
  212. if err != nil {
  213. return nil, err
  214. }
  215. return b.Bytes(), nil
  216. }
  217. // Write writes the QR Code as a PNG image to io.Writer.
  218. //
  219. // size is both the image width and height in pixels. If size is too small then
  220. // a larger image is silently written.
  221. func (q *QRCode) Write(size int, out io.Writer) error {
  222. var png []byte
  223. png, err := q.PNG(size)
  224. if err != nil {
  225. return err
  226. }
  227. _, err = out.Write(png)
  228. return err
  229. }
  230. // WriteFile writes the QR Code as a PNG image to the specified file.
  231. //
  232. // size is both the image width and height in pixels. If size is too small then
  233. // a larger image is silently written.
  234. func (q *QRCode) WriteFile(size int, filename string) error {
  235. var png []byte
  236. png, err := q.PNG(size)
  237. if err != nil {
  238. return err
  239. }
  240. return ioutil.WriteFile(filename, png, os.FileMode(0644))
  241. }
  242. // encode completes the steps required to encode the QR Code. These include
  243. // adding the terminator bits and padding, splitting the data into blocks and
  244. // applying the error correction, and selecting the best data mask.
  245. func (q *QRCode) encode(numTerminatorBits int) {
  246. q.addTerminatorBits(numTerminatorBits)
  247. q.addPadding()
  248. encoded := q.encodeBlocks()
  249. const numMasks int = 8
  250. penalty := 0
  251. for mask := 0; mask < numMasks; mask++ {
  252. var s *symbol
  253. var err error
  254. s, err = buildRegularSymbol(q.version, mask, encoded)
  255. if err != nil {
  256. log.Panic(err.Error())
  257. }
  258. numEmptyModules := s.numEmptyModules()
  259. if numEmptyModules != 0 {
  260. log.Panicf("bug: numEmptyModules is %d (expected 0) (version=%d)",
  261. numEmptyModules, q.VersionNumber)
  262. }
  263. p := s.penaltyScore()
  264. //log.Printf("mask=%d p=%3d p1=%3d p2=%3d p3=%3d p4=%d\n", mask, p, s.penalty1(), s.penalty2(), s.penalty3(), s.penalty4())
  265. if q.symbol == nil || p < penalty {
  266. q.symbol = s
  267. q.mask = mask
  268. penalty = p
  269. }
  270. }
  271. }
  272. // addTerminatorBits adds final terminator bits to the encoded data.
  273. //
  274. // The number of terminator bits required is determined when the QR Code version
  275. // is chosen (which itself depends on the length of the data encoded). The
  276. // terminator bits are thus added after the QR Code version
  277. // is chosen, rather than at the data encoding stage.
  278. func (q *QRCode) addTerminatorBits(numTerminatorBits int) {
  279. q.data.AppendNumBools(numTerminatorBits, false)
  280. }
  281. // encodeBlocks takes the completed (terminated & padded) encoded data, splits
  282. // the data into blocks (as specified by the QR Code version), applies error
  283. // correction to each block, then interleaves the blocks together.
  284. //
  285. // The QR Code's final data sequence is returned.
  286. func (q *QRCode) encodeBlocks() *bitset.Bitset {
  287. // Split into blocks.
  288. type dataBlock struct {
  289. data *bitset.Bitset
  290. ecStartOffset int
  291. }
  292. block := make([]dataBlock, q.version.numBlocks())
  293. start := 0
  294. end := 0
  295. blockID := 0
  296. for _, b := range q.version.block {
  297. for j := 0; j < b.numBlocks; j++ {
  298. start = end
  299. end = start + b.numDataCodewords*8
  300. // Apply error correction to each block.
  301. numErrorCodewords := b.numCodewords - b.numDataCodewords
  302. block[blockID].data = reedsolomon.Encode(q.data.Substr(start, end), numErrorCodewords)
  303. block[blockID].ecStartOffset = end - start
  304. blockID++
  305. }
  306. }
  307. // Interleave the blocks.
  308. result := bitset.New()
  309. // Combine data blocks.
  310. working := true
  311. for i := 0; working; i += 8 {
  312. working = false
  313. for j, b := range block {
  314. if i >= block[j].ecStartOffset {
  315. continue
  316. }
  317. result.Append(b.data.Substr(i, i+8))
  318. working = true
  319. }
  320. }
  321. // Combine error correction blocks.
  322. working = true
  323. for i := 0; working; i += 8 {
  324. working = false
  325. for j, b := range block {
  326. offset := i + block[j].ecStartOffset
  327. if offset >= block[j].data.Len() {
  328. continue
  329. }
  330. result.Append(b.data.Substr(offset, offset+8))
  331. working = true
  332. }
  333. }
  334. // Append remainder bits.
  335. result.AppendNumBools(q.version.numRemainderBits, false)
  336. return result
  337. }
  338. // max returns the maximum of a and b.
  339. func max(a int, b int) int {
  340. if a > b {
  341. return a
  342. }
  343. return b
  344. }
  345. // addPadding pads the encoded data upto the full length required.
  346. func (q *QRCode) addPadding() {
  347. numDataBits := q.version.numDataBits()
  348. if q.data.Len() == numDataBits {
  349. return
  350. }
  351. // Pad to the nearest codeword boundary.
  352. q.data.AppendNumBools(q.version.numBitsToPadToCodeword(q.data.Len()), false)
  353. // Pad codewords 0b11101100 and 0b00010001.
  354. padding := [2]*bitset.Bitset{
  355. bitset.New(true, true, true, false, true, true, false, false),
  356. bitset.New(false, false, false, true, false, false, false, true),
  357. }
  358. // Insert pad codewords alternately.
  359. i := 0
  360. for numDataBits-q.data.Len() >= 8 {
  361. q.data.Append(padding[i])
  362. i = 1 - i // Alternate between 0 and 1.
  363. }
  364. if q.data.Len() != numDataBits {
  365. log.Panicf("BUG: got len %d, expected %d", q.data.Len(), numDataBits)
  366. }
  367. }