code wiki / (root) / nx_jpeg_ascii_test.nx

nx_jpeg_ascii_test.nx source

↩ module page · 135 lines · 4461 B

1// nx_jpeg_ascii_test.nx -- KAT for the JPEG -> luminance ASCII bridge. 2// 3// Builds the same minimal grayscale 8x8 baseline JPEG used by 4// nx_jpeg_decode_test (zero-coefficient block -> every luma sample 5// == 128 after level shift), renders it through nx_jpeg_to_ascii_fb 6// at native 8x8, and verifies: 7// - the bridge returns NX_JPEG_ASCII_OK 8// - the framebuffer is 8x8 grayscale RGBA with every pixel == 128 9// - nx_paint_fb_ascii_dump maps luminance 128 to 'o' (the 128..191 10// bucket) for all 64 content cells, with row newlines. 11// 12// expect_exit: 0 13// license_tier: ORIGINAL 14 15import "nx_syscalls.nx" 16import "nx_paint_solid_rect.nx" 17import "nx_paint_fb_ascii_dump.nx" 18import "nx_jpeg_ascii.nx" 19 20func _fail(n: i64) -> i64 { 21 let b: *u8 = sys_mmap(16) 22 b[0]=0x46; b[1]=0x41; b[2]=0x49; b[3]=0x4C; b[4]=0x3D 23 sys_write(2, b, 5) 24 var x: i64 = n 25 if x < 0 { let m: *u8 = sys_mmap(4); m[0]=0x2D; sys_write(2, m, 1); x = 0 - x } 26 if x == 0 { let z: *u8 = sys_mmap(4); z[0]=0x30; sys_write(2, z, 1) } 27 else { 28 let buf: *u8 = sys_mmap(16) 29 var pos: i64 = 0 30 while x > 0 { buf[pos] = (0x30 + (x % 10)) as u8; x = x / 10; pos = pos + 1 } 31 let out: *u8 = sys_mmap(16) 32 var i: i64 = 0 33 while i < pos { out[i] = buf[pos - 1 - i]; i = i + 1 } 34 sys_write(2, out, pos) 35 } 36 let nl: *u8 = sys_mmap(4); nl[0]=0x0A; sys_write(2, nl, 1) 37 return 0 38} 39 40// Construct the 137-byte all-128 grayscale baseline JPEG. Identical 41// byte layout to nx_jpeg_decode_test. 42func _build_gray_jpeg(jpeg: *u8) -> i64 { 43 var p: i64 = 0 44 // SOI 45 jpeg[p]=0xFF; p=p+1; jpeg[p]=0xD8; p=p+1 46 // DQT (Pq=0 Tq=0, all-ones identity quant) 47 jpeg[p]=0xFF; p=p+1; jpeg[p]=0xDB; p=p+1 48 jpeg[p]=0x00; p=p+1; jpeg[p]=0x43; p=p+1 49 jpeg[p]=0x00; p=p+1 50 var i: i64 = 0 51 while i < 64 { jpeg[p+i] = 1; i = i + 1 } 52 p = p + 64 53 // DHT (DC + AC stacked, 36-byte payload) 54 jpeg[p]=0xFF; p=p+1; jpeg[p]=0xC4; p=p+1 55 jpeg[p]=0x00; p=p+1; jpeg[p]=0x26; p=p+1 56 jpeg[p]=0x00; p=p+1 57 jpeg[p]=0x01; p=p+1 58 i = 0 59 while i < 15 { jpeg[p+i] = 0; i = i + 1 } 60 p = p + 15 61 jpeg[p]=0x00; p=p+1 62 jpeg[p]=0x10; p=p+1 63 jpeg[p]=0x01; p=p+1 64 i = 0 65 while i < 15 { jpeg[p+i] = 0; i = i + 1 } 66 p = p + 15 67 jpeg[p]=0x00; p=p+1 68 // SOF0 (1 comp, 8x8) 69 jpeg[p]=0xFF; p=p+1; jpeg[p]=0xC0; p=p+1 70 jpeg[p]=0x00; p=p+1; jpeg[p]=0x0B; p=p+1 71 jpeg[p]=0x08; p=p+1 72 jpeg[p]=0x00; p=p+1; jpeg[p]=0x08; p=p+1 73 jpeg[p]=0x00; p=p+1; jpeg[p]=0x08; p=p+1 74 jpeg[p]=0x01; p=p+1 75 jpeg[p]=0x01; p=p+1 76 jpeg[p]=0x11; p=p+1 77 jpeg[p]=0x00; p=p+1 78 // SOS (1 comp) 79 jpeg[p]=0xFF; p=p+1; jpeg[p]=0xDA; p=p+1 80 jpeg[p]=0x00; p=p+1; jpeg[p]=0x08; p=p+1 81 jpeg[p]=0x01; p=p+1 82 jpeg[p]=0x01; p=p+1 83 jpeg[p]=0x00; p=p+1 84 jpeg[p]=0x00; p=p+1 85 jpeg[p]=0x3F; p=p+1 86 jpeg[p]=0x00; p=p+1 87 // Entropy: DC cat 0 + AC EOB 88 jpeg[p]=0x00; p=p+1 89 // EOI 90 jpeg[p]=0xFF; p=p+1; jpeg[p]=0xD9; p=p+1 91 return p 92} 93 94func main() -> i64 { 95 let jpeg: *u8 = sys_mmap(256) 96 let jpeg_len: i64 = _build_gray_jpeg(jpeg) 97 98 let fb: *Framebuffer = sys_mmap(NX_FRAMEBUFFER_BYTES) as *Framebuffer 99 let rc: i64 = nx_jpeg_to_ascii_fb(jpeg, jpeg_len, 8, 8, fb) 100 if rc != NX_JPEG_ASCII_OK { _fail(10 + rc); return 10 } 101 102 if fb.width != 8 { _fail(20); return 20 } 103 if fb.height != 8 { _fail(21); return 21 } 104 105 // Every pixel must be grayscale 128, fully opaque. 106 var i: i64 = 0 107 while i < 64 { 108 let o: i64 = i * 4 109 if (fb.pixels[o + 0] as i64 & 255) != 128 { _fail(30 + i); return 30 } 110 if (fb.pixels[o + 3] as i64 & 255) != 255 { _fail(100 + i); return 100 } 111 i = i + 1 112 } 113 114 // ASCII dump: 8 content cells + '\n' per row, 8 rows == 72 bytes. 115 let out: *u8 = sys_mmap(256) 116 let n: i64 = nx_paint_fb_ascii_dump(fb, out, 256) 117 if n != 72 { _fail(200 + n); return 200 } 118 119 // Content cells are 'o' (111); column 8 of each row is '\n' (10). 120 var y: i64 = 0 121 while y < 8 { 122 var x: i64 = 0 123 while x < 8 { 124 if (out[y * 9 + x] as i64 & 255) != 111 { _fail(300 + y * 9 + x); return 300 } 125 x = x + 1 126 } 127 if (out[y * 9 + 8] as i64 & 255) != 10 { _fail(400 + y); return 400 } 128 y = y + 1 129 } 130 131 let pass: *u8 = sys_mmap(16) 132 pass[0]=0x50; pass[1]=0x41; pass[2]=0x53; pass[3]=0x53; pass[4]=0x0A 133 sys_write(1, pass, 5) 134 return 0 135}