qrcode.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586
  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. // Output image.
  219. rect := image.Rectangle{Min: image.Point{0, 0}, Max: image.Point{size, size}}
  220. // Saves a few bytes to have them in this order
  221. p := color.Palette([]color.Color{q.BackgroundColor, q.ForegroundColor})
  222. img := image.NewPaletted(rect, p)
  223. fgClr := uint8(img.Palette.Index(q.ForegroundColor))
  224. // QR code bitmap.
  225. bitmap := q.symbol.bitmap()
  226. // Map each image pixel to the nearest QR code module.
  227. modulesPerPixel := float64(realSize) / float64(size)
  228. for y := 0; y < size; y++ {
  229. for x := 0; x < size; x++ {
  230. y2 := int(float64(y) * modulesPerPixel)
  231. x2 := int(float64(x) * modulesPerPixel)
  232. v := bitmap[y2][x2]
  233. if v {
  234. pos := img.PixOffset(x, y)
  235. img.Pix[pos] = fgClr
  236. }
  237. }
  238. }
  239. return img
  240. }
  241. // PNG returns the QR Code as a PNG image.
  242. //
  243. // size is both the image width and height in pixels. If size is too small then
  244. // a larger image is silently returned. Negative values for size cause a
  245. // variable sized image to be returned: See the documentation for Image().
  246. func (q *QRCode) PNG(size int) ([]byte, error) {
  247. img := q.Image(size)
  248. encoder := png.Encoder{CompressionLevel: png.BestCompression}
  249. var b bytes.Buffer
  250. err := encoder.Encode(&b, img)
  251. if err != nil {
  252. return nil, err
  253. }
  254. return b.Bytes(), nil
  255. }
  256. // Write writes the QR Code as a PNG image to io.Writer.
  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) Write(size int, out io.Writer) error {
  262. var png []byte
  263. png, err := q.PNG(size)
  264. if err != nil {
  265. return err
  266. }
  267. _, err = out.Write(png)
  268. return err
  269. }
  270. // WriteFile writes the QR Code as a PNG image to the specified file.
  271. //
  272. // size is both the image width and height in pixels. If size is too small then
  273. // a larger image is silently written. Negative values for size cause a
  274. // variable sized image to be written: See the documentation for Image().
  275. func (q *QRCode) WriteFile(size int, filename string) error {
  276. var png []byte
  277. png, err := q.PNG(size)
  278. if err != nil {
  279. return err
  280. }
  281. return ioutil.WriteFile(filename, png, os.FileMode(0644))
  282. }
  283. // encode completes the steps required to encode the QR Code. These include
  284. // adding the terminator bits and padding, splitting the data into blocks and
  285. // applying the error correction, and selecting the best data mask.
  286. func (q *QRCode) encode(numTerminatorBits int) {
  287. q.addTerminatorBits(numTerminatorBits)
  288. q.addPadding()
  289. encoded := q.encodeBlocks()
  290. const numMasks int = 8
  291. penalty := 0
  292. for mask := 0; mask < numMasks; mask++ {
  293. var s *symbol
  294. var err error
  295. s, err = buildRegularSymbol(q.version, mask, encoded)
  296. if err != nil {
  297. log.Panic(err.Error())
  298. }
  299. numEmptyModules := s.numEmptyModules()
  300. if numEmptyModules != 0 {
  301. log.Panicf("bug: numEmptyModules is %d (expected 0) (version=%d)",
  302. numEmptyModules, q.VersionNumber)
  303. }
  304. p := s.penaltyScore()
  305. //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())
  306. if q.symbol == nil || p < penalty {
  307. q.symbol = s
  308. q.mask = mask
  309. penalty = p
  310. }
  311. }
  312. }
  313. // addTerminatorBits adds final terminator bits to the encoded data.
  314. //
  315. // The number of terminator bits required is determined when the QR Code version
  316. // is chosen (which itself depends on the length of the data encoded). The
  317. // terminator bits are thus added after the QR Code version
  318. // is chosen, rather than at the data encoding stage.
  319. func (q *QRCode) addTerminatorBits(numTerminatorBits int) {
  320. q.data.AppendNumBools(numTerminatorBits, false)
  321. }
  322. // encodeBlocks takes the completed (terminated & padded) encoded data, splits
  323. // the data into blocks (as specified by the QR Code version), applies error
  324. // correction to each block, then interleaves the blocks together.
  325. //
  326. // The QR Code's final data sequence is returned.
  327. func (q *QRCode) encodeBlocks() *bitset.Bitset {
  328. // Split into blocks.
  329. type dataBlock struct {
  330. data *bitset.Bitset
  331. ecStartOffset int
  332. }
  333. block := make([]dataBlock, q.version.numBlocks())
  334. start := 0
  335. end := 0
  336. blockID := 0
  337. for _, b := range q.version.block {
  338. for j := 0; j < b.numBlocks; j++ {
  339. start = end
  340. end = start + b.numDataCodewords*8
  341. // Apply error correction to each block.
  342. numErrorCodewords := b.numCodewords - b.numDataCodewords
  343. block[blockID].data = reedsolomon.Encode(q.data.Substr(start, end), numErrorCodewords)
  344. block[blockID].ecStartOffset = end - start
  345. blockID++
  346. }
  347. }
  348. // Interleave the blocks.
  349. result := bitset.New()
  350. // Combine data blocks.
  351. working := true
  352. for i := 0; working; i += 8 {
  353. working = false
  354. for j, b := range block {
  355. if i >= block[j].ecStartOffset {
  356. continue
  357. }
  358. result.Append(b.data.Substr(i, i+8))
  359. working = true
  360. }
  361. }
  362. // Combine error correction blocks.
  363. working = true
  364. for i := 0; working; i += 8 {
  365. working = false
  366. for j, b := range block {
  367. offset := i + block[j].ecStartOffset
  368. if offset >= block[j].data.Len() {
  369. continue
  370. }
  371. result.Append(b.data.Substr(offset, offset+8))
  372. working = true
  373. }
  374. }
  375. // Append remainder bits.
  376. result.AppendNumBools(q.version.numRemainderBits, false)
  377. return result
  378. }
  379. // max returns the maximum of a and b.
  380. func max(a int, b int) int {
  381. if a > b {
  382. return a
  383. }
  384. return b
  385. }
  386. // addPadding pads the encoded data upto the full length required.
  387. func (q *QRCode) addPadding() {
  388. numDataBits := q.version.numDataBits()
  389. if q.data.Len() == numDataBits {
  390. return
  391. }
  392. // Pad to the nearest codeword boundary.
  393. q.data.AppendNumBools(q.version.numBitsToPadToCodeword(q.data.Len()), false)
  394. // Pad codewords 0b11101100 and 0b00010001.
  395. padding := [2]*bitset.Bitset{
  396. bitset.New(true, true, true, false, true, true, false, false),
  397. bitset.New(false, false, false, true, false, false, false, true),
  398. }
  399. // Insert pad codewords alternately.
  400. i := 0
  401. for numDataBits-q.data.Len() >= 8 {
  402. q.data.Append(padding[i])
  403. i = 1 - i // Alternate between 0 and 1.
  404. }
  405. if q.data.Len() != numDataBits {
  406. log.Panicf("BUG: got len %d, expected %d", q.data.Len(), numDataBits)
  407. }
  408. }
  409. // ToString produces a multi-line string that forms a QR-code image.
  410. func (q *QRCode) ToString(inverseColor bool) string {
  411. bits := q.Bitmap()
  412. var buf bytes.Buffer
  413. for y := range bits {
  414. for x := range bits[y] {
  415. if bits[y][x] != inverseColor {
  416. buf.WriteString(" ")
  417. } else {
  418. buf.WriteString("██")
  419. }
  420. }
  421. buf.WriteString("\n")
  422. }
  423. return buf.String()
  424. }
  425. // ToSmallString produces a multi-line string that forms a QR-code image, a
  426. // factor two smaller in x and y then ToString.
  427. func (q *QRCode) ToSmallString(inverseColor bool) string {
  428. bits := q.Bitmap()
  429. var buf bytes.Buffer
  430. // if there is an odd number of rows, the last one needs special treatment
  431. for y := 0; y < len(bits)-1; y += 2 {
  432. for x := range bits[y] {
  433. if bits[y][x] == bits[y+1][x] {
  434. if bits[y][x] != inverseColor {
  435. buf.WriteString(" ")
  436. } else {
  437. buf.WriteString("█")
  438. }
  439. } else {
  440. if bits[y][x] != inverseColor {
  441. buf.WriteString("▄")
  442. } else {
  443. buf.WriteString("▀")
  444. }
  445. }
  446. }
  447. buf.WriteString("\n")
  448. }
  449. // special treatment for the last row if odd
  450. if len(bits)%2 == 1 {
  451. y := len(bits) - 1
  452. for x := range bits[y] {
  453. if bits[y][x] != inverseColor {
  454. buf.WriteString(" ")
  455. } else {
  456. buf.WriteString("▀")
  457. }
  458. }
  459. buf.WriteString("\n")
  460. }
  461. return buf.String()
  462. }