nx_image_grade_v0.nx
buildroot/runtime/nx_image_grade_v0.nx
about
nx_image_grade_v0.nx -- minimum-trigger image grading composer.
CAPABILITY_COMPLETENESS: PARTIAL
MISSING_CAPABILITIES:
- per-region tier-axis verdicts (vein-signal / subsurface /
micro-expression / finger-count / shadow-direction /
surface-plane / interior-geometry / etc.) -- ALL marked
PENDING_SEGMENTATION; require nx_segmenter_classical
(queued Phase 3 of NISHI_VLM_AND_GRADER_ROADMAP.md)
- true CIELab chroma classification (nx_lab_from_rgb queued);
v0 uses RGB-proxy undertone heuristic
- palette PNG / progressive JPEG / Adam7 -- caller sees
decoder's UNSUPPORTED_* error code propagated up
- VLM verdicts (the second triangulation source);
this v0 ships MATH ONLY
COVERED:
- Auto-detect PNG vs JPEG by magic bytes
- Decoder dispatch + error propagation
- Tier 0 verdicts: dimensions, channels, bytes-per-pixel
- Tier 1 whole-image: mean luminance, channel histograms,
dynamic range
- Tier 1 RGB-proxy undertone (provisional until nx_lab_from_rgb)
- Tier 1 RGB-proxy skin-tone band via mean(R+G+B) of all pixels
(provisional until skin segmenter lands)
- Per-axis verdict + human-legible phrase via nx_verdict_phrase
The composer's job is to be the SUBSTRATE'S FIRST TRIGGER
PIPELINE -- one call takes an image file's bytes and returns a
stratified report. Per-axis PENDING entries are honest; caller
learns at COMPILE time (header) which axes are not yet wired.
genealogy_id: substrate_image_grade_v0_composer_2026_05_16
lineage_id: nx_image_grade_v0
dependencies 9 imports · 1 importers
imports: nx_syscalls.nxnx_runtime.nxnx_tier.nxnx_png_decoder.nxnx_jpeg_decoder.nxnx_verdict_phrase.nxnx_lab_from_rgb.nxnx_skin_tone_ita.nxnx_undertone_class.nx
imported by: nx_png_real_smoke.nx
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| 77 | struct NxIgv0AxisVerdict |
| 90 | struct NxIgv0Report |
consts
| 51 | const NX_MAGIC_1024: i64 = 1024 |
| 55 | const NX_IGV0_FORMAT_UNKNOWN: nx_int = 0 |
| 56 | const NX_IGV0_FORMAT_PNG: nx_int = 1 |
| 57 | const NX_IGV0_FORMAT_JPEG: nx_int = 2 |
| 61 | const NX_IGV0_OK: nx_int = 0 |
| 62 | const NX_IGV0_ERR_TOO_SHORT: nx_int = 1 |
| 63 | const NX_IGV0_ERR_UNKNOWN_FORMAT: nx_int = 2 |
| 64 | const NX_IGV0_ERR_DECODER: nx_int = 3 |
| 65 | const NX_IGV0_ERR_NULL_PIXELS: nx_int = 4 |
| 69 | const NX_IGV0_AXIS_OK: nx_int = 0 |
| 70 | const NX_IGV0_AXIS_PENDING_SEGMENTATION: nx_int = 1 |
| 71 | const NX_IGV0_AXIS_PENDING_LAB_CONVERSION: nx_int = 2 |
| 72 | const NX_IGV0_AXIS_PENDING_VLM: nx_int = 3 |
| 73 | const NX_IGV0_AXIS_NOT_APPLICABLE: nx_int = 4 |
| 86 | const NX_IGV0_AXIS_VERDICT_BYTES: nx_size = 48 |
| 107 | const NX_IGV0_REPORT_BYTES: nx_size = 96 |
| 110 | const NX_IGV0_AX_DIMENSIONS: nx_int = 0 |
| 111 | const NX_IGV0_AX_LUMINANCE: nx_int = 1 |
| 112 | const NX_IGV0_AX_SKIN_TONE_ITA: nx_int = 4 |
| 113 | const NX_IGV0_AX_GLCM_TEXTURE: nx_int = 5 |
| 114 | const NX_IGV0_AX_PORE_DETAIL: nx_int = 7 |
| 115 | const NX_IGV0_AX_UNDERTONE: nx_int = 12 |
| 116 | const NX_IGV0_AX_VEIN_SIGNAL: nx_int = 16 |
| 117 | const NX_IGV0_AX_SUBSURFACE_SIGNAL: nx_int = 17 |
| 118 | const NX_IGV0_AX_MICRO_EXPRESSION: nx_int = 22 |
| 119 | const NX_IGV0_AX_SHADOW_DIRECTION: nx_int = 23 |
| 120 | const NX_IGV0_AX_FINGER_COUNT: nx_int = 24 |
| 121 | const NX_IGV0_AX_SURFACE_PLANE: nx_int = 27 |
| 123 | const NX_IGV0_N_AXES: nx_int = 12 |
functions
| 127 | func _igv0_detect_format(buf: *u8, n: nx_int) -> nx_int |
| 150 | func _igv0_scan_means(pixels: *u8, w: nx_int, h: nx_int, called by 1: nx_image_grade_v0 |
| 202 | func _igv0_lab_skin_tone_band(lab: *NxLabColor) -> nx_int |
| 209 | func _igv0_lab_undertone(lab: *NxLabColor) -> nx_int |
| 217 | func _igv0_set_axis(axes: *NxIgv0AxisVerdict, idx: nx_int, |
| 275 | func nx_image_grade_v0(input: *u8, input_size: nx_int) -> *NxIgv0Report called by 2: mainmain calls 9: sys_mmap_igv0_detect_formatnx_png_decodenx_jpeg_decode_igv0_scan_meansnx_lab_from_rgb+3 |
| 400 | func main() -> nx_int |