41static const char*
const s_tag =
"jof_prod";
47typedef enum : uint32_t {
65typedef enum : uint8_t {
91 if ((bump ==
nullptr) || (len == 0U)) {
95 const size_t aligned = (bump->
off + mask) & ~mask;
96 if ((aligned > bump->
cap) || (len > (bump->
cap - aligned))) {
99 bump->
off = aligned + len;
100 return &bump->
base[aligned];
168 if ((uint64_t)len > ((uint64_t)UINT32_MAX - (uint64_t)st->
written)) {
189 const size_t take = (cap < left) ? cap : left;
255 const uint64_t band_bytes = (uint64_t)st->
w * (uint64_t)th * (uint64_t)st->
bpp;
256 const uint32_t tw_eff = (tw < st->
w) ? tw : st->
w;
257 const uint32_t th_eff = (th < st->
h) ? th : st->
h;
258 const uint64_t stage_bytes = (uint64_t)tw_eff * (uint64_t)th_eff * (uint64_t)st->
bpp;
260 if ((band_bytes > (uint64_t)UINT32_MAX) || (stage_bytes > (uint64_t)UINT32_MAX)) {
266 if ((st->
band ==
nullptr) || (st->
stage ==
nullptr) || (st->
idx ==
nullptr)) {
272 if (st->
cmp ==
nullptr) {
307 if ((width == 0U) || (width > st->
cap_w) || (height == 0U) || (height > st->
cap_h)) {
356 const uint8_t* out_bytes = st->
stage;
357 uint32_t out_len = payload;
398 const uint32_t stride = (uint32_t)st->
w * (uint32_t)st->
bpp;
399 for (uint32_t tx = 0U; tx < (uint32_t)st->
tile_cols; tx++) {
400 const uint32_t x0 = tx * (uint32_t)st->
cfg->
tile_w;
401 const uint32_t tw = (((uint32_t)st->
w - x0) < (uint32_t)st->
cfg->
tile_w)
402 ? ((uint32_t)st->
w - x0)
404 const uint32_t row_bytes = tw * (uint32_t)st->
bpp;
405 for (uint32_t r = 0U; r < th; r++) {
406 (void)
memcpy(&st->
stage[(
size_t)r * (
size_t)row_bytes],
407 &st->
band[((
size_t)r * (
size_t)stride) + ((
size_t)x0 * (
size_t)st->
bpp)],
427 if ((st->
geom_done == 0U) || (width != st->
w) || (channels != st->
bpp)) {
431 if ((nrows == 0U) || ((uint32_t)y0 != st->
rows_seen) ||
432 (((uint32_t)y0 + (uint32_t)nrows) > (uint32_t)st->
h)) {
435 const uint32_t stride = (uint32_t)st->
w * (uint32_t)st->
bpp;
436 const uint8_t* src = px;
437 uint32_t left = nrows;
440 const uint32_t take = (left < room) ? left : room;
443 (
size_t)take * (
size_t)stride);
446 src = &src[(size_t)take * (
size_t)stride];
487 uint16_t stripe_rows,
488 uint8_t** out_stripe,
489 uint32_t* out_stripe_cap)
496 const uint32_t cap = (uint32_t)width * (uint32_t)stripe_rows * (uint32_t)channels;
498 if (buf ==
nullptr) {
502 *out_stripe_cap = cap;
533 const uint32_t index_off = st->
written;
590uint32_t
jof_work_bytes(uint16_t max_width, uint16_t max_height, uint16_t tile_w, uint16_t tile_h)
592 if ((max_width == 0U) || ((uint32_t)max_width > (uint32_t)
k_jof_max_dim) || (max_height == 0U) ||
596 if ((tile_w == 0U) || (tile_h == 0U)) {
599 const uint64_t cols = ((uint64_t)max_width + tile_w - 1U) / tile_w;
600 const uint64_t rows = ((uint64_t)max_height + tile_h - 1U) / tile_h;
605 const uint64_t jpeg_set =
608 const uint64_t png_set = (uint64_t)
sizeof(tinfl_decompressor) + (uint64_t)
k_jof_png_ring +
610 const uint64_t dec_set = (jpeg_set > png_set) ? jpeg_set : png_set;
611 const uint64_t band = (uint64_t)max_width * (uint64_t)tile_h * bpp;
612 const uint64_t tw_eff =
613 ((uint64_t)tile_w < (uint64_t)max_width) ? (uint64_t)tile_w : (uint64_t)max_width;
614 const uint64_t th_eff =
615 ((uint64_t)tile_h < (uint64_t)max_height) ? (uint64_t)tile_h : (uint64_t)max_height;
616 const uint64_t stage = tw_eff * th_eff * bpp;
620 const uint64_t total =
622 if ((stage > (uint64_t)UINT32_MAX) || (total > (uint64_t)UINT32_MAX)) {
625 return (uint32_t)total;
649 (void)
memset(st, 0,
sizeof(*st));
662 if (st->
dfl ==
nullptr) {
688 size_t head_len = 0U;
731 if (window ==
nullptr) {
890 *out_w = (uint16_t)w;
891 *out_h = (uint16_t)h;
987 .head_len =
sizeof(head),
@ k_jof_le_sh16
16-bit shift.
@ k_jof_le_sh24
24-bit shift.
@ k_jof_le_sh8
8-bit shift.
JOF band-tile atlas: the display-native normalized image format (#231, shared with the longstrip scro...
@ k_jof_ofs_tile_count
Header: u32 tile count.
@ k_jof_index_entry
Bytes per tile-index entry.
@ k_jof_magic_len
Magic string length (both ends).
@ k_jof_footer_bytes
Footer length.
@ k_jof_ftr_total_size
Footer: u32 total atlas size.
@ k_jof_hdr_bytes
Header length.
@ k_jof_ftr_magic
Footer: magic "JOFE".
@ k_jof_ftr_index_off
Footer: u32 index offset.
@ k_jof_ofs_tile_h
Header: u16 tile height.
@ k_jof_ofs_codec
Header: u8 tile codec.
@ k_jof_idx_ofs_length
Index entry: u32 tile length.
@ k_jof_ofs_height
Header: u16 image height.
@ k_jof_ofs_tile_w
Header: u16 tile width.
@ k_jof_ofs_width
Header: u16 image width.
@ k_jof_ftr_tile_count
Footer: u32 tile count.
@ k_jof_ofs_bpp
Header: u8 bytes per pixel.
@ k_jof_idx_ofs_offset
Index entry: u32 tile offset.
@ k_jof_bpp_max
Max bytes per pixel.
@ k_jof_max_dim
Max image width/height, pixels.
@ k_jof_max_tiles
Max tiles per atlas.
@ k_jof_codec_deflate
Tile stream is one raw-DEFLATE run.
uint32_t jof_stored_bound(uint32_t raw_bytes)
Worst-case stored-tile byte bound for scratch/cell sizing.
Module-private seams shared by the producer translation units.
ra8_err_t priv_jof_on_geom(void *ctx, uint16_t width, uint16_t height, uint8_t channels)
Bind the source geometry: validate caps, carve buffers, emit header.
@ k_jof_bump_align
Every carve is 8-byte aligned.
@ k_jof_carve_slack
Alignment slack folded into every arena sizing.
ra8_err_t priv_jof_on_rows(void *ctx, const uint8_t *px, uint16_t width, uint16_t y0, uint16_t nrows, uint8_t channels)
Row sink shared by every decoder arm: accumulate, flush full bands.
ra8_err_t priv_jof_png_rows(jof_pull_fn pull, void *pull_ctx, jof_bump_t *bump, uint16_t max_w, uint16_t max_h, jof_geom_fn on_geom, jof_rows_fn on_rows, void *cb_ctx)
Streaming PNG scanline decode: pull bytes in, emit rows in order.
ra8_err_t priv_jof_webp_transcode(jof_prod_state_t *st, jof_prefix_pull_t *pfx)
Transcode a WebP source into the JOF tile path (whole-frame, #290).
ra8_err_t priv_jof_prefix_pull(void *ctx, uint8_t *buf, size_t cap, size_t *got)
Pull adapter: replay the sniffed head, then delegate to the source.
static ra8_err_t internal_check_cfg(const jof_produce_cfg_t *cfg)
Validate the caller configuration's non-pointer invariants.
static ra8_err_t internal_sniff_head(const jof_produce_cfg_t *cfg, uint8_t *head)
Pull the sniff head (both formats need at least these bytes).
ra8_err_t priv_jof_on_geom(void *ctx, uint16_t width, uint16_t height, uint8_t channels)
Bind the source geometry: validate caps, carve buffers, emit header.
static ra8_err_t internal_finish(jof_prod_state_t *st, jof_info_t *out_info)
Emit the tile index and footer, then fill the caller's info.
jof_png_signature_t
Fixed non-ASCII bytes in the PNG signature.
@ k_jof_png_sig_cr
Carriage return byte.
@ k_jof_png_sig_sub
DOS EOF byte.
@ k_jof_png_sig_lf
Line feed byte.
@ k_jof_png_sig_high
High-bit signature byte.
static ra8_err_t internal_carve_pixel_path(jof_prod_state_t *st)
Carve the band, stage, index and compressed-tile buffers.
static ra8_err_t internal_produce_args_ok(const jof_produce_cfg_t *cfg, const jof_info_t *out_info)
Reject any NULL jof_produce argument or seam.
void * priv_jof_bump_take(jof_bump_t *bump, size_t len)
Implementation of priv_jof_bump_take() – aligned linear carve.
static ra8_err_t internal_emit_header(jof_prod_state_t *st)
Serialize + sink the 32-byte JOF header from the bound geometry.
static const uint8_t s_prod_webp_riff[k_jof_magic_len]
WebP RIFF container tag (source head bytes 0..3).
ra8_err_t priv_jof_on_rows(void *ctx, const uint8_t *px, uint16_t width, uint16_t y0, uint16_t nrows, uint8_t channels)
Row sink shared by every decoder arm: accumulate, flush full bands.
ra8_err_t jof_probe_dims(const uint8_t *data, size_t len, uint16_t *out_w, uint16_t *out_h)
Read a source image's pixel dimensions without decoding its body.
static ra8_err_t internal_probe_sniff(const uint8_t *data, size_t len, uint16_t *out_w, uint16_t *out_h)
Sniff the container, read its declared geometry and range-check it.
static ra8_err_t internal_epilogue(jof_prod_state_t *st, jof_info_t *out_info)
Post-decode checks, final band flush and trailer emission.
static ra8_err_t internal_png_dims(const uint8_t *data, size_t len, uint32_t *out_w, uint32_t *out_h)
Read the pixel geometry out of a PNG IHDR chunk.
jof_prod_const_t
Producer sizing and sniffing constants.
@ k_jof_byte_mask
Low-byte mask.
@ k_jof_png_ihdr_h
PNG IHDR height field offset (big-endian).
@ k_jof_jpeg_soi_second
JPEG SOI second byte.
@ k_jof_png_ring
PNG inflate ring carve (bytes).
@ k_jof_png_inbuf
PNG input-buffer carve (bytes).
@ k_jof_png_ihdr_w
PNG IHDR width field offset (big-endian).
@ k_jof_webp_fourcc_ofs
Offset of the "WEBP" fourCC.
@ k_jof_png_sig_len
PNG signature length.
@ k_jof_png_ihdr_end
Bytes needed to read both IHDR fields.
@ k_jof_jpeg_soi_first
JPEG SOI first byte.
@ k_jof_sniff_bytes
Magic bytes pulled up front (WebP needs 12).
static ra8_err_t internal_jpeg_geom(void *ctx, uint16_t width, uint16_t height, uint8_t channels, uint16_t stripe_rows, uint8_t **out_stripe, uint32_t *out_stripe_cap)
JPEG geometry adapter: bind geometry, then carve the MCU stripe.
static ra8_err_t internal_encode_tile(jof_prod_state_t *st, uint32_t payload)
Encode one packed tile payload and append it to the atlas.
static ra8_err_t internal_flush_band(jof_prod_state_t *st, uint32_t th)
Cut the accumulated band into tiles and append each to the atlas.
static void internal_wr_u16(uint8_t *buf, uint16_t v)
Store a uint16 little-endian at buf.
static const uint8_t s_prod_png_sig[k_jof_png_sig_len]
PNG signature for source sniffing (mirrors the PNG decoder unit).
static void internal_wr_u32(uint8_t *buf, uint32_t v)
Store a uint32 little-endian at buf.
static ra8_err_t internal_sink(jof_prod_state_t *st, const uint8_t *buf, size_t len)
Append bytes to the caller sink, tracking the atlas offset.
static ra8_err_t internal_dispatch(jof_prod_state_t *st, const uint8_t *head, jof_prefix_pull_t *pfx)
Dispatch the sniffed source to the matching decoder.
static const uint8_t s_prod_webp_webp[k_jof_magic_len]
WebP form-type fourCC (source head bytes 8..11).
static bool internal_is_webp(const uint8_t *data)
True if the sniff window carries the WebP RIFF container magic.
static ra8_err_t internal_init_state(jof_prod_state_t *st, const jof_produce_cfg_t *cfg)
Reset the transcode state and carve the deflate scratch.
static uint32_t internal_rd_be32(const uint8_t *buf)
Read a big-endian uint32 (PNG stores its IHDR fields big-endian).
uint32_t jof_work_bytes(uint16_t max_width, uint16_t max_height, uint16_t tile_w, uint16_t tile_h)
Compute the work-arena size the producer needs for given caps.
ra8_err_t jof_produce(const jof_produce_cfg_t *cfg, jof_info_t *out_info)
Transcode one encoded JPEG/PNG/WebP source into a JOF atlas (#231, #290).
ra8_err_t priv_jof_prefix_pull(void *ctx, uint8_t *buf, size_t cap, size_t *got)
Pull adapter: replay the sniffed head, then delegate to the source.
Import-time transcode producer: JPEG/PNG/WebP -> JOF band-tile atlas in bounded RAM (#231,...
static const char * s_tag
Logging / check tag.
Annotation-attribute framework macros for ra8-firmware.
#define RA8_PRIV
Module-private helper: shared across TUs but only inside one library.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Validation and Error-Checking Macros for ra8-firmware.
#define RA8_CHECK_NULL_PTR(ptr, tag, message)
Reject nullptr pointer, returning k_ra8_err_null_ptr.
App-domain DEFLATE compress / decompress (zero-heap, firmware-safe).
@ k_ra8_compress_scratch_bytes
Minimum compress scratch size (one miniz tdefl_compressor).
ra8_err_t ra8_compress(const uint8_t *src, uint32_t src_len, uint8_t *out, uint32_t out_cap, void *scratch, uint32_t scratch_len, uint32_t *out_len)
Raw-DEFLATE compress src into out.
Error Code Definitions for ra8-firmware.
@ k_ra8_err_not_supported
Requested feature not compiled in, not wired, or not supported by this MCU variant.
@ k_ra8_err_invalid_arg
Invalid function argument.
@ k_ra8_err_invalid_state
Module in wrong state for requested operation.
@ k_ra8_err_validation_failed
Validation rule failed (caller-supplied invariant not satisfied).
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
@ k_ra8_err_protocol_error
Protocol-level error (e.g.
@ k_ra8_err_invalid_size
Invalid size parameter (too large, too small, or misaligned).
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
void * memset(void *dst, int value, size_t n)
Fill memory with a constant byte value.
int memcmp(const void *a, const void *b, size_t n)
Compare bytes in two memory areas.
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
Pure-software baseline JPEG (ISO/IEC 10918-1 / ITU-T T.81) codec.
@ k_ra8_jpeg_sw_stream_mcu_rows_max
Max rows per stripe (4:2:0).
@ k_ra8_jpeg_sw_stream_min_window
Minimum window bytes.
ra8_err_t ra8_jpeg_sw_decode_stripes(ra8_jpeg_sw_pull_fn pull, void *pull_ctx, uint8_t *window, uint32_t window_cap, ra8_jpeg_sw_geom_fn on_geom, ra8_jpeg_sw_rows_fn on_rows, void *cb_ctx)
Decode a baseline JPEG in bounded RAM, one MCU-row stripe at a time.
ra8_err_t ra8_jpeg_sw_get_dimensions(const uint8_t *jpeg_buf, uint32_t jpeg_len, uint16_t *out_w, uint16_t *out_h)
Parse the SOF0 marker of a JPEG stream and report its image dimensions without performing entropy dec...
Lightweight Logging Interface for ra8-firmware.
Zero-heap WebP (VP8 / VP8L) decode facade over the vendored libwebp.
ra8_err_t ra8_webp_get_info(const uint8_t *data, size_t size, uint32_t *out_w, uint32_t *out_h)
Read a WebP header's pixel dimensions without decoding the body.
Linear (bump) allocator over the caller's work arena.
size_t off
First free byte.
uint8_t * base
Arena base (caller's work buffer).
size_t cap
Arena capacity, bytes.
Parsed + validated geometry of one JOF atlas.
uint8_t bpp
Bytes per pixel (1, 3 or 4).
uint8_t codec
jof_codec_t member.
uint16_t tile_w
Tile width, pixels.
uint16_t width
Image width, pixels.
uint32_t index_off
Absolute byte offset of the tile index.
uint16_t tile_rows
Ceil(height / tile_h) tile rows.
uint16_t tile_h
Tile height, pixels.
uint32_t tile_count
Total tiles (== cols * rows).
uint16_t height
Image height, pixels.
uint32_t total_size
Whole atlas byte length (footer included).
uint16_t tile_cols
Ceil(width / tile_w) tile columns.
Pull adapter that replays the sniffed head bytes, then delegates.
size_t head_len
Sniffed byte count.
const uint8_t * head
Sniffed bytes to replay.
void * inner_ctx
Context for the source.
jof_pull_fn inner
Real source.
Whole transcode state (module-static instance in the producer TU).
uint32_t tiles_done
Tiles encoded + recorded so far.
uint32_t cmp_cap
Capacity of cmp.
uint32_t written
Atlas bytes sunk so far.
uint8_t * cmp
One encoded tile (deflate codec).
uint8_t geom_done
1 once geometry was bound.
uint32_t band_fill
Rows currently in the band.
jof_bump_t bump_store
Arena allocator state.
const jof_produce_cfg_t * cfg
Caller configuration.
uint8_t * idx
Tile index bytes (8 per tile).
uint8_t * stage
One packed tile payload.
uint8_t bpp
Output bytes per pixel.
uint16_t w
Source width, pixels.
uint16_t cap_h
Effective height cap.
uint16_t tile_cols
Tile grid columns.
uint32_t rows_seen
Decoded rows accumulated so far.
uint32_t dfl_len
Scratch length (0 for raw codec).
uint16_t tile_rows
Tile grid rows.
uint32_t tile_count
Total tiles (cols * rows).
jof_bump_t * bump
Arena allocator (owned).
uint8_t * dfl
Deflate compressor scratch.
uint8_t * band
One tile row of decoded pixels.
uint16_t h
Source height, pixels.
uint16_t cap_w
Effective width cap.
Producer configuration: source, sink, tile geometry and work arena.
uint16_t max_width
Width budget cap (0 = format cap).
void * pull_ctx
Context for pull.
uint8_t codec
jof_codec_t member.
uint16_t max_height
Height budget cap (0 = format cap).
jof_sink_fn sink
Atlas byte sink (append-only).
jof_pull_fn pull
Encoded-source byte stream.
void * sink_ctx
Context for sink.
uint16_t tile_h
Tile height, pixels (>= 1).
size_t work_cap
Arena size; see jof_work_bytes().
uint16_t tile_w
Tile width, pixels (>= 1).