|
ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
|
Pure-software baseline JPEG encoder: pixel pipeline and public API. More...
#include <stdint.h>#include <string.h>#include "ra8_attributes.h"#include "ra8_check.h"#include "ra8_err.h"#include "ra8_jpeg_sw.h"#include "ra8_jpeg_sw_encode_internal.h"#include "ra8_jpeg_sw_internal.h"#include "ra8_log.h"Go to the source code of this file.
Functions | |
| static void | internal_fwd_dct_1d_norm (const int32_t *in, int32_t *out) |
| 1-D forward DCT pass with JPEG normalization folded in. | |
| static void | internal_fdct8x8 (int32_t *block) |
| 2-D forward DCT of one 8x8 block, in place. | |
| static uint16_t | internal_enc_quality_scale (uint8_t q) |
| Compute the IJG quality-scale factor. | |
| static void | internal_enc_scale_qtab (const uint8_t *base, uint8_t *dst, uint16_t scale) |
| Scale a base quantization table by scale/100, clamped to 1..255. | |
| static uint8_t | internal_enc_bits_needed (int32_t v) |
| Compute the number of significant-magnitude bits of v. | |
| static int32_t | internal_enc_quantize (int32_t v, uint8_t qv) |
| Quantize one DCT coefficient with symmetric rounding. | |
| static void | internal_enc_block_ac (ra8_jpeg_enc_ctx_t *e, const int32_t *z, const uint16_t *ac_codes, const uint8_t *ac_sizes) |
| Emit the 63 AC coefficients of one quantized block. | |
| static void | internal_enc_block (ra8_jpeg_enc_ctx_t *e, const int32_t *spatial, const uint8_t *qtab, uint8_t comp_idx, const uint16_t *dc_codes, const uint8_t *dc_sizes, const uint16_t *ac_codes, const uint8_t *ac_sizes) |
| Encode one 8x8 block of source samples. | |
| static void | internal_enc_rgb_to_ycc_row (const uint8_t *rgb, uint16_t n, int32_t *y, int32_t *cb, int32_t *cr) |
| Convert one row of RGB into Y, Cb, Cr samples (BT.601 Q16). | |
| static void | internal_enc_sample_y_block (const int32_t *yplane, uint16_t plane_w, uint16_t plane_h, uint16_t x0, uint16_t y0, int32_t *out) |
| Sample one 8x8 luma block from the Y plane (clamp-to-edge). | |
| static int32_t | internal_enc_avg_2x2 (const int32_t *cplane, uint16_t plane_w, uint16_t plane_h, uint16_t sx, uint16_t sy) |
| Average the 2x2 chroma neighbourhood at (sx, sy), clamped. | |
| static void | internal_enc_sample_c_block_420 (const int32_t *cplane, uint16_t plane_w, uint16_t plane_h, uint16_t x0, uint16_t y0, int32_t *out) |
| Build one 8x8 chroma block by 2x2 averaging from a 16x16 region. | |
| static void | internal_enc_convert_strip_to_ycc (const uint8_t *rgb, uint16_t w, uint16_t h, uint16_t pad_w, uint16_t mby, int32_t *y_strip, int32_t *cb_strip, int32_t *cr_strip, uint8_t *tmp_rgb) |
| Convert 16 source RGB rows into Y / Cb / Cr 16-row strips. | |
| static void | internal_enc_encode_mcu_row (ra8_jpeg_enc_ctx_t *e, uint16_t pad_w, const int32_t *y_strip, const int32_t *cb_strip, const int32_t *cr_strip) |
| Encode every 16x16 MCU in a 16-row YCbCr strip. | |
| static ra8_err_t | internal_enc_run (ra8_jpeg_enc_ctx_t *e, const uint8_t *rgb, uint16_t w, uint16_t h, uint8_t quality) |
| Top-level encode driver – emits the full JFIF byte stream. | |
| 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. | |
Variables | |
| static const char * | s_tag = "JPEG_SW" |
| Component log tag. | |
| static const uint8_t | s_quant_luma [64] |
| T.81 Annex K.1 luma quantization table. | |
| static const uint8_t | s_quant_chroma [64] |
| T.81 Annex K.1 chroma quantization table. | |
Pure-software baseline JPEG encoder: pixel pipeline and public API.
Implements ra8_jpeg_sw_encode() for baseline (8-bit, sequential, Huffman) JPEG output in the YCbCr 4:2:0 layout. The reference codec is the write_JPEG_file() example shipped with the IJG libjpeg sources and the matching pseudo-code in ITU-T T.81 Annex K; it has been re-implemented here from scratch in this project's style and naming conventions, with no third-party code copied.
This unit owns the pixel pipeline: RGB->YCbCr strip conversion, luma/chroma block sampling, the forward DCT, quantization and the per-block Huffman emission driver. The byte/bit emitters, the Annex K.3.3 reference tables and the JFIF header writers live in ra8_jpeg_sw_encode_emit.c; the symbols shared between the two units are declared in ra8_jpeg_sw_encode_internal.h. The decoder half and the shared entropy/DSP primitives live in ra8_jpeg_sw.c, with cross-unit symbols in ra8_jpeg_sw_internal.h.
Spec citations are tagged T.81 sec X.Y "..." and refer to ITU-T Recommendation T.81 (1992) | ISO/IEC 10918-1.
Definition in file ra8_jpeg_sw_encode.c.
|
static |
Average the 2x2 chroma neighbourhood at (sx, sy), clamped.
Sums the four plane samples of the 2x2 window whose top-left corner is (sx, sy), clamping each coordinate to the plane edge, and returns the integer mean – the 4:2:0 sub-sampling kernel of internal_enc_sample_c_block_420().
| [in] | cplane | Chroma plane (plane_w samples per row). |
| [in] | plane_w | Plane width in samples. |
| [in] | plane_h | Plane height in rows. |
| [in] | sx | Window left edge. |
| [in] | sy | Window top edge. |
| 0..255 | For chroma planes in the nominal range. |
Definition at line 508 of file ra8_jpeg_sw_encode.c.
References RA8_INTERNAL.
Referenced by internal_enc_sample_c_block_420().
|
static |
Compute the number of significant-magnitude bits of v.
T.81 Table F.1 SSSS category: bit length of |v|, with 0 mapping to category 0.
| [in] | v | Coefficient difference or value. |
| 0 | v is zero. |
| 1..31 | Bit length of |v| otherwise. |
Definition at line 229 of file ra8_jpeg_sw_encode.c.
References RA8_INTERNAL.
Referenced by internal_enc_block(), and internal_enc_block_ac().
|
static |
Encode one 8x8 block of source samples.
Forward-DCTs the spatial block, quantizes it in zig-zag order, emits the DC difference (T.81 sec F.1.2.1) and hands the AC coefficients to internal_enc_block_ac().
| [in,out] | e | Encoder context (DC predictor + bits mutate). |
| [in] | spatial | 64-entry level-shifted sample block. |
| [in] | qtab | Scaled quant table for this component. |
| [in] | comp_idx | Component index (0 luma, 1 Cb, 2 Cr). |
| [in] | dc_codes | DC Huffman code LUT. |
| [in] | dc_sizes | DC Huffman code-length LUT. |
| [in] | ac_codes | AC Huffman code LUT. |
| [in] | ac_sizes | AC Huffman code-length LUT. |
Definition at line 355 of file ra8_jpeg_sw_encode.c.
References ra8_jpeg_enc_ctx_t::dc_pred, internal_enc_bits_needed(), internal_enc_block_ac(), internal_enc_quantize(), internal_fdct8x8(), k_ra8_jpeg_block_size, priv_jpeg_sw_enc_put_bits(), RA8_INTERNAL, and s_zigzag.
Referenced by internal_enc_encode_mcu_row().
|
static |
Emit the 63 AC coefficients of one quantized block.
T.81 sec F.1.2.2 run-length coding: zero runs of 16 emit ZRL (0xF0), each non-zero coefficient emits its (RRRR,SSSS) symbol followed by the magnitude bits, and a trailing zero run emits EOB.
| [in,out] | e | Encoder context (bit buffer mutates). |
| [in] | z | 64-entry zig-zag-ordered quantized block. |
| [in] | ac_codes | AC Huffman code LUT for this component. |
| [in] | ac_sizes | AC Huffman code-length LUT. |
Definition at line 300 of file ra8_jpeg_sw_encode.c.
References internal_enc_bits_needed(), k_jpeg_zrl_symbol, k_ra8_jpeg_block_size, k_ra8_jpeg_nibble_shift, priv_jpeg_sw_enc_put_bits(), and RA8_INTERNAL.
Referenced by internal_enc_block().
|
static |
Convert 16 source RGB rows into Y / Cb / Cr 16-row strips.
For each of 16 output rows, replicates the right-edge / bottom-edge source pixels (clamp-to-edge) so that the YCbCr strips cover the full pad_w width and the requested vertical strip starting at mby. Uses the caller-provided scratch RGB buffer for one row at a time, so the chroma sub-sampling later in internal_enc_sample_c_block_420() sees fully-populated planes.
| [in] | rgb | Source RGB888 image of size w*h. |
| [in] | w | Source image width in pixels. |
| [in] | h | Source image height in pixels. |
| [in] | pad_w | Padded (16-aligned) strip width. |
| [in] | mby | Strip start row in the padded image. |
| [out] | y_strip | Output Y plane of pad_w * 16 samples. |
| [out] | cb_strip | Output Cb plane of pad_w * 16 samples. |
| [out] | cr_strip | Output Cr plane of pad_w * 16 samples. |
| [out] | tmp_rgb | Scratch RGB row buffer of pad_w*3 bytes. |
Definition at line 601 of file ra8_jpeg_sw_encode.c.
References internal_enc_rgb_to_ycc_row(), k_ra8_jpeg_rgb_components, and RA8_INTERNAL.
Referenced by internal_enc_run().
|
static |
Encode every 16x16 MCU in a 16-row YCbCr strip.
For each MCU column inside pad_w, samples four 8x8 luma blocks at (0,0)(8,0)(0,8)(8,8), then two sub-sampled 8x8 chroma blocks (Cb,Cr). Each block is fed through internal_enc_block() with the matching quant table and Huffman LUTs, which emits the entropy-coded bits into the encoder context.
| [in,out] | e | Encoder context (bit-buffer mutates). |
| [in] | pad_w | Padded strip width (multiple of 16). |
| [in] | y_strip | Luma plane samples for this strip. |
| [in] | cb_strip | Cb plane samples for this strip. |
| [in] | cr_strip | Cr plane samples for this strip. |
Definition at line 660 of file ra8_jpeg_sw_encode.c.
References ra8_jpeg_enc_ctx_t::code_ac_c, ra8_jpeg_enc_ctx_t::code_ac_l, ra8_jpeg_enc_ctx_t::code_dc_c, ra8_jpeg_enc_ctx_t::code_dc_l, internal_enc_block(), internal_enc_sample_c_block_420(), internal_enc_sample_y_block(), k_ra8_jpeg_block_size, ra8_jpeg_enc_ctx_t::qc, ra8_jpeg_enc_ctx_t::qy, RA8_INTERNAL, ra8_jpeg_enc_ctx_t::size_ac_c, ra8_jpeg_enc_ctx_t::size_ac_l, ra8_jpeg_enc_ctx_t::size_dc_c, and ra8_jpeg_enc_ctx_t::size_dc_l.
Referenced by internal_enc_run().
|
static |
Compute the IJG quality-scale factor.
Maps the user quality 1..100 onto the IJG percentage scale: 5000/q below the pivot (50), 200 - 2q at or above it.
| [in] | q | Quality setting (1..100, caller-validated). |
| 5000..100 | For q in 1..49. |
| 100..0 | For q in 50..100. |
Definition at line 170 of file ra8_jpeg_sw_encode.c.
References k_jpeg_q_scale_high, k_jpeg_q_scale_low, k_ra8_jpeg_quality_pivot, and RA8_INTERNAL.
Referenced by internal_enc_run().
|
static |
Quantize one DCT coefficient with symmetric rounding.
Divides by the quant-table entry with round-half-away-from- zero semantics; a zero table entry is clamped to 1 as a divide-by-zero guard.
| [in] | v | Raw DCT coefficient. |
| [in] | qv | Quant-table divisor entry. |
| 0 | |v| below half the divisor. |
| non-zero | Rounded quotient otherwise. |
Definition at line 262 of file ra8_jpeg_sw_encode.c.
References RA8_INTERNAL.
Referenced by internal_enc_block().
|
static |
Convert one row of RGB into Y, Cb, Cr samples (BT.601 Q16).
Fixed-point BT.601 forward transform using the same Q16 coefficients as IJG jccolor.c; chroma outputs carry the +128 level offset.
| [in] | rgb | Packed RGB888 row (n pixels). |
| [in] | n | Pixel count. |
| [out] | y | Luma output row. |
| [out] | cb | Cb output row (level-offset applied). |
| [out] | cr | Cr output row (level-offset applied). |
Definition at line 416 of file ra8_jpeg_sw_encode.c.
References k_ra8_jpeg_cbb, k_ra8_jpeg_cbg, k_ra8_jpeg_cbr, k_ra8_jpeg_crb, k_ra8_jpeg_crg, k_ra8_jpeg_crr, k_ra8_jpeg_level_offset, k_ra8_jpeg_rgb_components, k_ra8_jpeg_yb, k_ra8_jpeg_yg, k_ra8_jpeg_yr, and k_ra8_jpeg_yuv_shift.
Referenced by internal_enc_convert_strip_to_ycc().
|
static |
Top-level encode driver – emits the full JFIF byte stream.
Builds the quant tables and Huffman LUTs, emits the header segments, streams the image through 16-row YCbCr strips (bounded working set), then flushes the entropy bits and closes the stream with EOI.
| [in,out] | e | Zeroed encoder context bound to the output buffer. |
| [in] | rgb | Source RGB888 image. |
| [in] | w | Image width in pixels. |
| [in] | h | Image height in pixels. |
| [in] | quality | IJG quality setting (1..100). |
| k_ra8_ok | Stream complete in e->dst[0..e->pos). |
| k_ra8_err_invalid_arg | Padded width exceeds the encoder cap. |
| k_ra8_err_invalid_size | Output buffer overflowed. |
Definition at line 726 of file ra8_jpeg_sw_encode.c.
References internal_enc_convert_strip_to_ycc(), internal_enc_encode_mcu_row(), internal_enc_quality_scale(), internal_enc_scale_qtab(), k_jpeg_mcu_align, k_ra8_err_invalid_arg, k_ra8_err_invalid_size, k_ra8_jpeg_enc_max_w, k_ra8_jpeg_marker_eoi, k_ra8_ok, ra8_jpeg_enc_ctx_t::overflow, priv_jpeg_sw_enc_build_huff(), priv_jpeg_sw_enc_emit_u16(), priv_jpeg_sw_enc_flush_bits(), priv_jpeg_sw_enc_headers(), ra8_jpeg_enc_ctx_t::qc, ra8_jpeg_enc_ctx_t::qy, s_quant_chroma, and s_quant_luma.
Referenced by ra8_jpeg_sw_encode().
|
static |
Build one 8x8 chroma block by 2x2 averaging from a 16x16 region.
Each destination sample is the internal_enc_avg_2x2() mean of the matching 2x2 source window, level-shifted by -128 for the DCT – the 4:2:0 chroma sub-sampling step.
| [in] | cplane | Chroma plane (plane_w samples per row). |
| [in] | plane_w | Plane width in samples. |
| [in] | plane_h | Plane height in rows. |
| [in] | x0 | Source region left edge. |
| [in] | y0 | Source region top edge. |
| [out] | out | 64-entry destination block. |
Definition at line 555 of file ra8_jpeg_sw_encode.c.
References internal_enc_avg_2x2(), k_ra8_jpeg_block_dim, k_ra8_jpeg_level_offset, and RA8_INTERNAL.
Referenced by internal_enc_encode_mcu_row().
|
static |
Sample one 8x8 luma block from the Y plane (clamp-to-edge).
Reads an 8x8 window at (x0, y0), clamping out-of-range coordinates to the plane edge, and level-shifts each sample by -128 for the DCT.
| [in] | yplane | Luma plane (plane_w samples per row). |
| [in] | plane_w | Plane width in samples. |
| [in] | plane_h | Plane height in rows. |
| [in] | x0 | Window left edge. |
| [in] | y0 | Window top edge. |
| [out] | out | 64-entry destination block. |
Definition at line 459 of file ra8_jpeg_sw_encode.c.
References k_ra8_jpeg_block_dim, k_ra8_jpeg_level_offset, and RA8_INTERNAL.
Referenced by internal_enc_encode_mcu_row().
|
static |
Scale a base quantization table by scale/100, clamped to 1..255.
Applies the IJG rounding form (base*scale + 50) / 100 per entry and clamps into the legal 8-bit DQT range.
| [in] | base | 64-entry Annex K.1 base table. |
| [out] | dst | 64-entry destination table. |
| [in] | scale | Percentage from internal_enc_quality_scale(). |
Definition at line 196 of file ra8_jpeg_sw_encode.c.
References k_jpeg_q_percent, k_jpeg_q_round_bias, k_ra8_jpeg_block_size, k_ra8_jpeg_pixel_max, and RA8_INTERNAL.
Referenced by internal_enc_run().
|
static |
2-D forward DCT of one 8x8 block, in place.
Separable two-pass transform: internal_fwd_dct_1d_norm() over the rows, then over the columns of the intermediate result.
| [in,out] | block | 64-entry row-major sample block, DCTed in place. |
Definition at line 120 of file ra8_jpeg_sw_encode.c.
References internal_fwd_dct_1d_norm(), k_ra8_jpeg_block_dim, k_ra8_jpeg_block_size, and RA8_INTERNAL.
Referenced by internal_enc_block().
|
static |
1-D forward DCT pass with JPEG normalization folded in.
Computes Y[k] = sqrt(2/N)*C(k) * sum_n y[n]*cos((2n+1)*k*pi/16) over the shared Q14 cosine basis, so the encoder and decoder use a numerically identical transform pair.
| [in] | in | 8-entry spatial sample row/column. |
| [out] | out | 8-entry frequency coefficient row/column. |
Definition at line 90 of file ra8_jpeg_sw_encode.c.
References k_jpeg_idct_p1_bias_sh, k_jpeg_idct_p1_sh, k_ra8_jpeg_block_dim, RA8_INTERNAL, s_dct_cos_q14, and s_dct_w_q14.
Referenced by internal_fdct8x8().
|
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().
|
static |
T.81 Annex K.1 chroma quantization table.
Definition at line 61 of file ra8_jpeg_sw_encode.c.
Referenced by internal_enc_run().
|
static |
T.81 Annex K.1 luma quantization table.
Definition at line 54 of file ra8_jpeg_sw_encode.c.
Referenced by internal_enc_run().
|
static |
Component log tag.
Definition at line 47 of file ra8_jpeg_sw_encode.c.