qrcode.go 13 KB

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