image/jpeg.nu — baseline (sequential DCT, Huffman) JPEG decode.
Supports the baseline JPEGs real encoders emit: 8-bit precision, Huffman coding, 1 component (greyscale) or 3 (YCbCr → RGB), any 4:4:4 / 4:2:2 / 4:2:0 / 4:1:1 subsampling, and restart intervals (DRI/RSTn). Chroma planes are box-upsampled and a separable float IDCT is used, so output matches a reference decoder (libjpeg) to within IDCT/upsampling rounding — JPEG is lossy and the spec permits IDCT variation, so this is not bit-exact.
Not supported (clean None, never an out-of-bounds read): progressive JPEG, arithmetic coding, 12-bit, and 4-component (CMYK/YCCK).
: Jpeg: Jpeg {
( Vec u ) buf i len
i width i height i ncomp
( Vec i ) cid ( Vec i ) chf ( Vec i ) cvf ( Vec i ) ctq ( Vec i ) ctd ( Vec i ) cta ( Vec i ) cpred
i hmax i vmax i restart
( Vec i ) qt
( Vec i ) hmin ( Vec i ) hmaxc ( Vec i ) hptr ( Vec i ) hvals
( Vec f ) idct_a ( Vec i ) zz
i bpos i bbuf i bcnt i marker
b ok
}
@ jpeg_decode ( Vec u ) buf → ?Imageimage — pure-NURL image codecs. One include for the whole package: the Image raster, PPM (P5/P6), PNG decode + encode, and file load/save with format sniffing. (Baseline JPEG decode is planned as a later milestone.)
$ deps/image/src/image.nu ?? ( image_load photo.png ) { T im → { // … use im (width/height/channels/data) … ( image_save_png out.png im ) ( image_free im ) } F → { ( nurleprintln decode failed ) } }
@ image_decode ( Vec u ) buf → ?ImageDecode by sniffing the magic bytes: PNG signature → png_decode, JPEG SOI (FF D8) → jpeg_decode, P → PPM.
@ image_load s path → ?ImageLoad and decode a file. None on an I/O error or an unrecognised/malformed format.
@ image_save_png s path Image im → b@ image_save_ppm s path Image im → bimage/core.nu — the Image type, byte helpers, and PPM (P5/P6).
An Image is a tightly-packed, row-major, 8-bit-per-channel raster: channels 1 = grayscale, 3 = RGB, 4 = RGBA. data holds widthheightchannels bytes. Every codec in the package decodes into, and encodes from, this one representation.
: Image: Image {
i width
i height
i channels
( Vec u ) data
}
@ image_new i w i h i ch → ImageA zero-filled image of the given geometry.
@ image_of i w i h i ch ( Vec u ) data → ImageAdopt an existing byte buffer (moved in; not copied).
@ image_free Image im → v@ image_width Image im → i@ image_height Image im → i@ image_channels Image im → i@ image_get Image im i x i y i c → i@ image_set Image im i x i y i c i v → v@ ppm_decode ( Vec u ) buf → ?Image@ ppm_encode Image im → ( Vec u )Encode as binary PPM: 3/4-channel → P6 (alpha dropped), 1-channel → P5.
image/png.nu — PNG decode + encode over the stdlib DEFLATE codec.
Decode: 8-bit depth, non-interlaced, colour types 0 (grey), 2 (RGB), 3 (palette → expanded to RGB), 4 (grey+alpha), 6 (RGBA). Reconstructs all five scanline filters. Encode: 8-bit, non-interlaced, filter 0, colour type chosen from the image's channel count. Lossless — a decode→encode→decode round-trip reproduces the pixels exactly.
Not yet: interlaced (Adam7) images, bit depths other than 8, and tRNS transparency on palette/grey images. png_decode returns None on those (and on malformed input); the codec never reads out of bounds.
@ png_decode ( Vec u ) buf → ?Image@ png_encode Image im → ( Vec u )Encode an image as a non-interlaced, filter-0, 8-bit PNG.