ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_viewer_jof.c
Go to the documentation of this file.
1
10
11#include <stdint.h>
12#include <string.h>
13
14#include "jof.h"
15#include "longstrip.h"
16#include "ra8_attributes.h"
17#include "ra8_decomp_limits.h"
18#include "ra8_err.h"
19#include "ra8_tile_cache.h"
20#include "ra8_viewer_reader.h"
22
31
46RA8_INTERNAL static uint16_t internal_band_pixel(const uint8_t* source, uint8_t bpp)
47{
48 if (bpp == (uint8_t)k_viewer_bpp_gray) {
49 return ra8_viewer_pack565(source[k_viewer_px_r], source[k_viewer_px_r], source[k_viewer_px_r]);
50 }
51 if (bpp == (uint8_t)k_viewer_bpp_rgb565) {
53 }
54 return ra8_viewer_pack565(source[k_viewer_px_r], source[k_viewer_px_g], source[k_viewer_px_b]);
55}
56
77 const uint8_t* pixels,
78 uint16_t source_width,
79 uint16_t source_height,
80 uint8_t bpp,
81 int32_t destination_x,
82 int32_t destination_y)
83{
85 const int32_t target_width = (int32_t)reader->rt_w;
86 const int32_t target_height = (int32_t)reader->rt_h;
87 for (int32_t row = 0; row < (int32_t)source_height; ++row) {
88 const int32_t y = destination_y + row;
89 if ((y < 0) || (y >= target_height)) {
90 continue;
91 }
92 for (int32_t column = 0; column < (int32_t)source_width; ++column) {
93 const int32_t x = destination_x + column + reader->jof.x_off;
94 if ((x < 0) || (x >= target_width)) {
95 continue;
96 }
97 const size_t source_index =
98 (((size_t)row * (size_t)source_width) + (size_t)column) * (size_t)bpp;
99 const size_t target_index = ((size_t)y * (size_t)target_width) + (size_t)x;
100 reader->rt565[target_index] = internal_band_pixel(&pixels[source_index], bpp);
101 }
102 }
103 return k_ra8_ok;
104}
105
120RA8_INTERNAL static ra8_err_t internal_wire(ra8_viewer_reader_t* reader, size_t band_bytes)
121{
122 viewer_jof_t* jof = &reader->jof;
123 jof->dctx.scratch = jof->scratch;
124 jof->dctx.scratch_cap = (uint32_t)jof->scratch_cap;
125 const ra8_tile_cache_cfg_t cache_config = {
126 .cell_mem = jof->cells,
127 .cell_bytes = (uint32_t)band_bytes,
128 .cell_count = (uint32_t)k_viewer_jof_cells,
129 .meta = jof->meta,
130 .keys = jof->keys,
131 .dims = jof->dims,
132 .buckets = jof->buckets,
133 .bucket_count = (uint32_t)k_viewer_jof_buckets,
134 .decode = longstrip_tile_decode,
135 .decode_ctx = &jof->dctx,
136 };
137 ra8_err_t error = ra8_tile_cache_init(&jof->cache, &cache_config);
138 if (error != k_ra8_ok) {
139 return error;
140 }
141 jof->viewport_h = (uint32_t)k_ra8_viewer_fb_height;
142 jof->x_off = 0;
143 const longstrip_cfg_t strip_config = {
144 .pread = priv_viewer_pread,
145 .pread_ctx = &reader->file,
146 .atlas_size = reader->file.size,
147 .cache = &jof->cache,
148 .image_id = 1U,
149 .viewport_w = jof->dctx.info.width,
150 .viewport_h = (uint16_t)k_ra8_viewer_fb_height,
151 .blit = internal_jof_blit,
152 .blit_ctx = reader,
153 };
154 return longstrip_open(&jof->strip, &strip_config);
155}
156
173{
174 const uint32_t top = page * jof->viewport_h;
175 const uint32_t canvas = jof->dctx.info.height;
176 const uint32_t remaining = (canvas > top) ? (canvas - top) : 0U;
177 const uint32_t content = (remaining < jof->viewport_h) ? remaining : jof->viewport_h;
178 if (content == 0U) {
180 }
181 const ra8_err_t error =
182 longstrip_set_viewport(&jof->strip, jof->dctx.info.width, (uint16_t)content);
183 if (error != k_ra8_ok) {
184 return error;
185 }
186 return longstrip_scroll_by(&jof->strip, (int32_t)top - jof->strip.scroll_y);
187}
188
190{
191 viewer_jof_t* jof = &reader->jof;
193 jof->dctx.pread_ctx = &reader->file;
194 ra8_err_t error = jof_parse(priv_viewer_pread, &reader->file, reader->file.size, &jof->dctx.info);
195 const uint64_t band = (uint64_t)jof->dctx.info.tile_w * (uint64_t)jof->dctx.info.tile_h *
196 (uint64_t)jof->dctx.info.bpp;
197 if ((error == k_ra8_ok) && (band == 0U)) {
199 }
201 if (error == k_ra8_ok) {
202 error = ra8_decomp_check_declared(&limits, reader->file.size, band);
203 }
204 const size_t scratch_required = (jof->dctx.info.codec == (uint8_t)k_jof_codec_raw)
205 ? 1U
206 : (size_t)jof_stored_bound((uint32_t)band);
207 if ((error == k_ra8_ok) &&
208 (((size_t)band > jof->cell_cap) || (scratch_required > jof->scratch_cap))) {
210 }
211 if (error != k_ra8_ok) {
212 return error;
213 }
214 return internal_wire(reader, (size_t)band);
215}
216
218{
219 viewer_jof_t* jof = &reader->jof;
220 reader->rt565 = reader->fb;
221 reader->rt_w = (uint32_t)k_ra8_viewer_fb_width;
222 reader->rt_h = (uint32_t)k_ra8_viewer_fb_height;
223 const int32_t strip_width = (int32_t)jof->dctx.info.width;
224 jof->x_off =
225 ((int32_t)reader->rt_w > strip_width) ? (((int32_t)reader->rt_w - strip_width) / 2) : 0;
226 memset(reader->fb,
228 (size_t)reader->rt_w * (size_t)reader->rt_h * sizeof(*reader->fb));
229 ra8_err_t error = internal_seek(jof, page);
230 if (error == k_ra8_ok) {
231 longstrip_render_stats_t stats = {};
232 error = longstrip_render(&jof->strip, &stats);
233 }
234 return error;
235}
236
238 uint32_t index,
239 uint16_t* pixels,
240 size_t pixel_bytes,
241 uint32_t* width,
242 uint32_t* height)
243{
244 viewer_jof_t* jof = &reader->jof;
245 const uint32_t native_width = reader->tile_wpx[index];
246 const uint32_t native_height = reader->tile_hpx[index];
247 const size_t required = (size_t)native_width * (size_t)native_height * sizeof(*pixels);
248 if ((native_width == 0U) || (native_height == 0U) || (pixel_bytes < required)) {
250 }
251 reader->rt565 = pixels;
252 reader->rt_w = native_width;
253 reader->rt_h = native_height;
254 jof->x_off = 0;
255 memset(pixels, (int)k_viewer_white_byte, required);
256 ra8_err_t error = internal_seek(jof, index);
257 if (error == k_ra8_ok) {
258 longstrip_render_stats_t stats = {};
259 error = longstrip_render(&jof->strip, &stats);
260 }
261 reader->rt565 = reader->fb;
262 reader->rt_w = (uint32_t)k_ra8_viewer_fb_width;
263 reader->rt_h = (uint32_t)k_ra8_viewer_fb_height;
264 if (error == k_ra8_ok) {
265 *width = native_width;
266 *height = native_height;
267 }
268 return error;
269}
270
272{
273 const uint32_t width = reader->jof.dctx.info.width;
274 const uint32_t viewport = reader->jof.viewport_h;
275 const uint32_t canvas = reader->jof.dctx.info.height;
276 for (uint32_t index = 0U; index < count; ++index) {
277 const uint32_t top = index * viewport;
278 uint32_t height = (canvas > top) ? (canvas - top) : 0U;
279 if (height > viewport) {
280 height = viewport;
281 }
282 reader->tile_wpx[index] = width;
283 reader->tile_hpx[index] = height;
284 }
285}
JOF band-tile atlas: the display-native normalized image format (#231, shared with the longstrip scro...
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
@ k_jof_codec_raw
Tile stream is the packed pixels.
Definition jof.h:191
uint32_t jof_stored_bound(uint32_t raw_bytes)
Worst-case stored-tile byte bound for scratch/cell sizing.
Definition jof.c:439
Continuous vertical-scroll (longstrip / manhwa) reading mode over an JOF band-tile atlas (#289).
ra8_err_t longstrip_tile_decode(void *ctx, const ra8_tile_key_t *key, uint8_t *cell, uint32_t cell_bytes, uint16_t *out_w, uint16_t *out_h)
JOF-backed ra8_tile_decode_fn: page one band in on a cache miss.
Definition longstrip.c:53
ra8_err_t longstrip_scroll_by(longstrip_t *wt, int32_t delta)
Scroll by a signed pixel delta (a finger drag), clamping at the ends.
Definition longstrip.c:273
ra8_err_t longstrip_render(longstrip_t *wt, longstrip_render_stats_t *stats)
Composite every visible band at the current scroll position.
Definition longstrip.c:550
ra8_err_t longstrip_set_viewport(longstrip_t *wt, uint16_t viewport_w, uint16_t viewport_h)
Resize the viewport of an open strip and re-derive the scroll clamp.
Definition longstrip.c:180
ra8_err_t longstrip_open(longstrip_t *wt, const longstrip_cfg_t *cfg)
Open a longstrip strip over a parsed + validated JOF atlas.
Definition longstrip.c:154
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Unified decompression-limits policy: one bound set for every decoder.
ra8_decomp_limits_t ra8_decomp_limits_default(void)
The owner-approved default decompression policy.
ra8_err_t ra8_decomp_check_declared(const ra8_decomp_limits_t *limits, uint64_t comp_size, uint64_t out_size)
Header-level check of a member's declared sizes against a policy.
Error Code Definitions for ra8-firmware.
@ k_ra8_err_out_of_range
Sensor or peripheral output out of valid range.
Definition ra8_err.h:337
@ 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.
Fixed-RAM-budget image-tile cache with LRU eviction (Layer 3b, #147).
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.
static ra8_err_t internal_seek(viewer_jof_t *jof, uint32_t page)
Seek to a viewport, including the short final page.
static ra8_err_t internal_jof_blit(void *ctx, const uint8_t *pixels, uint16_t source_width, uint16_t source_height, uint8_t bpp, int32_t destination_x, int32_t destination_y)
Composite one decoded band window into the active RGB565 target.
viewer_pixel_t
Supported source pixel widths and channel indices.
@ k_viewer_px_r
Red, gray, or RGB565 low byte.
@ k_viewer_bpp_gray
8-bit grayscale.
@ k_viewer_px_b
Blue byte.
@ k_viewer_bpp_rgb565
Little-endian RGB565.
@ k_viewer_px_g
Green or RGB565 high byte.
static uint16_t internal_band_pixel(const uint8_t *source, uint8_t bpp)
Convert one source pixel to native RGB565.
void priv_viewer_size_jof_tiles(ra8_viewer_reader_t *reader, uint32_t count)
Populate native tile dimensions after the strip opens.
ra8_err_t priv_viewer_tile_jof(ra8_viewer_reader_t *reader, uint32_t index, uint16_t *pixels, size_t pixel_bytes, uint32_t *width, uint32_t *height)
Render one JOF viewport into caller-owned RGB565 output.
ra8_err_t priv_viewer_open_jof(ra8_viewer_reader_t *reader)
Open and wire the JOF engine over a bound reader.
static ra8_err_t internal_wire(ra8_viewer_reader_t *reader, size_t band_bytes)
Wire the one-cell cache and long-strip engine.
ra8_err_t priv_viewer_render_jof(ra8_viewer_reader_t *reader, uint32_t page)
Render one JOF viewport into the fixed framebuffer.
Caller-owned host JOF/comic reader and RGB565 render surface.
@ k_ra8_viewer_fb_height
Framebuffer height in pixels.
@ k_ra8_viewer_fb_width
Framebuffer width in pixels.
uint16_t ra8_viewer_pack565(uint8_t rr, uint8_t gg, uint8_t bb)
Pack 8-bit RGB channels into one RGB565 word.
struct ra8_viewer_reader ra8_viewer_reader_t
Opaque state bound inside caller-owned workspace.
uint16_t ra8_viewer_pack565_le_pair(uint8_t low, uint8_t high)
Reassemble one little-endian RGB565 word.
Cross-translation-unit state for the bounded JOF/comic viewer.
ra8_err_t priv_viewer_pread(void *ctx, uint64_t offset, uint8_t *buffer, size_t length, size_t *out_read)
JOF positional-reader seam over viewer_file_ctx_t.
@ k_viewer_white_byte
Byte fill for white RGB565.
@ k_viewer_jof_buckets
Power-of-two cache bucket count.
@ k_viewer_jof_cells
One decoded band resident.
uint8_t bpp
Bytes per pixel (1, 3 or 4).
Definition jof.h:215
uint8_t codec
jof_codec_t member.
Definition jof.h:216
uint16_t tile_w
Tile width, pixels.
Definition jof.h:211
uint16_t width
Image width, pixels.
Definition jof.h:209
uint16_t tile_h
Tile height, pixels.
Definition jof.h:212
uint16_t height
Image height, pixels.
Definition jof.h:210
One-shot configuration handed to longstrip_open.
Definition longstrip.h:160
uint8_t * scratch
Deflate staging (codec 1 only).
Definition longstrip.h:141
void * pread_ctx
Context for pread.
Definition longstrip.h:139
jof_pread_fn pread
Atlas backing read seam.
Definition longstrip.h:138
jof_info_t info
Parsed atlas geometry.
Definition longstrip.h:140
uint32_t scratch_cap
Capacity of scratch.
Definition longstrip.h:142
Per-frame render accounting returned by longstrip_render.
Definition longstrip.h:215
int32_t scroll_y
Viewport top on the canvas, clamped.
Definition longstrip.h:193
One decompression policy: the five resource bounds decoders enforce.
Caller-supplied storage + decoder for ra8_tile_cache_init.
uint32_t * tile_hpx
Native height per viewport tile.
uint32_t * tile_wpx
Native width per viewport tile.
uint16_t * rt565
Current composite target.
viewer_jof_t jof
JOF engine and caller-bound cache.
uint32_t rt_w
Current target width.
uint16_t * fb
Fixed headless framebuffer.
viewer_file_ctx_t file
Raw source descriptor.
uint32_t rt_h
Current target height.
uint64_t size
Document length in bytes.
Caller-bound JOF engine and one-band cache backing.
size_t scratch_cap
Bound compressed staging bytes.
longstrip_t strip
Scroll/composite engine.
uint8_t * scratch
Compressed-band staging.
uint32_t viewport_h
Page height on the strip.
longstrip_decode_ctx_t dctx
JOF decoder callback state.
ra8_tile_dims_t * dims
Single cache dimensions entry.
ra8_tile_cache_t cache
One-band keyed cache.
uint8_t * cells
One decoded-band buffer.
ra8_tile_key_t * keys
Single cache key.
int32_t * buckets
Hash bucket heads.
ra8_keycache_cell_t * meta
Single cache metadata entry.
size_t cell_cap
Bound decoded-band bytes.
int32_t x_off
Horizontal target centring.