|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Pure-software baseline JPEG (ISO/IEC 10918-1 / ITU-T T.81) codec. More...
Go to the source code of this file.
Typedefs | |
| typedef ra8_err_t(* | ra8_jpeg_sw_pull_fn) (void *ctx, uint8_t *buf, size_t cap, size_t *got) |
| Forward byte source for the streaming decoder (DIP seam). | |
| typedef ra8_err_t(* | ra8_jpeg_sw_geom_fn) (void *ctx, uint16_t width, uint16_t height, uint8_t channels, uint16_t stripe_rows, uint8_t **out_stripe, uint32_t *out_stripe_cap) |
| Geometry callback: fires once, right after SOF0 parses. | |
| typedef ra8_err_t(* | ra8_jpeg_sw_rows_fn) (void *ctx, const uint8_t *px, uint16_t width, uint16_t y0, uint16_t nrows, uint8_t channels) |
| Stripe sink: receives each completed run of decoded pixel rows. | |
Enumerations | |
| enum | ra8_jpeg_sw_pixfmt_t : uint8_t { k_ra8_jpeg_sw_pixfmt_rgb888 = 0U } |
| Output pixel layout produced by ra8_jpeg_sw_decode(). More... | |
| enum | ra8_jpeg_sw_quality_t : uint8_t { k_ra8_jpeg_sw_quality_min = 1U , k_ra8_jpeg_sw_quality_low = 50U , k_ra8_jpeg_sw_quality_default = 75U , k_ra8_jpeg_sw_quality_high = 90U , k_ra8_jpeg_sw_quality_max = 100U } |
| Convenience quality presets for ra8_jpeg_sw_encode(). More... | |
| enum | ra8_jpeg_sw_stream_limits_t : uint32_t { k_ra8_jpeg_sw_stream_min_window = 131072U , k_ra8_jpeg_sw_stream_scan_margin = 32768U } |
| Sizing floors for the streaming stripe decoder. More... | |
| enum | ra8_jpeg_sw_stream_geom_t : uint8_t { k_ra8_jpeg_sw_stream_mcu_rows_max = 16U } |
| Stripe geometry constant exposed for consumer buffer sizing. More... | |
Functions | |
| 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 decoding. | |
| ra8_err_t | ra8_jpeg_sw_decode (const uint8_t *jpeg_buf, uint32_t jpeg_len, uint8_t *out_buf, uint32_t out_buf_len, uint16_t *out_w, uint16_t *out_h) |
| Decode a baseline JPEG stream into packed RGB888. | |
| ra8_err_t | ra8_jpeg_sw_encode (const uint8_t *rgb_buf, uint16_t width, uint16_t height, uint8_t quality, uint8_t *out_buf, uint32_t out_buf_len, uint32_t *out_len) |
| Encode a packed RGB888 frame as a baseline JPEG. | |
| 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. | |
Pure-software baseline JPEG (ISO/IEC 10918-1 / ITU-T T.81) codec.
The RA8D2 has no hardware JPEG block. This module implements a software baseline JPEG codec (8-bit precision, sequential DCT, Huffman entropy coding) for two pixel layouts:
Decoder input is accepted with both 4:2:0 and 4:4:4 chroma subsampling so that round-trip tests against known files still succeed; encoder output is fixed at 4:2:0 (or grayscale-only when quality is negative – see ra8_jpeg_sw_encode()).
Out of scope:
Spec citations are formatted as T.81 sec X.Y "..." and refer to ITU-T Recommendation T.81 (1992) | ISO/IEC 10918-1.
Definition in file ra8_jpeg_sw.h.
| typedef ra8_err_t(* ra8_jpeg_sw_geom_fn) (void *ctx, uint16_t width, uint16_t height, uint8_t channels, uint16_t stripe_rows, uint8_t **out_stripe, uint32_t *out_stripe_cap) |
Geometry callback: fires once, right after SOF0 parses.
The consumer learns the image dimensions and channel count (1 = grayscale, 3 = RGB) before any pixel decodes, sizes its own buffers, and hands back the stripe buffer the decoder will fill: at least width * (8 * vmax) * channels bytes, where 8 * vmax is 8 for 4:4:4/grayscale and 16 for 4:2:0. Sizing for k_ra8_jpeg_sw_stream_mcu_rows_max rows always suffices. Returning any error aborts the decode with that code (the fail-closed "image too large for my budget" hook).
| [in] | ctx | Consumer context. |
| [in] | width | Image width, pixels (>= 1). |
| [in] | height | Image height, pixels (>= 1). |
| [in] | channels | Output channels per pixel (1 or 3). |
| [in] | stripe_rows | Rows per stripe the decoder will emit (8/16). |
| [out] | out_stripe | Receives the consumer's stripe buffer. |
| [out] | out_stripe_cap | Receives that buffer's capacity, bytes. |
Definition at line 335 of file ra8_jpeg_sw.h.
| typedef ra8_err_t(* ra8_jpeg_sw_pull_fn) (void *ctx, uint8_t *buf, size_t cap, size_t *got) |
Forward byte source for the streaming decoder (DIP seam).
Strictly sequential: each call appends the next bytes of the JPEG stream. *got == 0 signals a clean end of stream; any error return aborts the decode with that code. An EPUB entry cursor (ra8_epub_entry_read) matches this shape directly.
| [in] | ctx | Source-specific context. |
| [out] | buf | Destination buffer (cap writable bytes). |
| [in] | cap | Capacity of buf. |
| [out] | got | Bytes delivered this call (0 = end of stream). |
Definition at line 310 of file ra8_jpeg_sw.h.
| typedef ra8_err_t(* ra8_jpeg_sw_rows_fn) (void *ctx, const uint8_t *px, uint16_t width, uint16_t y0, uint16_t nrows, uint8_t channels) |
Stripe sink: receives each completed run of decoded pixel rows.
Rows are tightly packed at width * channels bytes per row, top-to-bottom, and each stripe is emitted exactly once in order (y0 strictly increasing). The pixels live in the stripe buffer the geometry callback supplied and are only valid for the duration of the call. Returning any error aborts the decode with that code.
| [in] | ctx | Consumer context. |
| [in] | px | Stripe pixels (nrows * width * channels bytes). |
| [in] | width | Row width, pixels. |
| [in] | y0 | Image row of the stripe's first row. |
| [in] | nrows | Rows in this stripe (edge stripes are shorter). |
| [in] | channels | Bytes per pixel (1 or 3). |
Definition at line 363 of file ra8_jpeg_sw.h.
| enum ra8_jpeg_sw_pixfmt_t : uint8_t |
Output pixel layout produced by ra8_jpeg_sw_decode().
The decoder always emits packed RGB888 (3 bytes per pixel, R-G-B order, no row padding) regardless of the source colour space. This enum exists for symmetry with the encoder and to make future expansion (RGB565, YUV planar) explicit.
| Enumerator | |
|---|---|
| k_ra8_jpeg_sw_pixfmt_rgb888 | 24-bit packed R,G,B per pixel. |
Definition at line 59 of file ra8_jpeg_sw.h.
| enum ra8_jpeg_sw_quality_t : uint8_t |
Convenience quality presets for ra8_jpeg_sw_encode().
The quality argument to ra8_jpeg_sw_encode() is a plain integer in [1, 100]. These named constants document the recommended operating points; callers may pass any value in range.
Definition at line 73 of file ra8_jpeg_sw.h.
| enum ra8_jpeg_sw_stream_geom_t : uint8_t |
Stripe geometry constant exposed for consumer buffer sizing.
| Enumerator | |
|---|---|
| k_ra8_jpeg_sw_stream_mcu_rows_max | Max rows per stripe (4:2:0). |
Definition at line 376 of file ra8_jpeg_sw.h.
| enum ra8_jpeg_sw_stream_limits_t : uint32_t |
Sizing floors for the streaming stripe decoder.
The sliding window must always be able to materialise one whole marker segment (a segment length field is 16-bit, so <= 65537 bytes with its marker) AND keep a comfortable entropy-decode margin ahead of the bit reader between refills; 128 KiB covers both with 2x headroom. The scan margin is the refill trigger: the window slides whenever fewer bytes than this remain unread before an MCU decode.
| Enumerator | |
|---|---|
| k_ra8_jpeg_sw_stream_min_window | Minimum window bytes. |
| k_ra8_jpeg_sw_stream_scan_margin | Refill trigger, bytes. |
Definition at line 289 of file ra8_jpeg_sw.h.
|
nodiscard |
Decode a baseline JPEG stream into packed RGB888.
Performs full entropy decoding, dequantization, inverse DCT and YCbCr-to-RGB colour conversion (ITU-T T.871 JFIF colour conversion). The output buffer must be at least width * height * 3 bytes; the actual size is reported via *out_w and *out_h.
Supported source formats:
Algorithm (per MCU):
| [in] | jpeg_buf | Pointer to the JPEG byte stream. |
| [in] | jpeg_len | Length of jpeg_buf in bytes. |
| [out] | out_buf | Destination buffer for RGB888 pixels. |
| [in] | out_buf_len | Capacity of out_buf in bytes. |
| [out] | out_w | Receives image width in pixels. |
| [out] | out_h | Receives image height in pixels. |
| k_ra8_ok | Decoded successfully. |
| k_ra8_err_null_ptr | Any pointer argument was NULL. |
| k_ra8_err_protocol_error | Malformed JPEG stream. |
| k_ra8_err_not_supported | Progressive / arithmetic / 12-bit / unsupported chroma layout. |
| k_ra8_err_invalid_size | out_buf_len < width*height*3. |
Definition at line 896 of file ra8_jpeg_sw_decode.c.
References ra8_jpeg_dec_ctx_t::cursor, internal_dec_run(), internal_read_be16(), k_ra8_err_invalid_size, k_ra8_err_protocol_error, k_ra8_jpeg_marker_soi, memset(), RA8_CHECK_NULL_PTR, s_tag, ra8_jpeg_dec_ctx_t::src, and ra8_jpeg_dec_ctx_t::src_len.
|
nodiscard |
Decode a baseline JPEG in bounded RAM, one MCU-row stripe at a time.
The streaming counterpart of ra8_jpeg_sw_decode() for images whose whole decoded frame cannot be resident (#231). Input arrives through pull into the caller's sliding window (the resident compressed footprint); output leaves through on_rows one MCU row at a time (8 rows for 4:4:4/grayscale, 16 for 4:2:0), so the resident decoded footprint is one stripe – both independent of the image size. Between the two callbacks a transcoder can tile, convert, or compress each stripe with the whole image never in memory.
Same format envelope as ra8_jpeg_sw_decode(): baseline sequential Huffman, 8-bit, grayscale or YCbCr 4:4:4 / 4:2:0; progressive and restart-marker streams are rejected. Grayscale sources emit 1 channel, colour sources 3 (packed RGB888). One additional streaming-only bound: a run of more than the window size of consecutive 0xFF fill bytes is rejected as malformed rather than buffered unboundedly.
| [in] | pull | Sequential byte source (non-NULL). |
| [in] | pull_ctx | Context for pull. |
| [in] | window | Sliding compressed-input window buffer. |
| [in] | window_cap | Window capacity; >= k_ra8_jpeg_sw_stream_min_window. |
| [in] | on_geom | Geometry callback (non-NULL; supplies the stripe). |
| [in] | on_rows | Stripe sink (non-NULL). |
| [in] | cb_ctx | Context passed to both callbacks. |
| k_ra8_ok | Whole image decoded and emitted. |
| k_ra8_err_null_ptr | pull, window, on_geom, or on_rows is NULL. |
| k_ra8_err_invalid_size | window_cap below the minimum, or the supplied stripe buffer too small. |
| k_ra8_err_protocol_error | Malformed / truncated JPEG stream. |
| k_ra8_err_not_supported | Non-baseline stream (progressive, 12-bit, exotic chroma layout). |
| other | Propagated from pull / the callbacks. |
window holds window_cap writable bytes. pull delivers the stream strictly in order, once. Definition at line 497 of file ra8_jpeg_sw_stream.c.
References internal_js_begin(), internal_js_parse_markers(), internal_js_scan(), k_ra8_err_invalid_size, k_ra8_jpeg_sw_stream_min_window, k_ra8_ok, RA8_CHECK_NULL_PTR, s_js, and s_tag.
Referenced by internal_dispatch().
|
nodiscard |
Encode a packed RGB888 frame as a baseline JPEG.
Emits an SOI / APP0(JFIF 1.01) / DQT / SOF0 / DHT / SOS / compressed-data / EOI byte stream. Quantization tables are the T.81 Annex K.1 "Quantization table examples" luma and chroma tables, scaled by the IJG quality formula (scale = 5000/q for q < 50, 200 - 2q for q >= 50). Huffman tables are the T.81 Annex K.3.3 "Typical Huffman tables for 8-bit precision luminance and chrominance" reference tables, included verbatim via DHT segments rather than being optimized per image.
Colour space: input is interpreted as sRGB and converted to YCbCr per ITU-R BT.601, then chroma is averaged 4:1 to produce 4:2:0 subsampling. Width and height are padded to a multiple of 16 internally; the SOF0 marker still records the requested unpadded dimensions so decoders crop correctly.
| [in] | rgb_buf | Source pixels, 3 bytes per pixel (R, G, B), width * height * 3 total. |
| [in] | width | Image width in pixels (1..0xFFFF). |
| [in] | height | Image height in pixels (1..0xFFFF). |
| [in] | quality | Quality factor in [k_ra8_jpeg_sw_quality_min, k_ra8_jpeg_sw_quality_max]. |
| [out] | out_buf | Destination buffer for the JPEG bytes. |
| [in] | out_buf_len | Capacity of out_buf. |
| [out] | out_len | Receives the encoded byte count. |
| k_ra8_ok | Encoded; *out_len <= out_buf_len. |
| k_ra8_err_null_ptr | Any pointer argument was NULL. |
| k_ra8_err_invalid_arg | quality out of range, or width == 0, or height == 0. |
| k_ra8_err_invalid_size | out_buf_len too small to hold the encoded stream (worst case is roughly width * height * 3). |
Definition at line 778 of file ra8_jpeg_sw_encode.c.
References ra8_jpeg_enc_ctx_t::cap, ra8_jpeg_enc_ctx_t::dst, internal_enc_run(), k_ra8_err_invalid_arg, k_ra8_jpeg_sw_quality_max, k_ra8_jpeg_sw_quality_min, k_ra8_ok, memset(), ra8_jpeg_enc_ctx_t::pos, RA8_CHECK_NULL_PTR, and s_tag.
Referenced by internal_jpeg_sw_encode().
|
nodiscard |
Parse the SOF0 marker of a JPEG stream and report its image dimensions without performing entropy decoding.
Walks the marker chain looking for T.81 sec B.2.2 "Frame header syntax" (SOF0 = 0xFFC0). On match the 16-bit big-endian Y (height) and X (width) fields are returned. This is the cheap way to size an output buffer before calling ra8_jpeg_sw_decode().
Algorithm:
| [in] | jpeg_buf | Pointer to the JPEG byte stream (not NULL). |
| [in] | jpeg_len | Length of jpeg_buf in bytes (must be >= 4). |
| [out] | out_w | Receives image width in pixels (not NULL). |
| [out] | out_h | Receives image height in pixels (not NULL). |
| k_ra8_ok | Dimensions written to *out_w, *out_h. |
| k_ra8_err_null_ptr | Any pointer argument was NULL. |
| k_ra8_err_invalid_size | jpeg_len smaller than the SOI marker (2 bytes). |
| k_ra8_err_protocol_error | Stream lacks SOI, lacks SOF0, or a marker length field overflows the buffer. |
| k_ra8_err_not_supported | SOF marker is non-baseline (e.g. progressive 0xFFC2, lossless 0xFFC3, arithmetic 0xFFC9+). |
Definition at line 587 of file ra8_jpeg_sw.c.
References internal_dims_step(), internal_read_be16(), k_ra8_err_invalid_size, k_ra8_err_protocol_error, k_ra8_jpeg_marker_soi, k_ra8_ok, RA8_CHECK_NULL_PTR, and s_tag.
Referenced by internal_probe_sniff().