code wiki / (root) / nx_png_decoder.nx

nx_png_decoder.nx

buildroot/runtime/nx_png_decoder.nx

32851 B822 linesdepth 7pulls 10 transitivereach 96 importersview sourcekind tooltopic png
docsdependenciesstructsconstsfunctions

about

nx_png_decoder.nx -- RFC 2083 PNG decoder. CAPABILITY_COMPLETENESS: PARTIAL MISSING_CAPABILITIES: - color-type 3 (palette / PLTE chunk): IMPLEMENTED (PLTE walker + post-defilter expansion to packed RGB; gate-proven by nx_boxtex_gate T1 on Khronos BoxTextured, 66 distinct colours). This line read -queued, low-priority- until 2026-08-05. That stale claim was COPIED into nx_image_gray.nx, nx_image_index.nx, nx_image_grade_v0.nx and a USER-VISIBLE error string in nx_uiq_visual_lib.nx, so a shipped capability kept being re-scoped as unbuilt work. A STALE COMMENT IS A DEFECT: it costs the same as a missing feature and hides longer. (most modern PNGs use RGB/RGBA; palette is rare for new content but common in legacy assets) - Adam7 interlacing: IMPLEMENTED v4 2026-08-05 (all 7 passes, depths 1/2/4/8, gate nx_png_adam7_gate 5/5; interlaced 16-bit stays sealed as NX_PNG_ERR_UNSUPPORTED_INTERLACE -- rare, and no consumer of the linear 16-bit two-byte contract is interlaced) - 1 / 2 / 4 bit-depth sub-byte packing: IMPLEMENTED v3 2026-07-24 (gray scales to 0..255, palette indices stay raw for PLTE) - 16-bit-depth high-byte handling: scanlines are processed as bytes; 16-bit samples are filtered correctly per spec but high/low byte split is NOT presented as native u16 -- caller reads two bytes per sample. - ancillary chunks (tEXt / zTXt / iTXt / pHYs / gAMA / cHRM / sRGB / iCCP / etc.) are skipped (CRC validated, contents discarded); queued as nx_png_ancillary.nx Per cardinal `feedback-no-skip-paths-as-error-codes`: this primitive ships with COMPLETENESS=PARTIAL so callers know exactly what's covered. Caller can test for NX_PNG_ERR_UNSUPPORTED_* to detect when they hit one of the queued capabilities. PNG file structure: 8-byte signature: 89 50 4E 47 0D 0A 1A 0A sequence of chunks; first must be IHDR, last must be IEND each chunk: 4 bytes BE data length 4 bytes chunk type (ASCII) N bytes data 4 bytes BE CRC-32 of (type + data)

dependencies 5 imports · 32 importers

nx_syscalls.nx nx_runtime.nx nx_tier.nx nx_zlib_wrap.nx nx_crc32.nx nx_png_decoder.nx _codec_real_med.nx _imgscramble.nx nx_apng_decode.nx nx_charjudge.nx nx_editjudge_lib.nx nx_galx_thumb.nx nx_galx_thumb_oneshot.nx nx_galx_upscale.nx nx_grade.nx nx_ico_decode.nx

diagram shows first 10 each side; +0 more imports, +22 more importers in the complete lists below.

imports: nx_syscalls.nxnx_runtime.nxnx_tier.nxnx_zlib_wrap.nxnx_crc32.nx

imported by: _codec_real_med.nx_imgscramble.nxnx_apng_decode.nxnx_charjudge.nxnx_editjudge_lib.nxnx_galx_thumb.nxnx_galx_thumb_oneshot.nxnx_galx_upscale.nxnx_grade.nxnx_ico_decode.nxnx_image_grade_v0.nxnx_image_grade_v1.nxnx_image_grade_v2.nxnx_image_symmetry_lib.nxnx_img_adapt_gate.nxnx_img_bytes_to_rgb.nxnx_img_convert_loop_gate.nxnx_img_print.nxnx_lbp_imgio.nxnx_media_convert.nxnx_media_convert_jpeg_gate.nxnx_media_index.nxnx_page_verify.nxnx_png_adam7_gate.nxnx_png_dynamic_huffman_test.nxnx_png_lum.nxnx_png_probe.nxnx_png_real_smoke.nxnx_refbench_lib.nxnx_timeline_demo.nxnx_visual_diff.nxnx_xfade_demo.nx

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main sys_mmap _png_check_signature _png_n_channels _png_bytes_per_pixel _png_n_channels ↻ _png_paeth _png_unfilter_scanline _png_paeth ↻ nx_png_decode sys_mmap ↻ _png_check_signature ↻ _png_read_u32_be nx_crc32 nx_crc32_update nx_crc32_init nx_crc32_table_at _png_n_channels ↻ _png_bytes_per_pixel ↻ _png_a7_expected _png_a7_col0 _png_a7_coli _png_a7_row0 _png_a7_rowi nx_zlib_inflate sys_mmap ↻ nx_deflate_inflate sys_mmap ↻ nx_bitstream_alloc sys_mmap ↻ _deflate_inflate_block nx_bitstream_read_lsb nx_bitstream_bits_remainin _bs_peek_byte nx_bitstream_byte_align nx_bitstream_read_byte_ali nx_bitstream_byte_align ↻ _deflate_build_static_litl sys_mmap ↻ nx_huffman_build

structs

108struct NxPngHeader
123struct NxPngResult

consts

67const NX_MAGIC_2026: i64 = 2026
68const NX_MAGIC_67108864: i64 = 67108864
69const NX_MAGIC_262144: i64 = 262144
73const NX_PNG_OK: nx_int = 0
74const NX_PNG_ERR_TOO_SHORT: nx_int = 1
75const NX_PNG_ERR_BAD_SIGNATURE: nx_int = 2
76const NX_PNG_ERR_NO_IHDR: nx_int = 3
77const NX_PNG_ERR_BAD_IHDR: nx_int = 4
78const NX_PNG_ERR_BAD_CRC: nx_int = 5
79const NX_PNG_ERR_UNSUPPORTED_COLOR: nx_int = 6 // partial-capability
80const NX_PNG_ERR_UNSUPPORTED_DEPTH: nx_int = 7 // partial-capability
81const NX_PNG_ERR_UNSUPPORTED_INTERLACE: nx_int = 8 // partial-capability
82const NX_PNG_ERR_DECOMPRESS: nx_int = 9
83const NX_PNG_ERR_BAD_FILTER: nx_int = 10
84const NX_PNG_ERR_SCANLINE_LEN: nx_int = 11
85const NX_PNG_ERR_NO_IEND: nx_int = 12
89const NX_PNG_FILTER_NONE: nx_int = 0
90const NX_PNG_FILTER_SUB: nx_int = 1
91const NX_PNG_FILTER_UP: nx_int = 2
92const NX_PNG_FILTER_AVERAGE: nx_int = 3
93const NX_PNG_FILTER_PAETH: nx_int = 4
97const NX_PNG_COLOR_GRAY: nx_int = 0
98const NX_PNG_COLOR_RGB: nx_int = 2
99const NX_PNG_COLOR_PALETTE: nx_int = 3 // unsupported v1
100const NX_PNG_COLOR_GRAY_ALPHA: nx_int = 4
101const NX_PNG_COLOR_RGBA: nx_int = 6
118const NX_PNG_HEADER_BYTES: nx_size = 56
132const NX_PNG_RESULT_BYTES: nx_size = 48 // 6 x 8B fields (was 40 = one field short; mmap page-rounding hid it)

functions

136func _png_read_u32_be(buf: *u8, off: nx_int) -> nx_int
called by 1: nx_png_decode
146func _png_check_signature(buf: *u8, n: nx_int) -> nx_int
called by 2: nx_png_decodemain
161func _png_n_channels(color_type: nx_int) -> nx_int
173func _png_bytes_per_pixel(color_type: nx_int, bit_depth: nx_int) -> nx_int
called by 2: nx_png_decodemain calls 1: _png_n_channels
183func _png_paeth(a: nx_int, b: nx_int, c: nx_int) -> nx_int
206func _png_unfilter_scanline(
294func _png_a7_row0(p: nx_int) -> nx_int { if p==0 {return 0} if p==1 {return 0} if p==2 {return 4} if p==3 {return 0} if p==4 {return 2} if p==5 {return 0} return 1 }
295func _png_a7_col0(p: nx_int) -> nx_int { if p==0 {return 0} if p==1 {return 4} if p==2 {return 0} if p==3 {return 2} if p==4 {return 0} if p==5 {return 1} return 0 }
296func _png_a7_rowi(p: nx_int) -> nx_int { if p==0 {return 8} if p==1 {return 8} if p==2 {return 8} if p==3 {return 4} if p==4 {return 4} if p==5 {return 2} return 2 }
297func _png_a7_coli(p: nx_int) -> nx_int { if p==0 {return 8} if p==1 {return 8} if p==2 {return 4} if p==3 {return 4} if p==4 {return 2} if p==5 {return 2} return 1 }
301func _png_a7_expected(w: nx_int, h: nx_int, nch: nx_int, bd: nx_int) -> nx_int
321func _png_a7_deinterlace(zdata: *u8, w: nx_int, h: nx_int, nch: nx_int, bd: nx_int,
382func nx_png_decode(input: *u8, input_size: nx_int) -> *NxPngResult
713func main() -> nx_int