File size: 2,132 Bytes
9de7b70
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// 二维码生成、功能区识别与摆放
const QRCodeCore = require('./qrcore/qrcode')
const AlignmentPattern = require('./qrcore/alignment-pattern')

const SAMPLE_TEXT = '豆维·可扫码的拼豆'

// 功能区(定位/时序/对齐/格式/版本)直接决定能否扫出,配色时强制高对比
function buildFunctionMask(size, version) {
  const mask = new Uint8Array(size * size)
  const mark = (x, y) => { if (x >= 0 && y >= 0 && x < size && y < size) mask[y * size + x] = 1 }
  for (let y = 0; y < size; y += 1) {
    for (let x = 0; x < size; x += 1) {
      const finder = (x <= 8 && y <= 8) || (x >= size - 8 && y <= 8) || (x <= 8 && y >= size - 8)
      if (finder || x === 6 || y === 6) mark(x, y)
    }
  }
  const positions = AlignmentPattern.getPositions(version) || []
  positions.forEach(([row, col]) => {
    for (let dy = -2; dy <= 2; dy += 1) for (let dx = -2; dx <= 2; dx += 1) mark(col + dx, row + dy)
  })
  if (version >= 7) {
    for (let i = 0; i < 6; i += 1) {
      for (let j = size - 11; j < size - 8; j += 1) { mark(i, j); mark(j, i) }
    }
  }
  return mask
}

function makeQr(text, level) {
  const value = String(text || '').trim() || SAMPLE_TEXT
  const qr = QRCodeCore.create(value, { errorCorrectionLevel: level || 'H' })
  const size = qr.modules.size
  const version = qr.version || Math.round((size - 17) / 4)
  return {
    size,
    version,
    level: level || 'H',
    dark: Uint8Array.from(qr.modules.data),
    func: buildFunctionMask(size, version),
    isSample: !String(text || '').trim(),
  }
}

// scale:二维码占整张作品边长的百分比;quiet:二维码四周留白格数
function createPlacement(qrSize, { scale = 100, posX = 50, posY = 50, quiet = 0, hasImage = true } = {}) {
  const block = qrSize + quiet * 2
  const size = hasImage ? Math.max(block, Math.ceil(block * 100 / scale)) : block
  const free = size - block
  return {
    size,
    left: quiet + Math.round(free * posX / 100),
    top: quiet + Math.round(free * posY / 100),
    quiet,
    scale: hasImage ? scale : 100,
  }
}

module.exports = { SAMPLE_TEXT, makeQr, createPlacement }