encoder.go 17 KB

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