qrcode.go 15 KB

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