encoder.go 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. // package for QR barcode generation.
  2. package qr
  3. import (
  4. "fmt"
  5. "github.com/boombuler/barcode"
  6. "image"
  7. )
  8. type encodeFn func(content string, eccLevel ErrorCorrectionLevel) (*barcode.BitList, *versionInfo, error)
  9. type Encoding byte
  10. const (
  11. // Choose best matching encoding
  12. Auto Encoding = iota
  13. // Encode only numbers [0-9]
  14. Numeric
  15. // Encode only uppercase letters, numbers and [Space], $, %, *, +, -, ., /, :
  16. AlphaNumeric
  17. )
  18. func (e Encoding) getEncoder() encodeFn {
  19. switch e {
  20. case Auto:
  21. return encodeAuto
  22. case Numeric:
  23. return encodeNumeric
  24. case AlphaNumeric:
  25. return encodeAlphaNumeric
  26. }
  27. return nil
  28. }
  29. func (e Encoding) String() string {
  30. switch e {
  31. case Auto:
  32. return "Auto"
  33. case Numeric:
  34. return "Numeric"
  35. case AlphaNumeric:
  36. return "AlphaNumeric"
  37. }
  38. return ""
  39. }
  40. // Encodes the given content to a QR barcode
  41. func Encode(content string, level ErrorCorrectionLevel, mode Encoding) (barcode.Barcode, error) {
  42. bits, vi, err := mode.getEncoder()(content, level)
  43. if err != nil {
  44. return nil, err
  45. }
  46. if bits == nil || vi == nil {
  47. return nil, fmt.Errorf("Unable to encode \"%s\" with error correction level %s and encoding mode %s", content, level, mode)
  48. }
  49. blocks := splitToBlocks(bits.ItterateBytes(), vi)
  50. data := blocks.interleave(vi)
  51. result := render(data, vi)
  52. result.content = content
  53. return result, nil
  54. }
  55. func render(data []byte, vi *versionInfo) *qrcode {
  56. dim := vi.modulWidth()
  57. results := make([]*qrcode, 8)
  58. for i := 0; i < 8; i++ {
  59. results[i] = newBarcode(dim)
  60. }
  61. occupied := newBarcode(dim)
  62. setAll := func(x int, y int, val bool) {
  63. occupied.Set(x, y, true)
  64. for i := 0; i < 8; i++ {
  65. results[i].Set(x, y, val)
  66. }
  67. }
  68. drawFinderPatterns(vi, setAll)
  69. drawAlignmentPatterns(occupied, vi, setAll)
  70. //Timing Pattern:
  71. var i int
  72. for i = 0; i < dim; i++ {
  73. if !occupied.Get(i, 6) {
  74. setAll(i, 6, i%2 == 0)
  75. }
  76. if !occupied.Get(6, i) {
  77. setAll(6, i, i%2 == 0)
  78. }
  79. }
  80. // Dark Module
  81. setAll(8, dim-8, true)
  82. drawVersionInfo(vi, setAll)
  83. drawFormatInfo(vi, -1, occupied.Set)
  84. for i := 0; i < 8; i++ {
  85. drawFormatInfo(vi, i, results[i].Set)
  86. }
  87. // Write the data
  88. var curBitNo int = 0
  89. for pos := range itterateModules(occupied) {
  90. if curBitNo < len(data)*8 {
  91. curBit := ((data[curBitNo/8] >> uint(7-(curBitNo%8))) & 1) == 1
  92. for i := 0; i < 8; i++ {
  93. setMasked(pos.X, pos.Y, curBit, i, results[i].Set)
  94. }
  95. curBitNo += 1
  96. }
  97. }
  98. lowestPenalty := ^uint(0)
  99. lowestPenaltyIdx := -1
  100. for i := 0; i < 8; i++ {
  101. p := results[i].calcPenalty()
  102. if p < lowestPenalty {
  103. lowestPenalty = p
  104. lowestPenaltyIdx = i
  105. }
  106. }
  107. return results[lowestPenaltyIdx]
  108. }
  109. func setMasked(x, y int, val bool, mask int, set func(int, int, bool)) {
  110. switch mask {
  111. case 0:
  112. val = val != (((y + x) % 2) == 0)
  113. break
  114. case 1:
  115. val = val != ((y % 2) == 0)
  116. break
  117. case 2:
  118. val = val != ((x % 3) == 0)
  119. break
  120. case 3:
  121. val = val != (((y + x) % 3) == 0)
  122. break
  123. case 4:
  124. val = val != (((y/2 + x/3) % 2) == 0)
  125. break
  126. case 5:
  127. val = val != (((y*x)%2)+((y*x)%3) == 0)
  128. break
  129. case 6:
  130. val = val != ((((y*x)%2)+((y*x)%3))%2 == 0)
  131. break
  132. case 7:
  133. val = val != ((((y+x)%2)+((y*x)%3))%2 == 0)
  134. }
  135. set(x, y, val)
  136. }
  137. func itterateModules(occupied *qrcode) <-chan image.Point {
  138. result := make(chan image.Point)
  139. allPoints := make(chan image.Point)
  140. go func() {
  141. curX := occupied.dimension - 1
  142. curY := occupied.dimension - 1
  143. isUpward := true
  144. for true {
  145. if isUpward {
  146. allPoints <- image.Pt(curX, curY)
  147. allPoints <- image.Pt(curX-1, curY)
  148. curY -= 1
  149. if curY < 0 {
  150. curY = 0
  151. curX -= 2
  152. if curX == 6 {
  153. curX -= 1
  154. }
  155. if curX < 0 {
  156. break
  157. }
  158. isUpward = false
  159. }
  160. } else {
  161. allPoints <- image.Pt(curX, curY)
  162. allPoints <- image.Pt(curX-1, curY)
  163. curY += 1
  164. if curY >= occupied.dimension {
  165. curY = occupied.dimension - 1
  166. curX -= 2
  167. if curX == 6 {
  168. curX -= 1
  169. }
  170. isUpward = true
  171. if curX < 0 {
  172. break
  173. }
  174. }
  175. }
  176. }
  177. close(allPoints)
  178. }()
  179. go func() {
  180. for pt := range allPoints {
  181. if !occupied.Get(pt.X, pt.Y) {
  182. result <- pt
  183. }
  184. }
  185. close(result)
  186. }()
  187. return result
  188. }
  189. func drawFinderPatterns(vi *versionInfo, set func(int, int, bool)) {
  190. dim := vi.modulWidth()
  191. drawPattern := func(xoff int, yoff int) {
  192. for x := -1; x < 8; x++ {
  193. for y := -1; y < 8; y++ {
  194. val := (x == 0 || x == 6 || y == 0 || y == 6 || (x > 1 && x < 5 && y > 1 && y < 5)) && (x <= 6 && y <= 6 && x >= 0 && y >= 0)
  195. if x+xoff >= 0 && x+xoff < dim && y+yoff >= 0 && y+yoff < dim {
  196. set(x+xoff, y+yoff, val)
  197. }
  198. }
  199. }
  200. }
  201. drawPattern(0, 0)
  202. drawPattern(0, dim-7)
  203. drawPattern(dim-7, 0)
  204. }
  205. func drawAlignmentPatterns(occupied *qrcode, vi *versionInfo, set func(int, int, bool)) {
  206. drawPattern := func(xoff int, yoff int) {
  207. for x := -2; x <= 2; x++ {
  208. for y := -2; y <= 2; y++ {
  209. val := x == -2 || x == 2 || y == -2 || y == 2 || (x == 0 && y == 0)
  210. set(x+xoff, y+yoff, val)
  211. }
  212. }
  213. }
  214. positions := vi.alignmentPatternPlacements()
  215. for _, x := range positions {
  216. for _, y := range positions {
  217. if occupied.Get(x, y) {
  218. continue
  219. }
  220. drawPattern(x, y)
  221. }
  222. }
  223. }
  224. func drawFormatInfo(vi *versionInfo, usedMask int, set func(int, int, bool)) {
  225. var formatInfo []bool
  226. switch vi.Level {
  227. case L:
  228. switch usedMask {
  229. case 0:
  230. formatInfo = []bool{true, true, true, false, true, true, true, true, true, false, false, false, true, false, false}
  231. break
  232. case 1:
  233. formatInfo = []bool{true, true, true, false, false, true, false, true, true, true, true, false, false, true, true}
  234. break
  235. case 2:
  236. formatInfo = []bool{true, true, true, true, true, false, true, true, false, true, false, true, false, true, false}
  237. break
  238. case 3:
  239. formatInfo = []bool{true, true, true, true, false, false, false, true, false, false, true, true, true, false, true}
  240. break
  241. case 4:
  242. formatInfo = []bool{true, true, false, false, true, true, false, false, false, true, false, true, true, true, true}
  243. break
  244. case 5:
  245. formatInfo = []bool{true, true, false, false, false, true, true, false, false, false, true, true, false, false, false}
  246. break
  247. case 6:
  248. formatInfo = []bool{true, true, false, true, true, false, false, false, true, false, false, false, false, false, true}
  249. break
  250. case 7:
  251. formatInfo = []bool{true, true, false, true, false, false, true, false, true, true, true, false, true, true, false}
  252. break
  253. }
  254. break
  255. case M:
  256. switch usedMask {
  257. case 0:
  258. formatInfo = []bool{true, false, true, false, true, false, false, false, false, false, true, false, false, true, false}
  259. break
  260. case 1:
  261. formatInfo = []bool{true, false, true, false, false, false, true, false, false, true, false, false, true, false, true}
  262. break
  263. case 2:
  264. formatInfo = []bool{true, false, true, true, true, true, false, false, true, true, true, true, true, false, false}
  265. break
  266. case 3:
  267. formatInfo = []bool{true, false, true, true, false, true, true, false, true, false, false, true, false, true, true}
  268. break
  269. case 4:
  270. formatInfo = []bool{true, false, false, false, true, false, true, true, true, true, true, true, false, false, true}
  271. break
  272. case 5:
  273. formatInfo = []bool{true, false, false, false, false, false, false, true, true, false, false, true, true, true, false}
  274. break
  275. case 6:
  276. formatInfo = []bool{true, false, false, true, true, true, true, true, false, false, true, false, true, true, true}
  277. break
  278. case 7:
  279. formatInfo = []bool{true, false, false, true, false, true, false, true, false, true, false, false, false, false, false}
  280. break
  281. }
  282. break
  283. case Q:
  284. switch usedMask {
  285. case 0:
  286. formatInfo = []bool{false, true, true, false, true, false, true, false, true, false, true, true, true, true, true}
  287. break
  288. case 1:
  289. formatInfo = []bool{false, true, true, false, false, false, false, false, true, true, false, true, false, false, false}
  290. break
  291. case 2:
  292. formatInfo = []bool{false, true, true, true, true, true, true, false, false, true, true, false, false, false, true}
  293. break
  294. case 3:
  295. formatInfo = []bool{false, true, true, true, false, true, false, false, false, false, false, false, true, true, false}
  296. break
  297. case 4:
  298. formatInfo = []bool{false, true, false, false, true, false, false, true, false, true, true, false, true, false, false}
  299. break
  300. case 5:
  301. formatInfo = []bool{false, true, false, false, false, false, true, true, false, false, false, false, false, true, true}
  302. break
  303. case 6:
  304. formatInfo = []bool{false, true, false, true, true, true, false, true, true, false, true, true, false, true, false}
  305. break
  306. case 7:
  307. formatInfo = []bool{false, true, false, true, false, true, true, true, true, true, false, true, true, false, true}
  308. break
  309. }
  310. break
  311. case H:
  312. switch usedMask {
  313. case 0:
  314. formatInfo = []bool{false, false, true, false, true, true, false, true, false, false, false, true, false, false, true}
  315. break
  316. case 1:
  317. formatInfo = []bool{false, false, true, false, false, true, true, true, false, true, true, true, true, true, false}
  318. break
  319. case 2:
  320. formatInfo = []bool{false, false, true, true, true, false, false, true, true, true, false, false, true, true, true}
  321. break
  322. case 3:
  323. formatInfo = []bool{false, false, true, true, false, false, true, true, true, false, true, false, false, false, false}
  324. break
  325. case 4:
  326. formatInfo = []bool{false, false, false, false, true, true, true, false, true, true, false, false, false, true, false}
  327. break
  328. case 5:
  329. formatInfo = []bool{false, false, false, false, false, true, false, false, true, false, true, false, true, false, true}
  330. break
  331. case 6:
  332. formatInfo = []bool{false, false, false, true, true, false, true, false, false, false, false, true, true, false, false}
  333. break
  334. case 7:
  335. formatInfo = []bool{false, false, false, true, false, false, false, false, false, true, true, true, false, true, true}
  336. break
  337. }
  338. break
  339. }
  340. if usedMask == -1 {
  341. formatInfo = []bool{true, true, true, true, true, true, true, true, true, true, true, true, true, true, true} // Set all to true cause -1 --> occupied mask.
  342. }
  343. if len(formatInfo) == 15 {
  344. dim := vi.modulWidth()
  345. set(0, 8, formatInfo[0])
  346. set(1, 8, formatInfo[1])
  347. set(2, 8, formatInfo[2])
  348. set(3, 8, formatInfo[3])
  349. set(4, 8, formatInfo[4])
  350. set(5, 8, formatInfo[5])
  351. set(7, 8, formatInfo[6])
  352. set(8, 8, formatInfo[7])
  353. set(8, 7, formatInfo[8])
  354. set(8, 5, formatInfo[9])
  355. set(8, 4, formatInfo[10])
  356. set(8, 3, formatInfo[11])
  357. set(8, 2, formatInfo[12])
  358. set(8, 1, formatInfo[13])
  359. set(8, 0, formatInfo[14])
  360. set(8, dim-1, formatInfo[0])
  361. set(8, dim-2, formatInfo[1])
  362. set(8, dim-3, formatInfo[2])
  363. set(8, dim-4, formatInfo[3])
  364. set(8, dim-5, formatInfo[4])
  365. set(8, dim-6, formatInfo[5])
  366. set(8, dim-7, formatInfo[6])
  367. set(dim-8, 8, formatInfo[7])
  368. set(dim-7, 8, formatInfo[8])
  369. set(dim-6, 8, formatInfo[9])
  370. set(dim-5, 8, formatInfo[10])
  371. set(dim-4, 8, formatInfo[11])
  372. set(dim-3, 8, formatInfo[12])
  373. set(dim-2, 8, formatInfo[13])
  374. set(dim-1, 8, formatInfo[14])
  375. }
  376. }
  377. func drawVersionInfo(vi *versionInfo, set func(int, int, bool)) {
  378. var versionInfoBits []bool
  379. switch vi.Version {
  380. case 7:
  381. versionInfoBits = []bool{false, false, false, true, true, true, true, true, false, false, true, false, false, true, false, true, false, false}
  382. break
  383. case 8:
  384. versionInfoBits = []bool{false, false, true, false, false, false, false, true, false, true, true, false, true, true, true, true, false, false}
  385. break
  386. case 9:
  387. versionInfoBits = []bool{false, false, true, false, false, true, true, false, true, false, true, false, false, true, true, false, false, true}
  388. break
  389. case 10:
  390. versionInfoBits = []bool{false, false, true, false, true, false, false, true, false, false, true, true, false, true, false, false, true, true}
  391. break
  392. case 11:
  393. versionInfoBits = []bool{false, false, true, false, true, true, true, false, true, true, true, true, true, true, false, true, true, false}
  394. break
  395. case 12:
  396. versionInfoBits = []bool{false, false, true, true, false, false, false, true, true, true, false, true, true, false, false, false, true, false}
  397. break
  398. case 13:
  399. versionInfoBits = []bool{false, false, true, true, false, true, true, false, false, false, false, true, false, false, false, true, true, true}
  400. break
  401. case 14:
  402. versionInfoBits = []bool{false, false, true, true, true, false, false, true, true, false, false, false, false, false, true, true, false, true}
  403. break
  404. case 15:
  405. versionInfoBits = []bool{false, false, true, true, true, true, true, false, false, true, false, false, true, false, true, false, false, false}
  406. break
  407. case 16:
  408. versionInfoBits = []bool{false, true, false, false, false, false, true, false, true, true, false, true, true, true, true, false, false, false}
  409. break
  410. case 17:
  411. versionInfoBits = []bool{false, true, false, false, false, true, false, true, false, false, false, true, false, true, true, true, false, true}
  412. break
  413. case 18:
  414. versionInfoBits = []bool{false, true, false, false, true, false, true, false, true, false, false, false, false, true, false, true, true, true}
  415. break
  416. case 19:
  417. versionInfoBits = []bool{false, true, false, false, true, true, false, true, false, true, false, false, true, true, false, false, true, false}
  418. break
  419. case 20:
  420. versionInfoBits = []bool{false, true, false, true, false, false, true, false, false, true, true, false, true, false, false, true, true, false}
  421. break
  422. case 21:
  423. versionInfoBits = []bool{false, true, false, true, false, true, false, true, true, false, true, false, false, false, false, false, true, true}
  424. break
  425. case 22:
  426. versionInfoBits = []bool{false, true, false, true, true, false, true, false, false, false, true, true, false, false, true, false, false, true}
  427. break
  428. case 23:
  429. versionInfoBits = []bool{false, true, false, true, true, true, false, true, true, true, true, true, true, false, true, true, false, false}
  430. break
  431. case 24:
  432. versionInfoBits = []bool{false, true, true, false, false, false, true, true, true, false, true, true, false, false, false, true, false, false}
  433. break
  434. case 25:
  435. versionInfoBits = []bool{false, true, true, false, false, true, false, false, false, true, true, true, true, false, false, false, false, true}
  436. break
  437. case 26:
  438. versionInfoBits = []bool{false, true, true, false, true, false, true, true, true, true, true, false, true, false, true, false, true, true}
  439. break
  440. case 27:
  441. versionInfoBits = []bool{false, true, true, false, true, true, false, false, false, false, true, false, false, false, true, true, true, false}
  442. break
  443. case 28:
  444. versionInfoBits = []bool{false, true, true, true, false, false, true, true, false, false, false, false, false, true, true, false, true, false}
  445. break
  446. case 29:
  447. versionInfoBits = []bool{false, true, true, true, false, true, false, false, true, true, false, false, true, true, true, true, true, true}
  448. break
  449. case 30:
  450. versionInfoBits = []bool{false, true, true, true, true, false, true, true, false, true, false, true, true, true, false, true, false, true}
  451. break
  452. case 31:
  453. versionInfoBits = []bool{false, true, true, true, true, true, false, false, true, false, false, true, false, true, false, false, false, false}
  454. break
  455. case 32:
  456. versionInfoBits = []bool{true, false, false, false, false, false, true, false, false, true, true, true, false, true, false, true, false, true}
  457. break
  458. case 33:
  459. versionInfoBits = []bool{true, false, false, false, false, true, false, true, true, false, true, true, true, true, false, false, false, false}
  460. break
  461. case 34:
  462. versionInfoBits = []bool{true, false, false, false, true, false, true, false, false, false, true, false, true, true, true, false, true, false}
  463. break
  464. case 35:
  465. versionInfoBits = []bool{true, false, false, false, true, true, false, true, true, true, true, false, false, true, true, true, true, true}
  466. break
  467. case 36:
  468. versionInfoBits = []bool{true, false, false, true, false, false, true, false, true, true, false, false, false, false, true, false, true, true}
  469. break
  470. case 37:
  471. versionInfoBits = []bool{true, false, false, true, false, true, false, true, false, false, false, false, true, false, true, true, true, false}
  472. break
  473. case 38:
  474. versionInfoBits = []bool{true, false, false, true, true, false, true, false, true, false, false, true, true, false, false, true, false, false}
  475. break
  476. case 39:
  477. versionInfoBits = []bool{true, false, false, true, true, true, false, true, false, true, false, true, false, false, false, false, false, true}
  478. break
  479. case 40:
  480. versionInfoBits = []bool{true, false, true, false, false, false, true, true, false, false, false, true, true, false, true, false, false, true}
  481. break
  482. }
  483. if len(versionInfoBits) > 0 {
  484. for i := 0; i < len(versionInfoBits); i++ {
  485. x := (vi.modulWidth() - 11) + i%3
  486. y := i / 3
  487. set(x, y, versionInfoBits[len(versionInfoBits)-i-1])
  488. set(y, x, versionInfoBits[len(versionInfoBits)-i-1])
  489. }
  490. }
  491. }
  492. func addPaddingAndTerminator(bl *barcode.BitList, vi *versionInfo) {
  493. for i := 0; i < 4 && bl.Len() < vi.totalDataBytes()*8; i++ {
  494. bl.AddBit(false)
  495. }
  496. for bl.Len()%8 != 0 {
  497. bl.AddBit(false)
  498. }
  499. for i := 0; bl.Len() < vi.totalDataBytes()*8; i++ {
  500. if i%2 == 0 {
  501. bl.AddByte(236)
  502. } else {
  503. bl.AddByte(17)
  504. }
  505. }
  506. }