nx_bmp.nx source
↩ module page · 78 lines · 2275 B
1// nx_bmp.nx -- sovereign 24-bit BMP writer, so detector output is VIEWABLE
2// directly on Windows (double-click) with no browser, no PNG encoder, no
3// third-party. BI_RGB, bottom-up, BGR, rows padded to 4 bytes.
4//
5// genealogy_id: microsoft_bmp_bi_rgb (record-hint)
6// lineage_id: bmp_fileheader + infoheader + bgr_bottom_up
7// license_tier: ORIGINAL
8import "syscalls.nx"
9import "nx_image.nx"
10
11func bmp_u32(fd: i64, v: i64) -> i64 {
12 let b: *u8 = sys_mmap(4)
13 b[0] = (v & 255) as u8
14 b[1] = ((v >> 8) & 255) as u8
15 b[2] = ((v >> 16) & 255) as u8
16 b[3] = ((v >> 24) & 255) as u8
17 sys_write(fd, b, 4)
18 return 0
19}
20func bmp_u16(fd: i64, v: i64) -> i64 {
21 let b: *u8 = sys_mmap(2)
22 b[0] = (v & 255) as u8
23 b[1] = ((v >> 8) & 255) as u8
24 sys_write(fd, b, 2)
25 return 0
26}
27
28// Write an RGB *Image as a 24-bit BMP. Returns 0 ok / -1 fail.
29func bmp_write(img: *Image, path: *u8) -> i64 {
30 let w: i64 = img.width
31 let h: i64 = img.height
32 let row3: i64 = w * 3
33 let pad: i64 = (4 - (row3 % 4)) % 4
34 let rowstride: i64 = row3 + pad
35 let datasize: i64 = rowstride * h
36 let filesize: i64 = 54 + datasize
37
38 let fd: i64 = sys_openat_wr(path, 420)
39 if fd < 0 { return 0 - 1 }
40 // BITMAPFILEHEADER (14 bytes)
41 sys_write(fd, "BM\x00" as *u8, 2)
42 bmp_u32(fd, filesize)
43 bmp_u32(fd, 0)
44 bmp_u32(fd, 54)
45 // BITMAPINFOHEADER (40 bytes)
46 bmp_u32(fd, 40)
47 bmp_u32(fd, w)
48 bmp_u32(fd, h)
49 bmp_u16(fd, 1)
50 bmp_u16(fd, 24)
51 bmp_u32(fd, 0)
52 bmp_u32(fd, datasize)
53 bmp_u32(fd, 0)
54 bmp_u32(fd, 0)
55 bmp_u32(fd, 0)
56 bmp_u32(fd, 0)
57 // pixels, bottom-up, BGR
58 let rowbuf: *u8 = sys_mmap(rowstride + 4)
59 var y: i64 = h - 1
60 while y >= 0 {
61 var x: i64 = 0
62 while x < w {
63 let r: i64 = nx_image_get(img, x, y, 0)
64 let g: i64 = nx_image_get(img, x, y, 1)
65 let b: i64 = nx_image_get(img, x, y, 2)
66 rowbuf[x * 3] = b as u8
67 rowbuf[x * 3 + 1] = g as u8
68 rowbuf[x * 3 + 2] = r as u8
69 x = x + 1
70 }
71 var p: i64 = 0
72 while p < pad { rowbuf[row3 + p] = 0 as u8; p = p + 1 }
73 sys_write(fd, rowbuf, rowstride)
74 y = y - 1
75 }
76 sys_close(fd)
77 return 0
78}