Skip to content

Commit 082f2aa

Browse files
fix: rMQR pattern ordering matches Zint — timing first then finder overlay
Follow exact Zint rmqr_setup_grid order: timing → finder → alignment → corners → separator. Previous order had timing overwriting finder. Also fix timing polarity: !(i & 1) for all edges. Match with Zint: 82.7% (was 72.8%) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 9c9be5c commit 082f2aa

1 file changed

Lines changed: 18 additions & 18 deletions

File tree

src/encoders/rmqr.ts

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -216,47 +216,47 @@ export function encodeRMQR(text: string, options: RMQROptions = {}): boolean[][]
216216
Array.from<boolean | null>({ length: cols }).fill(null),
217217
);
218218

219-
// 1. Finder pattern (7×7 at top-left)
219+
// Follow EXACT Zint rmqr_setup_grid order:
220+
// 1. Timing patterns FIRST (all 4 edges)
221+
for (let c = 0; c < cols; c++) {
222+
matrix[0]![c] = !(c & 1);
223+
matrix[rows - 1]![c] = !(c & 1);
224+
}
225+
for (let r = 0; r < rows; r++) {
226+
matrix[r]![0] = !(r & 1);
227+
matrix[r]![cols - 1] = !(r & 1);
228+
}
229+
230+
// 2. Finder pattern (7×7 at top-left) - OVERRIDES timing
220231
for (let r = 0; r < 7; r++) {
221232
for (let c = 0; c < 7; c++) {
222233
const isOuter = r === 0 || r === 6 || c === 0 || c === 6;
223234
const isInner = r >= 2 && r <= 4 && c >= 2 && c <= 4;
224235
matrix[r]![c] = isOuter || isInner;
225236
}
226237
}
227-
// Separator around finder
228-
if (rows > 7) for (let c = 0; c < 8 && c < cols; c++) matrix[7]![c] = false;
229-
for (let r = 0; r < 7 && 7 < cols; r++) matrix[r]![7] = false;
230238

231-
// 2. Bottom-right alignment pattern (5×5)
239+
// 3. Bottom-right alignment (5×5) - OVERRIDES timing
232240
const arx = cols - 5;
233241
const ary = rows - 5;
234-
const AP = [0x1f, 0x11, 0x15, 0x11, 0x1f]; // 5x5 alignment
242+
const AP = [0x1f, 0x11, 0x15, 0x11, 0x1f];
235243
for (let r = 0; r < 5; r++) {
236244
for (let c = 0; c < 5; c++) {
237245
matrix[ary + r]![arx + c] = ((AP[r]! >> (4 - c)) & 1) === 1;
238246
}
239247
}
240248

241-
// 3. Corner finder patterns (from Zint rmqr_setup_grid)
242-
// Bottom-left: (v_size-2,0)=dark, (v_size-2,1)=light, (v_size-1,1)=dark
249+
// 4. Corner finder patterns
243250
matrix[rows - 2]![0] = true;
244251
matrix[rows - 2]![1] = false;
245252
matrix[rows - 1]![1] = true;
246-
// Top-right: (0,h_size-2)=dark, (1,h_size-2)=light, (1,h_size-1)=dark
247253
matrix[0]![cols - 2] = true;
248254
matrix[1]![cols - 2] = false;
249255
matrix[1]![cols - 1] = true;
250256

251-
// 4. Timing patterns on all 4 edges
252-
for (let c = 7; c < cols - 1; c++) {
253-
if (matrix[0]![c] === null) matrix[0]![c] = c % 2 === 0;
254-
if (matrix[rows - 1]![c] === null) matrix[rows - 1]![c] = (c + 1) % 2 === 0;
255-
}
256-
for (let r = 1; r < rows - 1; r++) {
257-
if (matrix[r]![0] === null) matrix[r]![0] = (r + 1) % 2 === 0;
258-
if (matrix[r]![cols - 1] === null) matrix[r]![cols - 1] = r % 2 === 0;
259-
}
257+
// 5. Separator
258+
for (let r = 0; r < 7; r++) matrix[r]![7] = false;
259+
if (rows > 7) for (let c = 0; c < 8; c++) matrix[7]![c] = false;
260260

261261
// 4b. Sub-alignment vertical timing columns (rMQR-specific)
262262
// Column positions from rmqr_table_d1, indexed by width group

0 commit comments

Comments
 (0)