utils.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. function hex2rgba (hex) {
  2. if (typeof hex === 'number') {
  3. hex = hex.toString()
  4. }
  5. if (typeof hex !== 'string') {
  6. throw new Error('Color should be defined as hex string')
  7. }
  8. let hexCode = hex.slice().replace('#', '').split('')
  9. if (hexCode.length < 3 || hexCode.length === 5 || hexCode.length > 8) {
  10. throw new Error('Invalid hex color: ' + hex)
  11. }
  12. // Convert from short to long form (fff -> ffffff)
  13. if (hexCode.length === 3 || hexCode.length === 4) {
  14. hexCode = Array.prototype.concat.apply([], hexCode.map(function (c) {
  15. return [c, c]
  16. }))
  17. }
  18. // Add default alpha value
  19. if (hexCode.length === 6) hexCode.push('F', 'F')
  20. const hexValue = parseInt(hexCode.join(''), 16)
  21. return {
  22. r: (hexValue >> 24) & 255,
  23. g: (hexValue >> 16) & 255,
  24. b: (hexValue >> 8) & 255,
  25. a: hexValue & 255,
  26. hex: '#' + hexCode.slice(0, 6).join('')
  27. }
  28. }
  29. exports.getOptions = function getOptions (options) {
  30. if (!options) options = {}
  31. if (!options.color) options.color = {}
  32. const margin = typeof options.margin === 'undefined' ||
  33. options.margin === null ||
  34. options.margin < 0
  35. ? 4
  36. : options.margin
  37. const width = options.width && options.width >= 21 ? options.width : undefined
  38. const scale = options.scale || 4
  39. return {
  40. width: width,
  41. scale: width ? 4 : scale,
  42. margin: margin,
  43. color: {
  44. dark: hex2rgba(options.color.dark || '#000000ff'),
  45. light: hex2rgba(options.color.light || '#ffffffff')
  46. },
  47. type: options.type,
  48. rendererOpts: options.rendererOpts || {}
  49. }
  50. }
  51. exports.getScale = function getScale (qrSize, opts) {
  52. return opts.width && opts.width >= qrSize + opts.margin * 2
  53. ? opts.width / (qrSize + opts.margin * 2)
  54. : opts.scale
  55. }
  56. exports.getImageWidth = function getImageWidth (qrSize, opts) {
  57. const scale = exports.getScale(qrSize, opts)
  58. return Math.floor((qrSize + opts.margin * 2) * scale)
  59. }
  60. exports.qrToImageData = function qrToImageData (imgData, qr, opts) {
  61. const size = qr.modules.size
  62. const data = qr.modules.data
  63. const scale = exports.getScale(size, opts)
  64. const symbolSize = Math.floor((size + opts.margin * 2) * scale)
  65. const scaledMargin = opts.margin * scale
  66. const palette = [opts.color.light, opts.color.dark]
  67. for (let i = 0; i < symbolSize; i++) {
  68. for (let j = 0; j < symbolSize; j++) {
  69. let posDst = (i * symbolSize + j) * 4
  70. let pxColor = opts.color.light
  71. if (i >= scaledMargin && j >= scaledMargin &&
  72. i < symbolSize - scaledMargin && j < symbolSize - scaledMargin) {
  73. const iSrc = Math.floor((i - scaledMargin) / scale)
  74. const jSrc = Math.floor((j - scaledMargin) / scale)
  75. pxColor = palette[data[iSrc * size + jSrc] ? 1 : 0]
  76. }
  77. imgData[posDst++] = pxColor.r
  78. imgData[posDst++] = pxColor.g
  79. imgData[posDst++] = pxColor.b
  80. imgData[posDst] = pxColor.a
  81. }
  82. }
  83. }