nx_media_index.nx source
↩ module page · 105 lines · 3871 B
1// nx_media_index.nx -- EXPOSURE rung X1 (library): tag a real media file by
2// running the detectors over it, producing a record the portal can filter and
3// search. REUSES the shipped sovereign decoder (nx_png_decode) + R2 presence
4// -- no new decode/detect code. This is how the capabilities reach the real
5// library instead of synthetic in-memory pixels.
6//
7// PNG today (the gallery is PNG, verified end-to-end on a real 1024x768 file).
8// JPEG is a drop-in extension via the existing nx_jpeg_decode; NAS .jpg paths
9// also need an SMB-reachable mount -- both deliberately deferred, not faked.
10//
11// genealogy_id: media_studio_exposure_index (record-hint)
12// lineage_id: decode + presence + tag_record
13// license_tier: ORIGINAL
14import "nx_syscalls.nx"
15import "nx_tier.nx"
16import "nx_image.nx"
17import "nx_png_decoder.nx"
18import "nx_jpeg_ascii.nx"
19import "nx_presence.nx"
20
21const NX_MIDX_OK: i64 = 0
22const NX_MIDX_NOFILE: i64 = 1
23const NX_MIDX_NOTPNG: i64 = 2
24const NX_MIDX_DECERR: i64 = 3
25
26const NX_MIDX_MIN_SKIN: i64 = 50
27const NX_MIDX_MIN_CONC: i64 = 500
28
29// Wrap a decoded PNG result as an nx_image pointing at its pixel buffer.
30func nx_mindex_png_to_image(r: *NxPngResult) -> *Image {
31 let raw: *u8 = sys_mmap(40)
32 let img: *Image = raw as *Image
33 img.pixels = r.pixels
34 img.width = r.header.width
35 img.height = r.header.height
36 img.channels = r.n_channels
37 img.stride = r.header.width * r.n_channels
38 return img
39}
40
41// Wrap a packed RGB buffer (from nx_jpeg_decode_rgb) as an nx_image.
42func nx_mindex_rgb_to_image(rgb: *u8, w: i64, h: i64) -> *Image {
43 let raw: *u8 = sys_mmap(40)
44 let img: *Image = raw as *Image
45 img.pixels = rgb
46 img.width = w
47 img.height = h
48 img.channels = 3
49 img.stride = w * 3
50 return img
51}
52
53// Tag one media file by path. Writes a 7-field record into out[]:
54// [0]=status [1]=width (or PNG err code when status=DECERR) [2]=height
55// [3]=skin permille [4]=conc permille [5]=present(1/0) [6]=skin count
56// Returns the status.
57func nx_mindex_tag_path(path: *u8, out: *i64) -> i64 {
58 out[0] = NX_MIDX_NOFILE
59 out[1] = 0
60 out[2] = 0
61 out[3] = 0
62 out[4] = 0
63 out[5] = 0
64 out[6] = 0
65 out[7] = 0 - 1 // bbox minx,miny,maxx,maxy
66 out[8] = 0 - 1
67 out[9] = 0 - 1
68 out[10] = 0 - 1
69 let szp: *i64 = sys_mmap(16) as *i64
70 let buf: *u8 = sys_read_file(path, szp)
71 if (buf as i64) == 0 { return out[0] }
72 if szp[0] < 8 { out[0] = NX_MIDX_NOTPNG; return out[0] }
73 var img: *Image = 0 as *Image
74 let b0: i64 = buf[0] as i64
75 let b1: i64 = buf[1] as i64
76 if b0 == 137 && b1 == 80 { // PNG (\x89 'P')
77 let r: *NxPngResult = nx_png_decode(buf, szp[0])
78 if (r as i64) == 0 { out[0] = NX_MIDX_DECERR; return out[0] }
79 if r.error_code != NX_PNG_OK { out[0] = NX_MIDX_DECERR; out[1] = r.error_code; return out[0] }
80 img = nx_mindex_png_to_image(r)
81 }
82 if b0 == 255 && b1 == 216 { // JPEG (0xFF 0xD8)
83 let pr: *i64 = sys_mmap(8) as *i64
84 let pw: *i64 = sys_mmap(8) as *i64
85 let ph: *i64 = sys_mmap(8) as *i64
86 let dr: i64 = nx_jpeg_decode_rgb(buf, szp[0], pr, pw, ph)
87 if dr != NX_JPEG_ASCII_OK { out[0] = NX_MIDX_DECERR; out[1] = dr; return out[0] }
88 img = nx_mindex_rgb_to_image(pr[0] as *u8, pw[0], ph[0])
89 }
90 if (img as i64) == 0 { out[0] = NX_MIDX_NOTPNG; return out[0] } // unsupported format
91 let pout: *i64 = sys_mmap(128) as *i64
92 nx_presence_scan(img, pout)
93 out[0] = NX_MIDX_OK
94 out[1] = img.width
95 out[2] = img.height
96 out[3] = pout[0]
97 out[4] = pout[1]
98 out[5] = nx_presence_classify(pout[0], pout[1], NX_MIDX_MIN_SKIN, NX_MIDX_MIN_CONC)
99 out[6] = pout[2]
100 out[7] = pout[3]
101 out[8] = pout[4]
102 out[9] = pout[5]
103 out[10] = pout[6]
104 return out[0]
105}