|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Zero-heap raster image decode + nearest-neighbour scale + blit (#106). More...
#include "reflow_image.h"#include <stddef.h>#include <stdint.h>#include <string.h>#include "ra8_attributes.h"#include "ra8_check.h"#include "ra8_err.h"#include "ra8_gfx.h"#include "ra8_img_arena.h"#include "ra8_log.h"#include "reflow_svg.h"#include "stb_image.h"Go to the source code of this file.
Enumerations | |
| enum | ra8_img_pack_t : uint8_t { k_ra8_img_req_rgb = 3 , k_ra8_img_ch_r = 0 , k_ra8_img_ch_g = 1 , k_ra8_img_ch_b = 2 , k_ra8_img_min_edge = 1 } |
| Pixel-packing and channel constants (no magic numbers). More... | |
| enum | ra8_img_shift_t : uint8_t { k_ra8_img_shift_r = 16 , k_ra8_img_shift_g = 8 } |
| Channel shifts to assemble a 0x00RRGGBB colour for ra8_gfx (no magics). More... | |
Functions | |
| ra8_err_t | ra8_img_probe_size (const uint8_t *bytes, size_t len, int32_t *out_w, int32_t *out_h) |
| Probe an image's intrinsic dimensions without a full decode. | |
| static void | internal_fit_box (int32_t src_w, int32_t src_h, int32_t box_w, int32_t box_h, int32_t *fit_w, int32_t *fit_h) |
| Compute the aspect-preserving fit rectangle for an image in a box. | |
| static ra8_err_t | internal_decode_fail (void) |
| Map a decode failure to the closest ra8_err_t via stbi_failure_reason. | |
| static void | internal_blit_scaled (const uint8_t *pixels, int32_t src_w, int32_t src_h, int32_t fit_w, int32_t fit_h, int32_t dst_x, int32_t dst_y) |
| Nearest-neighbour blit a decoded RGB image into the bound framebuffer. | |
| static void | internal_arena_release (ra8_img_arena_t *arena) |
| Unbind the decode arena and force it back to the fully-drained state. | |
| ra8_err_t | ra8_img_decode_blit (ra8_img_arena_t *arena, const uint8_t *bytes, size_t len, int32_t dst_x, int32_t dst_y, int32_t box_w, int32_t box_h, int32_t *out_w, int32_t *out_h) |
| Implementation of ra8_img_decode_blit() – nearest-neighbour scale. | |
Variables | |
| static const char *const | s_tag_img = "ra8_img" |
| Log tag for the image decode/blit module. | |
Zero-heap raster image decode + nearest-neighbour scale + blit (#106).
Implements reflow_image.h. The decode runs through the vendored stb_image (built once in apps/shared_libs/third_party/stb/stb_image_impl.c) with its allocator redirected to a caller-bound bump arena, so no malloc is reached. The blit is an integer nearest-neighbour scale-to-fit into a layout box, emitting one ra8_gfx_pixel() per destination pixel (which clips to the framebuffer).
[Ring 4 / Reflow] {World: NS}
Definition in file reflow_image.c.
| enum ra8_img_pack_t : uint8_t |
Pixel-packing and channel constants (no magic numbers).
Definition at line 42 of file reflow_image.c.
| enum ra8_img_shift_t : uint8_t |
Channel shifts to assemble a 0x00RRGGBB colour for ra8_gfx (no magics).
| Enumerator | |
|---|---|
| k_ra8_img_shift_r | Red channel shift into 0x00RRGGBB. |
| k_ra8_img_shift_g | Green channel shift into 0x00RRGGBB. |
Definition at line 54 of file reflow_image.c.
|
static |
Unbind the decode arena and force it back to the fully-drained state.
Calls ra8_img_arena_unbind() to clear the module-static pointer that redirects stb_image allocations, then resets both bookkeeping fields of the arena struct to zero: offset (the bump pointer) and live (the outstanding allocation count). This guarantees the arena is ready for reuse and that no stale stb_image allocation callbacks can reach it after the call. The base and cap fields, which are owned by the caller, are left untouched. Called on every return path of ra8_img_decode_blit() – both on success after stbi_image_free() and on failure before returning an error code. Internal helper for ra8_img_decode_blit().
| [in,out] | arena | Bump arena to unbind and reset; must not be NULL. |
arena is a valid non-NULL pointer to a bound or partially-used ra8_img_arena_t that was previously passed to ra8_img_arena_bind(). arena (i.e., ra8_img_arena_bind() has been called and not yet paired with unbind). arena->offset == 0 and arena->live == 0. arena.Definition at line 269 of file reflow_image.c.
References ra8_img_arena_t::live, ra8_img_arena_t::offset, and ra8_img_arena_unbind().
Referenced by ra8_img_decode_blit().
|
static |
Nearest-neighbour blit a decoded RGB image into the bound framebuffer.
Iterates over every pixel in the fit_w x fit_h destination rectangle. For each destination pixel (dx, dy) the corresponding source row and column are computed with integer division scaled by int64 products to avoid overflow: map_y = (dy * src_h) / fit_h and map_x = (dx * src_w) / fit_w. The RGB triple at that position in the row-major pixels buffer is then packed into a 0x00RRGGBB word and emitted via ra8_gfx_pixel(dst_x + dx, dst_y + dy, color), which clips coordinates that fall outside the bound framebuffer. The function reads every pixel in the destination rectangle once; no sub-pixel filtering is applied. Internal helper for ra8_img_decode_blit().
| [in] | pixels | Decoded source buffer, row-major RGB triples, size src_w * src_h * 3 bytes; must not be NULL. |
| [in] | src_w | Source width, pixels (>= 1). |
| [in] | src_h | Source height, pixels (>= 1). |
| [in] | fit_w | Destination width, pixels (>= 1). |
| [in] | fit_h | Destination height, pixels (>= 1). |
| [in] | dst_x | Destination left edge in framebuffer coordinates. |
| [in] | dst_y | Destination top edge in framebuffer coordinates. |
pixels is a valid pointer to src_w * src_h * 3 readable bytes. src_w, src_h, fit_w, fit_h) are >= 1 so neither loop bound is zero and no division by zero occurs. pixels buffer is not modified (read-only traversal).pixels use module-static state. Caller must ensure exclusive access.Definition at line 217 of file reflow_image.c.
References k_ra8_img_ch_b, k_ra8_img_ch_g, k_ra8_img_ch_r, k_ra8_img_req_rgb, k_ra8_img_shift_g, k_ra8_img_shift_r, and ra8_gfx_pixel().
Referenced by ra8_img_decode_blit().
|
static |
Map a decode failure to the closest ra8_err_t via stbi_failure_reason.
Queries stbi_failure_reason() immediately after a failed stbi_load_from_memory() call and inspects the returned string for the substring "outofmem". When that tag is present the arena exhausted its capacity before the decode completed; the function returns k_ra8_err_no_mem so the caller can report a memory shortage rather than a format error. Any other reason string (corrupt header, unsupported colour depth, unsupported format, etc.) maps to k_ra8_err_not_supported. A NULL reason string is treated the same way as an unrecognised string. Internal helper for ra8_img_decode_blit().
| k_ra8_err_no_mem | The "outofmem" tag was found in the reason. |
| k_ra8_err_not_supported | Any other failure (corrupt or unsupported). |
Definition at line 163 of file reflow_image.c.
References k_ra8_err_no_mem, k_ra8_err_not_supported, and strstr().
Referenced by ra8_img_decode_blit().
|
static |
Compute the aspect-preserving fit rectangle for an image in a box.
Picks the largest integer scale that maps the source into the box while preserving aspect ratio. The tighter axis is determined by comparing box_w * src_h with box_h * src_w using int64 products to prevent overflow on large dimensions. The width-constrained branch scales height proportionally to width; the height-constrained branch scales width proportionally to height. Both output dimensions are clamped to at least k_ra8_img_min_edge (1 pixel) so downstream callers never receive a zero-size rectangle. Internal helper for ra8_img_decode_blit().
| [in] | src_w | Source width, pixels (>= 1). |
| [in] | src_h | Source height, pixels (>= 1). |
| [in] | box_w | Box width, pixels (>= 1). |
| [in] | box_h | Box height, pixels (>= 1). |
| [out] | fit_w | Receives the scaled width, pixels (>= 1). |
| [out] | fit_h | Receives the scaled height, pixels (>= 1). |
fit_w and fit_h are valid, writable, non-NULL pointers. Definition at line 113 of file reflow_image.c.
References k_ra8_img_min_edge.
Referenced by ra8_img_decode_blit().
|
nodiscard |
Implementation of ra8_img_decode_blit() – nearest-neighbour scale.
Decode bytes and blit it, scaled to fit, into the bound framebuffer.
Definition at line 277 of file reflow_image.c.
References internal_arena_release(), internal_blit_scaled(), internal_decode_fail(), internal_fit_box(), k_ra8_err_invalid_arg, k_ra8_img_min_edge, k_ra8_img_req_rgb, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_img_arena_bind(), ra8_log_error, and s_tag_img.
Referenced by cm_draw_page(), ec_render_cover_or_halt(), ef_decode_and_hash(), internal_decode(), internal_render_one_image(), internal_render_svg(), main(), sh_book_cover_fullscreen(), sh_comic_blit_page(), and sh_epub_thumb().
|
nodiscard |
Probe an image's intrinsic dimensions without a full decode.
Wraps stbi_info_from_memory – lets the layout pass size an <img> box from the source dimensions before deciding to decode + blit. Allocates nothing.
| [in] | bytes | Encoded image bytes. |
| [in] | len | Length of bytes. |
| [out] | out_w | Receives intrinsic width. |
| [out] | out_h | Receives intrinsic height. |
| k_ra8_ok | Dimensions read. |
| k_ra8_err_null_ptr | Any pointer argument is NULL. |
| k_ra8_err_not_supported | stb_image could not parse the header. |
bytes holds len bytes; out_w / out_h are writable. bytes; thread-safe. Definition at line 59 of file reflow_image.c.
References k_ra8_err_not_supported, k_ra8_ok, RA8_CHECK_NULL_PTR, ra8_log_error, ra8_svg_is_svg(), ra8_svg_size(), and s_tag_img.
Referenced by internal_image_resolve_size(), and internal_probe_page().
|
static |
Log tag for the image decode/blit module.
Definition at line 36 of file reflow_image.c.
Referenced by ra8_img_decode_blit(), and ra8_img_probe_size().