qrcode.go 15 KB

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