ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
comic_tiles.c
Go to the documentation of this file.
1
29
30/* Compile the tile reader only where the ra8_mem tile cache and the JOF atlas
31 * reader/producer are on the include path (tiling comic apps + the host test
32 * build). Otherwise empty. */
33#if __has_include("ra8_tile_cache.h") && __has_include("jof.h")
34
35#include "comic_tiles.h"
36
37#include <stddef.h>
38#include <stdint.h>
39#include <string.h>
40
41#include "jof.h"
42#include "jof_produce.h"
43#include "ra8_attributes.h"
44#include "ra8_check.h"
45#include "ra8_err.h"
46#include "ra8_tile_cache.h"
47
49static const char* const s_tag = "comic_tiles";
50
60typedef struct {
61 const uint8_t* d;
62 size_t n;
63 size_t off;
64} comic_tiles_pull_t;
65
83RA8_INTERNAL static ra8_err_t internal_mem_pull(void* ctx, uint8_t* buf, size_t cap, size_t* got)
84{
85 comic_tiles_pull_t* p = (comic_tiles_pull_t*)ctx;
86 const size_t remain = p->n - p->off;
87 const size_t k = (cap < remain) ? cap : remain;
88 if (k > 0U) {
89 (void)memcpy(buf, &p->d[p->off], k);
90 }
91 p->off += k;
92 *got = k;
93 return k_ra8_ok;
94}
95
118 const ra8_tile_key_t* key,
119 uint8_t* cell,
120 uint32_t cell_bytes,
121 uint16_t* out_w,
122 uint16_t* out_h)
123{
126 &r->store,
127 &r->info,
128 key->tile_x,
129 key->tile_y,
130 r->scratch,
131 r->scratch_cap,
132 cell,
133 cell_bytes,
134 out_w,
135 out_h);
136 if (err == k_ra8_err_invalid_size) {
137 return k_ra8_err_no_mem; /* tile exceeds the cell / scratch budget */
138 }
139 return err;
140}
141
142ra8_err_t comic_tiles_footprint(const uint8_t* enc,
143 size_t len,
144 uint16_t* out_w,
145 uint16_t* out_h,
146 uint64_t* out_decoded_bytes)
147{
148 RA8_CHECK_NULL_PTR(enc, s_tag, "footprint: null enc");
149 RA8_CHECK_NULL_PTR(out_w, s_tag, "footprint: null out_w");
150 RA8_CHECK_NULL_PTR(out_h, s_tag, "footprint: null out_h");
151 RA8_CHECK_NULL_PTR(out_decoded_bytes, s_tag, "footprint: null out_decoded_bytes");
152 if (len == 0U) {
154 }
155 uint16_t w = 0U;
156 uint16_t h = 0U;
157 const ra8_err_t err = jof_probe_dims(enc, len, &w, &h);
158 if (err != k_ra8_ok) {
159 return err;
160 }
161 *out_w = w;
162 *out_h = h;
163 *out_decoded_bytes = (uint64_t)w * (uint64_t)h * (uint64_t)k_comic_tiles_decoded_bpp;
164 return k_ra8_ok;
165}
166
167bool comic_tiles_over_budget(uint64_t decoded_bytes, uint64_t budget_bytes)
168{
169 return (budget_bytes != 0U) && (decoded_bytes > budget_bytes);
170}
171
173 const ra8_tile_cache_cfg_t* storage,
174 uint8_t* scratch,
175 uint32_t scratch_cap)
176{
177 RA8_CHECK_NULL_PTR(r, s_tag, "init: null r");
178 RA8_CHECK_NULL_PTR(storage, s_tag, "init: null storage");
179 (void)memset(r, 0, sizeof(*r));
180 r->scratch = scratch;
181 r->scratch_cap = (scratch != nullptr) ? scratch_cap : 0U;
182 ra8_tile_cache_cfg_t cfg = *storage;
184 cfg.decode_ctx = r;
185 return ra8_tile_cache_init(&r->cache, &cfg);
186}
187
206RA8_INTERNAL static ra8_err_t internal_import_args_ok(const comic_tile_reader_t* r,
207 const uint8_t* enc,
208 const comic_tiles_import_cfg_t* cfg)
209{
210 RA8_CHECK_NULL_PTR(r, s_tag, "import: null r");
211 RA8_CHECK_NULL_PTR(enc, s_tag, "import: null enc");
212 RA8_CHECK_NULL_PTR(cfg, s_tag, "import: null cfg");
213 RA8_CHECK_NULL_PTR(cfg->work, s_tag, "import: null work");
214 RA8_CHECK_NULL_PTR(cfg->atlas, s_tag, "import: null atlas");
215 return k_ra8_ok;
216}
217
237RA8_INTERNAL static ra8_err_t internal_transcode(comic_tile_reader_t* r,
238 const uint8_t* enc,
239 size_t enc_len,
240 const comic_tiles_import_cfg_t* cfg)
241{
242 r->store = (jof_memstore_t){.buf = cfg->atlas, .cap = cfg->atlas_cap, .len = 0U};
243 comic_tiles_pull_t pull = {.d = enc, .n = enc_len, .off = 0U};
244 const jof_produce_cfg_t pcfg = {
245 .pull = internal_mem_pull,
246 .pull_ctx = &pull,
247 .sink = jof_memstore_sink,
248 .sink_ctx = &r->store,
249 .tile_w = cfg->tile_w,
250 .tile_h = cfg->tile_h,
251 .codec = cfg->codec,
252 .max_width = cfg->max_width,
253 .max_height = cfg->max_height,
254 .work = cfg->work,
255 .work_cap = cfg->work_cap,
256 .webp_work = cfg->webp_work,
257 .webp_work_cap = cfg->webp_work_cap,
258 };
259 jof_info_t produced = {};
260 const ra8_err_t perr = jof_produce(&pcfg, &produced);
261 if (perr != k_ra8_ok) {
262 return perr;
263 }
264 return jof_parse(jof_memstore_pread, &r->store, (uint64_t)r->store.len, &r->info);
265}
266
268 const uint8_t* enc,
269 size_t enc_len,
270 const comic_tiles_import_cfg_t* cfg)
271{
272 const ra8_err_t nz = internal_import_args_ok(r, enc, cfg);
273 if (nz != k_ra8_ok) {
274 return nz;
275 }
276 if (enc_len == 0U) {
278 }
279 r->bound = false; /* invalidate first: any error leaves no bound page */
280 const ra8_err_t err = internal_transcode(r, enc, enc_len, cfg);
281 if (err != k_ra8_ok) {
282 return err;
283 }
284 r->epoch += 1U;
285 r->bound = true;
286 return k_ra8_ok;
287}
288
290{
291 RA8_CHECK_NULL_PTR(r, s_tag, "info: null r");
292 RA8_CHECK_NULL_PTR(out_info, s_tag, "info: null out_info");
293 if (!r->bound) {
295 }
296 *out_info = r->info;
297 return k_ra8_ok;
298}
299
301comic_tiles_tile(comic_tile_reader_t* r, uint16_t tile_x, uint16_t tile_y, ra8_tile_t* out_tile)
302{
303 RA8_CHECK_NULL_PTR(r, s_tag, "tile: null r");
304 RA8_CHECK_NULL_PTR(out_tile, s_tag, "tile: null out_tile");
305 if (!r->bound) {
307 }
308 if (tile_x >= r->info.tile_cols) {
310 }
311 if (tile_y >= r->info.tile_rows) {
313 }
314 const ra8_tile_key_t key = {.image_id = r->epoch,
315 .tile_x = tile_x,
316 .tile_y = tile_y,
317 .zoom = 0U,
318 .reserved = 0U};
319 return ra8_tile_cache_get(&r->cache, &key, out_tile);
320}
321
322ra8_err_t comic_tiles_release(comic_tile_reader_t* r, const uint8_t* pixels)
323{
324 RA8_CHECK_NULL_PTR(r, s_tag, "release: null r");
325 RA8_CHECK_NULL_PTR(pixels, s_tag, "release: null pixels");
326 return ra8_tile_cache_put(&r->cache, pixels);
327}
328
329#else
330/* ra8_mem tile cache / JOF atlas reader not on the include path for this app:
331 * the comic tile reader is unused here (the whole-decode path stands alone). A
332 * single typedef keeps the translation unit non-empty. */
334#endif /* __has_include("ra8_tile_cache.h") && __has_include("jof.h") */
int comic_tiles_unused_translation_unit_t
Tile an oversized comic page through the JOF atlas + ra8_tile_cache so a CBZ/CBR page larger than the...
ra8_err_t comic_tiles_tile(comic_tile_reader_t *r, uint16_t tile_x, uint16_t tile_y, ra8_tile_t *out_tile)
Get (and pin) one decoded tile of the bound page (#344).
ra8_err_t comic_tiles_import(comic_tile_reader_t *r, const uint8_t *enc, size_t enc_len, const comic_tiles_import_cfg_t *cfg)
Transcode one encoded comic page to a JOF atlas and bind it for tiling.
ra8_err_t comic_tiles_info(const comic_tile_reader_t *r, jof_info_t *out_info)
Report the bound page's parsed atlas geometry (#344).
ra8_err_t comic_tiles_footprint(const uint8_t *enc, size_t len, uint16_t *out_w, uint16_t *out_h, uint64_t *out_decoded_bytes)
Read a comic page's decoded footprint from its encoded header (#344).
@ k_comic_tiles_decoded_bpp
Bytes/pixel used for the budget estimate.
bool comic_tiles_over_budget(uint64_t decoded_bytes, uint64_t budget_bytes)
Decide whether a page's decoded footprint exceeds the resident budget.
ra8_err_t comic_tiles_init(comic_tile_reader_t *r, const ra8_tile_cache_cfg_t *storage, uint8_t *scratch, uint32_t scratch_cap)
Initialise a comic tile reader over caller-supplied tile-cache storage.
ra8_err_t comic_tiles_release(comic_tile_reader_t *r, const uint8_t *pixels)
Release one pin taken by comic_tiles_tile (#344).
JOF band-tile atlas: the display-native normalized image format (#231, shared with the longstrip scro...
ra8_err_t jof_memstore_pread(void *ctx, uint64_t offset, uint8_t *buf, size_t len, size_t *got)
Positioned read from a jof_memstore_t (reader seam).
Definition jof.c:177
ra8_err_t jof_read_tile(jof_pread_fn pread, void *pread_ctx, const jof_info_t *info, uint16_t tile_x, uint16_t tile_y, uint8_t *scratch, uint32_t scratch_cap, uint8_t *out_px, uint32_t out_cap, uint16_t *out_w, uint16_t *out_h)
Read + decode one tile into caller pixels, in bounded RAM.
Definition jof.c:637
ra8_err_t jof_parse(jof_pread_fn pread, void *pread_ctx, uint64_t total_size, jof_info_t *out_info)
Parse + validate a JOF atlas's header, footer and index bounds.
Definition jof.c:379
ra8_err_t jof_memstore_sink(void *ctx, const uint8_t *buf, size_t len)
Append len bytes to a jof_memstore_t (producer sink).
Definition jof.c:163
Import-time transcode producer: JPEG/PNG/WebP -> JOF band-tile atlas in bounded RAM (#231,...
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.
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).
static const char * s_tag
Logging / check tag.
Definition ra8_app.c:17
Annotation-attribute framework macros for ra8-firmware.
#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.
Definition ra8_check.h:243
Error Code Definitions for ra8-firmware.
@ k_ra8_err_no_mem
Static buffer exhausted (no dynamic memory on this project).
Definition ra8_err.h:142
@ k_ra8_err_out_of_range
Sensor or peripheral output out of valid range.
Definition ra8_err.h:337
@ k_ra8_err_invalid_state
Module in wrong state for requested operation.
Definition ra8_err.h:161
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_invalid_size
Invalid size parameter (too large, too small, or misaligned).
Definition ra8_err.h:167
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
void * memset(void *dst, int value, size_t n)
Fill memory with a constant byte value.
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
static ra8_err_t internal_tile_decode(void *ctx, const void *key, uint8_t *cell, uint32_t cell_bytes, void *user)
Decode trampoline: adapt ra8_tile_decode_fn to the keycache seam.
Fixed-RAM-budget image-tile cache with LRU eviction (Layer 3b, #147).
ra8_err_t ra8_tile_cache_get(ra8_tile_cache_t *tc, const ra8_tile_key_t *key, ra8_tile_t *out_tile)
Get (and pin) the decoded tile for key.
ra8_err_t ra8_tile_cache_put(ra8_tile_cache_t *tc, const uint8_t *pixels)
Release one pin on a tile previously returned by ra8_tile_cache_get.
ra8_err_t ra8_tile_cache_init(ra8_tile_cache_t *tc, const ra8_tile_cache_cfg_t *cfg)
Initialise a tile cache over caller-supplied storage.
One comic tile reader: owned tile cache, atlas store, bound page.
bool bound
True while a page atlas is imported.
uint32_t scratch_cap
Capacity of scratch.
uint32_t epoch
Import counter; the tile-cache key id.
uint8_t * scratch
Stored-tile staging for deflate atlases.
jof_memstore_t store
Atlas backing for the bound page.
ra8_tile_cache_t cache
Owned tile cache (decode wired to this).
jof_info_t info
Parsed geometry of the bound page.
Import-time transcode knobs, work arena, and destination atlas store.
uint8_t codec
jof_codec_t member.
uint16_t tile_w
Tile width, pixels (>= 1).
uint8_t * atlas
Atlas memstore backing (out-lives tile fetch).
uint16_t max_width
Width budget cap (0 = format cap).
size_t atlas_cap
Capacity of atlas in bytes.
uint16_t tile_h
Tile height, pixels (>= 1).
uint8_t * webp_work
WebP whole-frame arena, or NULL to reject WebP.
size_t work_cap
Arena size (jof_work_bytes()).
uint16_t max_height
Height budget cap (0 = format cap).
size_t webp_work_cap
WebP arena size (jof_webp_work_bytes()).
Parsed + validated geometry of one JOF atlas.
Definition jof.h:208
uint16_t tile_rows
Ceil(height / tile_h) tile rows.
Definition jof.h:214
uint16_t tile_cols
Ceil(width / tile_w) tile columns.
Definition jof.h:213
Append-only memory store: the simplest atlas backing (RAM/SDRAM).
Definition jof.h:256
size_t len
Bytes appended so far (see sink).
Definition jof.h:259
Producer configuration: source, sink, tile geometry and work arena.
Caller-supplied storage + decoder for ra8_tile_cache_init.
ra8_tile_decode_fn decode
Decode-on-miss callback.
void * decode_ctx
Opaque context passed to decode.
Identifies one decoded image tile.
uint16_t tile_y
Tile row index (in tile units).
uint16_t tile_x
Tile column index (in tile units).
A pinned view of a cached tile returned by ra8_tile_cache_get.