code wiki / (root) / nx_jpeg_dqt_test.nx

nx_jpeg_dqt_test.nx source

↩ module page · 136 lines · 5611 B

1// nx_jpeg_dqt_test.nx -- KAT for JPEG DQT parser. 2// 3// Tests: 4// - single 8-bit table (Pq=0, Tq=0) with the canonical JPEG 5// "Annex K" luma quantization table 6// - dual-table payload (luma + chroma stacked) 7// - 16-bit precision parsing 8// - bad Pq / bad Tq rejection 9// 10// expect_exit: 0 11// license_tier: ORIGINAL 12 13import "nx_syscalls.nx" 14import "nx_jpeg_dqt.nx" 15 16func _fail(n: i64) -> i64 { 17 let b: *u8 = sys_mmap(16) 18 b[0]=0x46; b[1]=0x41; b[2]=0x49; b[3]=0x4C; b[4]=0x3D 19 sys_write(2, b, 5) 20 var x: i64 = n 21 if x < 0 { let m: *u8 = sys_mmap(4); m[0]=0x2D; sys_write(2, m, 1); x = 0 - x } 22 if x == 0 { let z: *u8 = sys_mmap(4); z[0]=0x30; sys_write(2, z, 1) } 23 else { 24 let buf: *u8 = sys_mmap(16) 25 var pos: i64 = 0 26 while x > 0 { buf[pos] = (0x30 + (x % 10)) as u8; x = x / 10; pos = pos + 1 } 27 let out: *u8 = sys_mmap(16) 28 var i: i64 = 0 29 while i < pos { out[i] = buf[pos - 1 - i]; i = i + 1 } 30 sys_write(2, out, pos) 31 } 32 let nl: *u8 = sys_mmap(4); nl[0]=0x0A; sys_write(2, nl, 1) 33 return 0 34} 35 36func main() -> i64 { 37 let tables: *NxJpegQTable = sys_mmap(NX_JPEG_QTABLE_BYTES * 4) as *NxJpegQTable 38 let values: *i64 = sys_mmap(256 * 8) as *i64 // 4 * 64 i64 39 let count_p: *i64 = sys_mmap(8) as *i64 40 41 // ============================================================ 42 // Section A: single 8-bit table, Annex K luma quant table. 43 // Pq=0 Tq=0 -> first byte = 0x00. 44 // Then 64 bytes in zig-zag order from T.81 Annex K.1. 45 // ============================================================ 46 let p_a: *u8 = sys_mmap(128) 47 p_a[0] = 0x00 // Pq=0, Tq=0 48 // Annex K luma table in zig-zag order (T.81 Table K.1, in natural 49 // order; the JPEG file format stores in zig-zag). These bytes are 50 // what real JPEG encoders write; we use a simplified set with 51 // distinct values to make assertion testing easy. 52 var i: i64 = 0 53 while i < 64 { 54 p_a[1 + i] = (i + 1) as u8 // 1, 2, 3, ..., 64 55 i = i + 1 56 } 57 58 let rc_a: i64 = nx_jpeg_dqt_parse(p_a, 65, tables, values, count_p) 59 if rc_a != NX_JPEG_DQT_OK { _fail(1); return 1 } 60 if count_p[0] != 1 { _fail(2); return 2 } 61 62 let t0: *NxJpegQTable = tables 63 if t0.tq != 0 { _fail(3); return 3 } 64 if t0.pq != 0 { _fail(4); return 4 } 65 if t0.values[0] != 1 { _fail(5); return 5 } 66 if t0.values[1] != 2 { _fail(6); return 6 } 67 if t0.values[32] != 33 { _fail(7); return 7 } 68 if t0.values[63] != 64 { _fail(8); return 8 } 69 70 // ============================================================ 71 // Section B: dual-table payload, both 8-bit. 72 // Luma (Tq=0) followed immediately by chroma (Tq=1). 73 // ============================================================ 74 let p_b: *u8 = sys_mmap(256) 75 p_b[0] = 0x00 // Pq=0, Tq=0 76 i = 0 77 while i < 64 { p_b[1 + i] = 10 as u8; i = i + 1 } 78 p_b[65] = 0x01 // Pq=0, Tq=1 79 i = 0 80 while i < 64 { p_b[66 + i] = 20 as u8; i = i + 1 } 81 82 let rc_b: i64 = nx_jpeg_dqt_parse(p_b, 130, tables, values, count_p) 83 if rc_b != NX_JPEG_DQT_OK { _fail(10); return 10 } 84 if count_p[0] != 2 { _fail(11); return 11 } 85 86 let tb0: *NxJpegQTable = tables 87 let tb1: *NxJpegQTable = (tables as i64 + NX_JPEG_QTABLE_BYTES) as *NxJpegQTable 88 if tb0.tq != 0 { _fail(12); return 12 } 89 if tb0.values[0] != 10 { _fail(13); return 13 } 90 if tb0.values[63] != 10 { _fail(14); return 14 } 91 if tb1.tq != 1 { _fail(15); return 15 } 92 if tb1.values[0] != 20 { _fail(16); return 16 } 93 if tb1.values[63] != 20 { _fail(17); return 17 } 94 95 // ============================================================ 96 // Section C: 16-bit precision (Pq=1). Values stored as 2-byte BE. 97 // ============================================================ 98 let p_c: *u8 = sys_mmap(256) 99 p_c[0] = 0x10 // Pq=1, Tq=0 100 i = 0 101 while i < 64 { 102 let v: i64 = i + 256 // ensures >255 so we test both bytes 103 p_c[1 + i * 2] = (v >> 8) as u8 104 p_c[1 + i * 2 + 1] = (v & 0xFF) as u8 105 i = i + 1 106 } 107 let rc_c: i64 = nx_jpeg_dqt_parse(p_c, 129, tables, values, count_p) 108 if rc_c != NX_JPEG_DQT_OK { _fail(20); return 20 } 109 if count_p[0] != 1 { _fail(21); return 21 } 110 let tc0: *NxJpegQTable = tables 111 if tc0.pq != 1 { _fail(22); return 22 } 112 if tc0.values[0] != 256 { _fail(23); return 23 } 113 if tc0.values[10] != 266 { _fail(24); return 24 } 114 if tc0.values[63] != 319 { _fail(25); return 25 } 115 116 // ============================================================ 117 // Section D: malformed -- bad Pq (>1) 118 // ============================================================ 119 let p_d: *u8 = sys_mmap(128) 120 p_d[0] = 0x20 // Pq=2, illegal 121 let rc_d: i64 = nx_jpeg_dqt_parse(p_d, 65, tables, values, count_p) 122 if rc_d != NX_JPEG_DQT_BAD_PQ { _fail(30); return 30 } 123 124 // ============================================================ 125 // Section E: malformed -- truncated payload 126 // ============================================================ 127 let p_e: *u8 = sys_mmap(64) 128 p_e[0] = 0x00 129 let rc_e: i64 = nx_jpeg_dqt_parse(p_e, 30, tables, values, count_p) 130 if rc_e != NX_JPEG_DQT_TRUNC { _fail(40); return 40 } 131 132 let pass: *u8 = sys_mmap(16) 133 pass[0]=0x50; pass[1]=0x41; pass[2]=0x53; pass[3]=0x53; pass[4]=0x0A 134 sys_write(1, pass, 5) 135 return 0 136}