@gongbaodd/qr-renderer 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +25 -0
- package/dist/node.js +3130 -0
- package/dist/types/core/artifacts.d.ts +2 -0
- package/dist/types/core/assemble.d.ts +36 -0
- package/dist/types/core/errors.d.ts +6 -0
- package/dist/types/core/export-sizes.d.ts +21 -0
- package/dist/types/core/image.d.ts +14 -0
- package/dist/types/core/imaging/browser.d.ts +23 -0
- package/dist/types/core/imaging/cloudflare.d.ts +2 -0
- package/dist/types/core/imaging/index.d.ts +5 -0
- package/dist/types/core/imaging/node.d.ts +4 -0
- package/dist/types/core/imaging/pixels.d.ts +28 -0
- package/dist/types/core/imaging/types.d.ts +45 -0
- package/dist/types/core/mask.d.ts +11 -0
- package/dist/types/core/module-cut.d.ts +107 -0
- package/dist/types/core/palette.d.ts +80 -0
- package/dist/types/core/pattern-cut.d.ts +96 -0
- package/dist/types/core/pattern.d.ts +119 -0
- package/dist/types/core/placement.d.ts +9 -0
- package/dist/types/core/qr.d.ts +57 -0
- package/dist/types/core/rotate.d.ts +149 -0
- package/dist/types/core/squircle.d.ts +2 -0
- package/dist/types/core/types.d.ts +475 -0
- package/dist/types/engine/engine.d.ts +68 -0
- package/dist/types/engine/index.d.ts +34 -0
- package/dist/types/engine/mapping.d.ts +14 -0
- package/dist/types/engine/pipeline.d.ts +77 -0
- package/dist/types/engine/types.d.ts +66 -0
- package/dist/types/node.d.ts +17 -0
- package/dist/types/png-guard.d.ts +17 -0
- package/dist/types/recipe.d.ts +132 -0
- package/dist/types/schema.d.ts +211 -0
- package/dist/types/worker-shim.d.ts +12 -0
- package/package.json +79 -0
- package/src/core/artifacts.ts +6 -0
- package/src/core/assemble.ts +1195 -0
- package/src/core/errors.ts +24 -0
- package/src/core/export-sizes.ts +179 -0
- package/src/core/image.ts +57 -0
- package/src/core/imaging/browser.ts +186 -0
- package/src/core/imaging/cloudflare.ts +15 -0
- package/src/core/imaging/index.ts +14 -0
- package/src/core/imaging/node.ts +95 -0
- package/src/core/imaging/pixels.ts +121 -0
- package/src/core/imaging/types.ts +56 -0
- package/src/core/mask.ts +295 -0
- package/src/core/module-cut.ts +523 -0
- package/src/core/palette.ts +227 -0
- package/src/core/pattern-cut.ts +522 -0
- package/src/core/pattern.ts +478 -0
- package/src/core/placement.ts +94 -0
- package/src/core/qr.ts +695 -0
- package/src/core/rotate.ts +267 -0
- package/src/core/squircle.ts +53 -0
- package/src/core/types.ts +477 -0
- package/src/engine/engine.ts +316 -0
- package/src/engine/index.ts +58 -0
- package/src/engine/mapping.ts +66 -0
- package/src/engine/pipeline.ts +501 -0
- package/src/engine/types.ts +61 -0
- package/src/node.ts +45 -0
- package/src/png-guard.ts +66 -0
- package/src/recipe.ts +161 -0
- package/src/schema.ts +137 -0
- package/src/wasm.d.ts +5 -0
- package/src/worker-shim.ts +15 -0
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
import type { LoadedPng } from './image'
|
|
2
|
+
import type { DecodedQr } from './qr'
|
|
3
|
+
|
|
4
|
+
export interface ImageDimensions {
|
|
5
|
+
width: number
|
|
6
|
+
height: number
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface BoundingBox {
|
|
10
|
+
x: number
|
|
11
|
+
y: number
|
|
12
|
+
width: number
|
|
13
|
+
height: number
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface Point {
|
|
17
|
+
x: number
|
|
18
|
+
y: number
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface RegionMask extends ImageDimensions {
|
|
22
|
+
/** Row-major binary coverage: 0 is outside, 255 is inside M. */
|
|
23
|
+
data: Uint8Array
|
|
24
|
+
source: 'auto' | 'file'
|
|
25
|
+
area: number
|
|
26
|
+
bounds: BoundingBox
|
|
27
|
+
centroid: Point
|
|
28
|
+
detection?: {
|
|
29
|
+
strongBlackThreshold: number
|
|
30
|
+
tolerantLumaThreshold: number
|
|
31
|
+
separationRadius: number
|
|
32
|
+
densityThreshold: number
|
|
33
|
+
candidateAreas: number[]
|
|
34
|
+
dominanceRatio: number | null
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export interface QrMetadata extends ImageDimensions {
|
|
39
|
+
decodedText: string
|
|
40
|
+
version: number
|
|
41
|
+
qrModules: number
|
|
42
|
+
quietZoneModules: 2
|
|
43
|
+
totalModules: number
|
|
44
|
+
sourceModulePixels: number
|
|
45
|
+
quietZoneLightRatio: number
|
|
46
|
+
/** `added` when the input was a bare code grid and the two-module margin was rebuilt locally. */
|
|
47
|
+
quietZoneSource?: 'added'
|
|
48
|
+
/** Trimmed-away margin of a code-grid input, in source pixels. */
|
|
49
|
+
sourceTrim?: QrSourceTrim
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface QrSourceTrim {
|
|
53
|
+
left: number
|
|
54
|
+
top: number
|
|
55
|
+
right: number
|
|
56
|
+
bottom: number
|
|
57
|
+
modulePixels: number
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface QrPlacement {
|
|
61
|
+
x: number
|
|
62
|
+
y: number
|
|
63
|
+
size: number
|
|
64
|
+
/** Clockwise degrees the finished plate is rotated around the square's centre; canonical [0, 360). */
|
|
65
|
+
rotation: number
|
|
66
|
+
modulePixels: number
|
|
67
|
+
totalModules: number
|
|
68
|
+
mode: 'auto' | 'manual'
|
|
69
|
+
/** Extra decorative modules reserved around the QR; retained for report compatibility. */
|
|
70
|
+
artPaddingModules: number
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface ResolvedLayout {
|
|
74
|
+
/** The poster exactly as supplied. */
|
|
75
|
+
poster: LoadedPng
|
|
76
|
+
/** The QR file exactly as supplied, kept for input reporting. */
|
|
77
|
+
qrSource: LoadedPng
|
|
78
|
+
/** The QR image placement uses: the input, or a code grid re-padded with a quiet zone. */
|
|
79
|
+
qrImage: LoadedPng
|
|
80
|
+
maskInput?: LoadedPng
|
|
81
|
+
regionMask: RegionMask
|
|
82
|
+
decoded: DecodedQr
|
|
83
|
+
qrMetadata: QrMetadata
|
|
84
|
+
placement: QrPlacement
|
|
85
|
+
normalizedQr: Uint8Array
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface VerificationCheck {
|
|
89
|
+
name:
|
|
90
|
+
| 'sourceQr'
|
|
91
|
+
| 'normalizedQr'
|
|
92
|
+
| 'beforeAi'
|
|
93
|
+
| 'halfScale'
|
|
94
|
+
| 'jpeg80'
|
|
95
|
+
| 'poster'
|
|
96
|
+
| 'posterHalfScale'
|
|
97
|
+
| 'posterJpeg80'
|
|
98
|
+
| 'outsideRegionPixels'
|
|
99
|
+
| 'qrPixels'
|
|
100
|
+
| 'qrPlateCorners'
|
|
101
|
+
| 'moduleCut'
|
|
102
|
+
| 'alphaPreserved'
|
|
103
|
+
| 'transparentBackground'
|
|
104
|
+
passed: boolean
|
|
105
|
+
decodedText?: string
|
|
106
|
+
decoder?: 'zxing' | 'jsqr'
|
|
107
|
+
version?: number
|
|
108
|
+
error?: string
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export interface VerificationResult {
|
|
112
|
+
expectedText: string
|
|
113
|
+
checks: VerificationCheck[]
|
|
114
|
+
qualified: boolean
|
|
115
|
+
/** Checks that a mode deliberately does not run, so a qualified report stays honest. */
|
|
116
|
+
skippedChecks?: VerificationCheck['name'][]
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export interface ReportV1 {
|
|
120
|
+
schemaVersion: 1
|
|
121
|
+
status: 'prepared' | 'verification_failed'
|
|
122
|
+
qualified: boolean
|
|
123
|
+
dryRun: true
|
|
124
|
+
createdAt: string
|
|
125
|
+
durationMs: number
|
|
126
|
+
inputs: {
|
|
127
|
+
poster: { path: string; sha256: string; width: number; height: number }
|
|
128
|
+
qr: { path: string; sha256: string; width: number; height: number }
|
|
129
|
+
mask?: { path: string; sha256: string }
|
|
130
|
+
}
|
|
131
|
+
region: {
|
|
132
|
+
source: 'auto' | 'file'
|
|
133
|
+
area: number
|
|
134
|
+
bounds: BoundingBox
|
|
135
|
+
centroid: Point
|
|
136
|
+
detection?: RegionMask['detection']
|
|
137
|
+
}
|
|
138
|
+
qr: QrMetadata & {
|
|
139
|
+
normalizedSize: number
|
|
140
|
+
normalizedModulePixels: number
|
|
141
|
+
}
|
|
142
|
+
placement: QrPlacement
|
|
143
|
+
artifacts: Record<'regionMask' | 'qr' | 'layoutPreview' | 'editMask' | 'beforeAi', string>
|
|
144
|
+
verification: VerificationResult
|
|
145
|
+
warnings: string[]
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export interface QrBoxInput {
|
|
149
|
+
x: number
|
|
150
|
+
y: number
|
|
151
|
+
size: number
|
|
152
|
+
/** Optional clockwise rotation in degrees; defaults to 0 (upright). */
|
|
153
|
+
rotation?: number
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export interface PosterInputOptions {
|
|
157
|
+
inputPath: string
|
|
158
|
+
outputDir: string
|
|
159
|
+
maskPath?: string
|
|
160
|
+
qrBox?: QrBoxInput
|
|
161
|
+
force?: boolean
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** Generate a QR from content, or retain the legacy QR PNG input for programmatic callers. */
|
|
165
|
+
export type QrInputOptions =
|
|
166
|
+
| { content: string; qrPath?: never; expectedText?: never }
|
|
167
|
+
| { content?: never; qrPath: string; expectedText?: string }
|
|
168
|
+
|
|
169
|
+
export type PreparePosterOptions = PosterInputOptions &
|
|
170
|
+
QrInputOptions & {
|
|
171
|
+
dryRun: true
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export interface PrepareResult {
|
|
175
|
+
report: ReportV1
|
|
176
|
+
outputDir: string
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export interface CompositePosterInputs {
|
|
180
|
+
original: Uint8Array
|
|
181
|
+
generated: Uint8Array
|
|
182
|
+
regionMask: RegionMask
|
|
183
|
+
qr: Uint8Array
|
|
184
|
+
placement: QrPlacement
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export type GeneratePosterOptions = PosterInputOptions &
|
|
188
|
+
QrInputOptions & {
|
|
189
|
+
apiKey?: string
|
|
190
|
+
baseUrl?: string
|
|
191
|
+
model?: string
|
|
192
|
+
prompt?: string
|
|
193
|
+
generatedImagePath?: string
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export interface ReportV2 extends Omit<ReportV1, 'schemaVersion' | 'status' | 'dryRun' | 'artifacts'> {
|
|
197
|
+
schemaVersion: 2
|
|
198
|
+
status: 'generated' | 'verification_failed' | 'generation_failed'
|
|
199
|
+
dryRun: false
|
|
200
|
+
artifacts: ReportV1['artifacts'] & {
|
|
201
|
+
aiRaw?: string
|
|
202
|
+
poster?: string
|
|
203
|
+
patternReference?: string
|
|
204
|
+
referenceCanvas?: string
|
|
205
|
+
}
|
|
206
|
+
generation: {
|
|
207
|
+
source: 'qwen' | 'file'
|
|
208
|
+
model: string
|
|
209
|
+
prompt: string
|
|
210
|
+
canvas: ImageDimensions
|
|
211
|
+
durationMs: number
|
|
212
|
+
requestId?: string
|
|
213
|
+
usage?: unknown
|
|
214
|
+
error?: string
|
|
215
|
+
}
|
|
216
|
+
phoneScan: 'untested'
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export interface GenerateResult {
|
|
220
|
+
report: ReportV2
|
|
221
|
+
outputDir: string
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export type PatternPreviewOptions = PosterInputOptions &
|
|
225
|
+
QrInputOptions & {
|
|
226
|
+
/** Module pitch in poster pixels; defaults to the pitch the pipeline places on the poster. */
|
|
227
|
+
modulePixels?: number
|
|
228
|
+
/** Seed for the random text line; defaults to a fresh random seed per run. */
|
|
229
|
+
seed?: number
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export interface PatternReport {
|
|
233
|
+
schemaVersion: 3
|
|
234
|
+
mode: 'pattern-preview'
|
|
235
|
+
status: 'generated'
|
|
236
|
+
createdAt: string
|
|
237
|
+
durationMs: number
|
|
238
|
+
inputs: ReportV1['inputs']
|
|
239
|
+
region: ReportV1['region']
|
|
240
|
+
placement: QrPlacement
|
|
241
|
+
pitchSource: 'placement' | 'override'
|
|
242
|
+
pattern: {
|
|
243
|
+
seed: number
|
|
244
|
+
alphabet: string
|
|
245
|
+
textLength: number
|
|
246
|
+
textSha256: string
|
|
247
|
+
ecc: 'M'
|
|
248
|
+
version: number
|
|
249
|
+
qrModules: number
|
|
250
|
+
quietZoneModules: 2
|
|
251
|
+
totalModules: number
|
|
252
|
+
modulePixels: number
|
|
253
|
+
pixelStyle: 'square' | 'rounded' | 'dot'
|
|
254
|
+
removedTypes: Array<'Position' | 'Alignment'>
|
|
255
|
+
/** Dropped marker cells are refilled with seeded random bits, never left light. */
|
|
256
|
+
markerRefill: 'seeded-random'
|
|
257
|
+
refilledModules: number
|
|
258
|
+
codeSize: number
|
|
259
|
+
canvas: ImageDimensions
|
|
260
|
+
crop: { left: number; top: number }
|
|
261
|
+
}
|
|
262
|
+
artifacts: {
|
|
263
|
+
pattern: string
|
|
264
|
+
patternSha256: string
|
|
265
|
+
}
|
|
266
|
+
warnings: string[]
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
export interface PatternPreviewResult {
|
|
270
|
+
report: PatternReport
|
|
271
|
+
outputDir: string
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
export interface PatternCutOptions {
|
|
275
|
+
/** Rendered pattern PNG to cut, poster-sized. */
|
|
276
|
+
inputPath: string
|
|
277
|
+
/** Same-size mask PNG: transparent or dark pixels select the cut shape. */
|
|
278
|
+
maskPath: string
|
|
279
|
+
outputDir: string
|
|
280
|
+
/** Corner fillet radius in pixels; defaults to 5. */
|
|
281
|
+
radius?: number
|
|
282
|
+
/** Douglas-Peucker tolerance in pixels for the traced outline; defaults to 3. */
|
|
283
|
+
smoothTolerance?: number
|
|
284
|
+
force?: boolean
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
export interface PatternCutReport {
|
|
288
|
+
schemaVersion: 4
|
|
289
|
+
mode: 'pattern-cut'
|
|
290
|
+
status: 'generated'
|
|
291
|
+
createdAt: string
|
|
292
|
+
durationMs: number
|
|
293
|
+
inputs: {
|
|
294
|
+
pattern: { path: string; sha256: string; width: number; height: number }
|
|
295
|
+
mask: { path: string; sha256: string; width: number; height: number }
|
|
296
|
+
}
|
|
297
|
+
cut: {
|
|
298
|
+
radius: number
|
|
299
|
+
smoothTolerance: number
|
|
300
|
+
/** A mask pixel selects the shape when it is transparent or dark. */
|
|
301
|
+
keep: 'transparent-or-dark'
|
|
302
|
+
minLoopArea: number
|
|
303
|
+
/** Solid black band retained inside the letter outline, in pixels. */
|
|
304
|
+
borderWidth: number
|
|
305
|
+
}
|
|
306
|
+
shape: {
|
|
307
|
+
loopsTraced: number
|
|
308
|
+
loopsKept: number
|
|
309
|
+
specksDropped: number
|
|
310
|
+
verticesTraced: number
|
|
311
|
+
verticesSimplified: number
|
|
312
|
+
holes: number
|
|
313
|
+
/** Area of the simplified cut polygon before corner rounding. */
|
|
314
|
+
area: number
|
|
315
|
+
radiusClamped: boolean
|
|
316
|
+
bounds: BoundingBox
|
|
317
|
+
}
|
|
318
|
+
artifacts: {
|
|
319
|
+
svg: string
|
|
320
|
+
svgSha256: string
|
|
321
|
+
png: string
|
|
322
|
+
pngSha256: string
|
|
323
|
+
}
|
|
324
|
+
warnings: string[]
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
export interface PatternCutResult {
|
|
328
|
+
report: PatternCutReport
|
|
329
|
+
outputDir: string
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
export type AssemblePosterOptions = PosterInputOptions &
|
|
333
|
+
QrInputOptions & {
|
|
334
|
+
/** Seed for the pattern random text line and the marker refill; defaults to a fresh seed per run. */
|
|
335
|
+
seed?: number
|
|
336
|
+
/** Depth of the light band kept beside each finder marker: one whole module. */
|
|
337
|
+
qrMargin?: 1
|
|
338
|
+
/** Keep one safe-module ring along the inside edge of the selected region light. */
|
|
339
|
+
regionMargin?: boolean
|
|
340
|
+
/**
|
|
341
|
+
* Plate corner treatment: zero keeps the diagonal corner block beside each finder marker light,
|
|
342
|
+
* and any positive value hands those three blocks to the texture. Defaults to two module pitches
|
|
343
|
+
* (12px on the bundled version-5 fixture), which rounds the plate. The region silhouette is always
|
|
344
|
+
* whole modules, so there is no fillet to size.
|
|
345
|
+
*/
|
|
346
|
+
radius?: number
|
|
347
|
+
/** Outer dark rim thickness in modules, 0 disables the rim. Range 0-5. */
|
|
348
|
+
rimModules?: number
|
|
349
|
+
/** When true the rim's outer corners are rounded with antialiased edges. */
|
|
350
|
+
rimRounded?: boolean
|
|
351
|
+
/** Not used by assembly: the cut is module-aligned rather than traced. Rejected when supplied. */
|
|
352
|
+
smoothTolerance?: number
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
export interface AssembleReport {
|
|
356
|
+
schemaVersion: 8
|
|
357
|
+
mode: 'assemble'
|
|
358
|
+
status: 'generated' | 'verification_failed'
|
|
359
|
+
qualified: boolean
|
|
360
|
+
createdAt: string
|
|
361
|
+
durationMs: number
|
|
362
|
+
inputs: ReportV1['inputs']
|
|
363
|
+
region: ReportV1['region']
|
|
364
|
+
qr: ReportV1['qr'] & {
|
|
365
|
+
/** The pixels actually composited: the code grid plus the light band beside the markers. */
|
|
366
|
+
overlay: {
|
|
367
|
+
/** The light band is kept beside the finder markers only. */
|
|
368
|
+
band: 'markers'
|
|
369
|
+
/** Depth of the light band beside each marker, in modules. */
|
|
370
|
+
quietZoneModules: number
|
|
371
|
+
/** Finder footprint each band arm spans, in modules. */
|
|
372
|
+
markerModules: number
|
|
373
|
+
/** Crop of the normalized QR the plate copies verbatim: the code grid, no quiet zone. */
|
|
374
|
+
crop: { left: number; top: number; size: number }
|
|
375
|
+
x: number
|
|
376
|
+
y: number
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
placement: QrPlacement
|
|
380
|
+
pattern: PatternReport['pattern'] & {
|
|
381
|
+
/** The settings palette the generated QR and the texture were rendered with. */
|
|
382
|
+
colors: {
|
|
383
|
+
pixel: string
|
|
384
|
+
marker: string
|
|
385
|
+
background: string
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* The texture window is phase-locked to the placed QR, so both share one module lattice.
|
|
389
|
+
* `phase` is the residual offset of the texture's module boundaries from the QR lattice:
|
|
390
|
+
* `0,0` means they coincide.
|
|
391
|
+
*/
|
|
392
|
+
alignment: {
|
|
393
|
+
alignedToQr: boolean
|
|
394
|
+
phase: { x: number; y: number }
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
cut: {
|
|
398
|
+
/** Poster-space module pitch the cut is quantized to; equals the placed QR pitch. */
|
|
399
|
+
modulePixels: number
|
|
400
|
+
/** Poster-space origin of the module lattice, in `[0, modulePixels)`. */
|
|
401
|
+
lattice: { x: number; y: number }
|
|
402
|
+
/** Requested `--cut-radius`; zero leaves the plate square, a positive value rounds it. */
|
|
403
|
+
radius: number
|
|
404
|
+
/** Modules whose whole pixel block is inside the painted region. */
|
|
405
|
+
safeModules: number
|
|
406
|
+
/** Modules the region covers only in part; the cut leaves them as the original artwork. */
|
|
407
|
+
droppedPartialModules: number
|
|
408
|
+
/** Region pixels inside those dropped modules. */
|
|
409
|
+
droppedPartialPixels: number
|
|
410
|
+
/** Modules the cut draws: safe modules minus the QR plate hole. */
|
|
411
|
+
drawnModules: number
|
|
412
|
+
/** Outer rings of drawn modules forced dark; rounded is antialiased. */
|
|
413
|
+
rim: { modules: number; style: 'cell' | 'rounded-antialiased' }
|
|
414
|
+
/** Light ring of safe modules along the region edge, 0 when disabled. */
|
|
415
|
+
regionMarginModules: 0 | 1
|
|
416
|
+
/** Modules of the plate handed back to the texture: the diagonal block at each marker corner. */
|
|
417
|
+
plateCornerModules: number
|
|
418
|
+
/** The cut shape is the detected or supplied painted region itself. */
|
|
419
|
+
keep: 'region-mask'
|
|
420
|
+
/** Whole modules replace the original pixels; antialiased blends the edge. */
|
|
421
|
+
edgeBlend: 'cell-aligned-over-original' | 'antialiased'
|
|
422
|
+
}
|
|
423
|
+
/** The plate the texture is cut around and the QR is drawn in; all of it is whole modules. */
|
|
424
|
+
qrPlate: {
|
|
425
|
+
/** The light band is kept beside the finder markers only. */
|
|
426
|
+
band: 'markers'
|
|
427
|
+
/** Depth of the light band beside each marker: one whole module. */
|
|
428
|
+
marginModules: 1
|
|
429
|
+
/** The band actually painted, in pixels: `marginModules * modulePixels`. */
|
|
430
|
+
marginPixels: number
|
|
431
|
+
/** Finder footprint each band arm spans, in modules. */
|
|
432
|
+
markerModules: number
|
|
433
|
+
/** Light cells the band keeps beside the three markers, corner blocks included. */
|
|
434
|
+
bandCells: number
|
|
435
|
+
/** The code grid the plate copies verbatim; the band sits outside it. */
|
|
436
|
+
box: BoundingBox
|
|
437
|
+
/** Modules the hole covers: code grid plus band, corner blocks already handed back. */
|
|
438
|
+
holeModules: number
|
|
439
|
+
/** Modules handed back to the texture, 0 when `--cut-radius` is zero. */
|
|
440
|
+
cornerModules: number
|
|
441
|
+
/** Pixels those modules leave as texture instead of the QR's own light band. */
|
|
442
|
+
cornerTexturePixels: number
|
|
443
|
+
}
|
|
444
|
+
shape: {
|
|
445
|
+
/** Canvas-pixel bounds of the drawn modules. */
|
|
446
|
+
bounds: BoundingBox
|
|
447
|
+
/** Pixels the drawn modules cover: texture, rim, or light margin. */
|
|
448
|
+
area: number
|
|
449
|
+
/** Modules the cut draws. */
|
|
450
|
+
modules: number
|
|
451
|
+
/** Drawn modules forced dark as the rim. */
|
|
452
|
+
rimModules: number
|
|
453
|
+
/** Drawn modules painted light as the region edge or tight-QR quiet margin. */
|
|
454
|
+
marginModules: number
|
|
455
|
+
/** Drawn modules carrying the texture. */
|
|
456
|
+
textureModules: number
|
|
457
|
+
}
|
|
458
|
+
artifacts: {
|
|
459
|
+
poster: string
|
|
460
|
+
posterSha256: string
|
|
461
|
+
regionMask: string
|
|
462
|
+
qr: string
|
|
463
|
+
qrSha256: string
|
|
464
|
+
patternCutPng: string
|
|
465
|
+
patternCutPngSha256: string
|
|
466
|
+
patternCutSvg: string
|
|
467
|
+
patternCutSvgSha256: string
|
|
468
|
+
}
|
|
469
|
+
verification: VerificationResult
|
|
470
|
+
phoneScan: 'untested'
|
|
471
|
+
warnings: string[]
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
export interface AssembleResult {
|
|
475
|
+
report: AssembleReport
|
|
476
|
+
outputDir: string
|
|
477
|
+
}
|