ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
ra8_rabook_gray4.c File Reference

Grayscale image transcode – downscale + quantise + nibble-pack (4-bpp) or copy (8-bpp). More...

#include "ra8_rabook_gray4.h"
#include <stdint.h>
#include <string.h>
#include "ra8_attributes.h"
#include "ra8_check.h"
#include "ra8_err.h"
#include "ra8_log.h"
Include dependency graph for ra8_rabook_gray4.c:

Go to the source code of this file.

Enumerations

enum  ra8_gray4_fp_t : uint32_t {
  k_fp_shift = 16U ,
  k_fp_unit = 0x10000U ,
  k_fp_mask = 0xFFFFU ,
  k_fp_norm_shift = 32U
}
 Q16.16 fixed-point constants for the bilinear downscale kernel. More...
enum  ra8_gray4_nib_t : uint8_t {
  k_nib_shift = 4U ,
  k_nib_lo_msk = 1U
}
 Nibble packing constants. More...

Functions

static uint8_t internal_bilinear_sample (const uint8_t *src, uint16_t src_w, uint16_t src_h, uint64_t sx_fp, uint64_t sy_fp)
 Sample one bilinear-interpolated pixel at fixed-point source (sx_fp, sy_fp).
static void internal_pack_nibbles (const uint8_t *gray_pixels, uint32_t n_pixels, uint8_t *out)
 Quantise n_pixels grayscale bytes to 4-bpp nibbles packed into out.
void ra8_rabook_gray4_output_dims (uint16_t src_w, uint16_t src_h, uint16_t max_edge, uint16_t *out_w, uint16_t *out_h)
 Compute scaled output dimensions keeping the longer edge within max_edge.
ra8_err_t ra8_rabook_gray4_downscale (const uint8_t *src, uint16_t src_w, uint16_t src_h, uint8_t *dst, uint16_t dst_w, uint16_t dst_h)
 Bilinear-interpolate a grayscale image from (src_w x src_h) to (dst_w x dst_h).
ra8_err_t ra8_rabook_gray4_encode (const uint8_t *gray_pixels, uint16_t w, uint16_t h, uint8_t *out, uint32_t out_cap, uint32_t *out_size)
 Quantise a grayscale buffer to 16 levels and pack as 4-bpp nibbles.
ra8_err_t ra8_rabook_gray8_encode (const uint8_t *gray_pixels, uint16_t w, uint16_t h, uint8_t *out, uint32_t out_cap, uint32_t *out_size)
 Copy a grayscale buffer out verbatim as 8-bpp (one byte per pixel).

Variables

static const char *const s_tag = "ra8_rabook_gray4"

Detailed Description

Grayscale image transcode – downscale + quantise + nibble-pack (4-bpp) or copy (8-bpp).

Streams decoded grayscale rows through bounded resampling and packs the selected RABOOK pixel representation into caller-owned output storage.

Since
Version 0.1.0

Definition in file ra8_rabook_gray4.c.

Enumeration Type Documentation

◆ ra8_gray4_fp_t

enum ra8_gray4_fp_t : uint32_t

Q16.16 fixed-point constants for the bilinear downscale kernel.

Q16.16 represents 1.0 as 65536; the 32-bit normalisation shift is 32 because each bilinear weight is a 16-bit fractional (product of two 16-bit values = 32 bits of normalisation needed after accumulation).

Since
Version 0.1.0
Enumerator
k_fp_shift 

Integer part starts at bit 16.

k_fp_unit 

1.0 in Q16.16 (65536).

k_fp_mask 

Fractional-bits mask (low 16 bits).

k_fp_norm_shift 

Right-shift to normalise 64-bit product.

Definition at line 33 of file ra8_rabook_gray4.c.

◆ ra8_gray4_nib_t

enum ra8_gray4_nib_t : uint8_t

Nibble packing constants.

Since
Version 0.1.0
Enumerator
k_nib_shift 

Shift even pixel into the high nibble of a byte.

k_nib_lo_msk 

Bit 0: whether pixel index is odd (low nibble).

Definition at line 45 of file ra8_rabook_gray4.c.

Function Documentation

◆ internal_bilinear_sample()

uint8_t internal_bilinear_sample ( const uint8_t * src,
uint16_t src_w,
uint16_t src_h,
uint64_t sx_fp,
uint64_t sy_fp )
static

Sample one bilinear-interpolated pixel at fixed-point source (sx_fp, sy_fp).

Q16.16 coordinates: integer bits select the top-left corner, the fractional bits weight the four neighbours. Clamps sx1/sy1 at the image edge so out-of-bounds samples repeat the last pixel row/column. The four 8-bit neighbours are blended in 64-bit arithmetic and the accumulated product is normalised back down by k_fp_norm_shift.

Parameters
[in]srcGrayscale source: src_w * src_h bytes, one byte per pixel.
[in]src_wSource width in pixels (> 0).
[in]src_hSource height in pixels (> 0).
[in]sx_fpSource x sample point in Q16.16 (< src_w << 16).
[in]sy_fpSource y sample point in Q16.16 (< src_h << 16).
Returns
The interpolated grayscale value (0-255).
Return values
0-255The Q16.16 weighted blend of the four neighbouring source bytes, normalised back to a single 8-bit grayscale sample.
Precondition
src is non-NULL and holds at least src_w * src_h readable bytes.
src_w and src_h are both non-zero.
Postcondition
The return value lies in [0, 255].
src is not modified (read-only sampler).
Note
Not thread-safe in the sense of shared state, but holds none; pure.
Since
Version 0.1.0

Definition at line 84 of file ra8_rabook_gray4.c.

References k_fp_mask, k_fp_norm_shift, k_fp_shift, k_fp_unit, and RA8_ASSERT.

Referenced by ra8_rabook_gray4_downscale().

◆ internal_pack_nibbles()

void internal_pack_nibbles ( const uint8_t * gray_pixels,
uint32_t n_pixels,
uint8_t * out )
static

Quantise n_pixels grayscale bytes to 4-bpp nibbles packed into out.

Each pixel v becomes nibble n = (v + k_ra8_rabook_gray4_round_half) / k_ra8_rabook_gray4_quant_div, clamped to k_ra8_rabook_gray4_nib_max. Even pixels land in the high nibble, odd pixels in the low nibble, matching epub_compile.py byte-for-byte. out must already be zeroed so the trailing high-nibble-only byte of an odd pixel count keeps a zero low half.

Parameters
[in]gray_pixelsGrayscale source: n_pixels readable bytes, 0-255 each.
[in]n_pixelsNumber of pixels to pack (> 0).
[out]outNibble buffer: at least (n_pixels + 1) / 2 zeroed bytes.
Precondition
gray_pixels and out are non-NULL (caller-validated).
out holds at least (n_pixels + 1) / 2 writable, pre-zeroed bytes.
Postcondition
Every packed nibble n satisfies 0 <= n <= k_ra8_rabook_gray4_nib_max.
gray_pixels is not modified (read-only quantisation).
Note
Not thread-safe in the sense of shared state, but holds none; pure.
Since
Version 0.1.0

Definition at line 137 of file ra8_rabook_gray4.c.

References k_nib_lo_msk, k_nib_shift, k_ra8_rabook_gray4_nib_max, k_ra8_rabook_gray4_nib_per_byte, k_ra8_rabook_gray4_quant_div, and k_ra8_rabook_gray4_round_half.

Referenced by ra8_rabook_gray4_encode().

◆ ra8_rabook_gray4_downscale()

ra8_err_t ra8_rabook_gray4_downscale ( const uint8_t * src,
uint16_t src_w,
uint16_t src_h,
uint8_t * dst,
uint16_t dst_w,
uint16_t dst_h )

Bilinear-interpolate a grayscale image from (src_w x src_h) to (dst_w x dst_h).

Each output pixel is the bilinear interpolation of the four nearest source pixels at the corresponding sample point, computed in Q16.16 fixed-point arithmetic (no floating-point, no malloc). The mapping places the sample for output pixel dx at source x = dx * src_w / dst_w (and similarly for y); this is a left-aligned sample grid that is deterministic for any src/dst size pair.

When dst_w == src_w and dst_h == src_h the output is an exact copy. When src_w or src_h is 0 the output is zeroed and k_ra8_ok returned.

Parameters
[in]srcSource buffer: src_w * src_h bytes, one byte per pixel.
[in]src_wSource width in pixels.
[in]src_hSource height in pixels.
[out]dstDestination buffer: must hold dst_w * dst_h writable bytes.
[in]dst_wDestination width (> 0).
[in]dst_hDestination height (> 0).
Returns
Error code.
Return values
k_ra8_okResampled successfully.
k_ra8_err_null_ptrsrc or dst is NULL.
k_ra8_err_invalid_argdst_w or dst_h is 0.
Precondition
src holds at least src_w * src_h readable bytes.
dst holds at least dst_w * dst_h writable bytes.
Postcondition
Every byte in dst[0..dst_w*dst_h) holds the interpolated value.
The source buffer is unchanged.
Note
Not thread-safe.
Since
Version 0.1.0

Definition at line 194 of file ra8_rabook_gray4.c.

References internal_bilinear_sample(), k_fp_shift, k_ra8_err_invalid_arg, k_ra8_ok, memset(), RA8_CHECK_NULL_PTR, ra8_log_error, and s_tag.

Referenced by internal_downscale_if_needed(), and internal_scale().

◆ ra8_rabook_gray4_encode()

ra8_err_t ra8_rabook_gray4_encode ( const uint8_t * gray_pixels,
uint16_t w,
uint16_t h,
uint8_t * out,
uint32_t out_cap,
uint32_t * out_size )

Quantise a grayscale buffer to 16 levels and pack as 4-bpp nibbles.

For each source pixel v the nibble is n = (v + 8) / 17, clamped to [0, 15] (round-to-nearest quantisation to the 16-level palette at {0, 17, 34, ..., 255}). Pairs of nibbles are packed one per byte: byte[i] = (nib[2i] << 4) | nib[2i+1]. For an odd pixel count the last byte holds the final nibble in its high half and its low half is zero.

Output size is ceil(w * h / 2) == (w * h + 1) / 2 bytes.

The packing order is byte-identical to epub_compile.py for the same input pixel values.

Parameters
[in]gray_pixelsGrayscale source: w * h bytes, 0-255 each.
[in]wImage width in pixels.
[in]hImage height in pixels.
[out]outOutput nibble buffer; must hold at least (w*h+1)/2 bytes.
[in]out_capCapacity of out in bytes.
[out]out_sizeOn success: bytes written (== (w*h+1)/2).
Returns
Error code.
Return values
k_ra8_okEncoded successfully.
k_ra8_err_null_ptrgray_pixels, out, or out_size is NULL.
k_ra8_err_no_memout_cap < (w*h+1)/2.
Precondition
gray_pixels holds at least w * h readable bytes.
out_cap >= (w * h + 1) / 2.
Postcondition
*out_size == (w * h + 1) / 2.
Every output nibble n satisfies 0 <= n <= 15.
Note
When w or h is 0, *out_size is set to 0 and k_ra8_ok is returned.
Not thread-safe.
Since
Version 0.1.0

Definition at line 229 of file ra8_rabook_gray4.c.

References internal_pack_nibbles(), k_ra8_err_no_mem, k_ra8_ok, k_ra8_rabook_gray4_nib_per_byte, memset(), RA8_CHECK_NULL_PTR, ra8_log_error, and s_tag.

Referenced by internal_encode(), and internal_encode_gray().

◆ ra8_rabook_gray4_output_dims()

void ra8_rabook_gray4_output_dims ( uint16_t src_w,
uint16_t src_h,
uint16_t max_edge,
uint16_t * out_w,
uint16_t * out_h )

Compute scaled output dimensions keeping the longer edge within max_edge.

If max(src_w, src_h) <= max_edge the source dimensions are returned unchanged. Otherwise both dimensions are scaled by max_edge / longer_edge (rounded to nearest, minimum 1 each) so the image fits the panel class without distorting the aspect ratio. The result is the exact size the caller must allocate for the intermediate downscale buffer.

Parameters
[in]src_wSource width in pixels.
[in]src_hSource height in pixels.
[in]max_edgeMaximum allowed length of the longer edge.
[out]out_wScaled output width (>= 1 when src_w, src_h and max_edge are all > 0; 0 otherwise, per the
Note
below).
Parameters
[out]out_hScaled output height (>= 1 when src_w, src_h and max_edge are all > 0; 0 otherwise, per the
Note
below).
Precondition
out_w is non-NULL.
out_h is non-NULL.
Postcondition
If max(src_w, src_h) <= max_edge then *out_w == src_w and *out_h == src_h.
If scaling is required then max(*out_w, *out_h) <= max_edge.
Note
Not thread-safe.
When src_w, src_h, or max_edge is 0 both outputs are set to 0.
Since
Version 0.1.0

Definition at line 159 of file ra8_rabook_gray4.c.

Referenced by internal_output_dims(), and internal_transcode_image().

◆ ra8_rabook_gray8_encode()

ra8_err_t ra8_rabook_gray8_encode ( const uint8_t * gray_pixels,
uint16_t w,
uint16_t h,
uint8_t * out,
uint32_t out_cap,
uint32_t * out_size )

Copy a grayscale buffer out verbatim as 8-bpp (one byte per pixel).

The 8-bpp counterpart of ra8_rabook_gray4_encode, selected when a device profile wants the lossless grayscale source instead of the half-size 4-bpp packing. There is no quantise and no packing: the k_book_pixfmt_gray8 pool bytes ARE the decoded (and possibly downscaled) gray pixels, so out[i] == gray_pixels[i] for every pixel. Keeping it a distinct, validated call – rather than a bare memcpy at the call site – means the transcode stage always states the depth it produced and the capacity is checked once, here.

Output size is w * h bytes (0 when either dimension is 0).

Parameters
[in]gray_pixelsGrayscale source: w * h bytes, 0-255 each.
[in]wImage width in pixels.
[in]hImage height in pixels.
[out]outOutput buffer; must hold at least w * h bytes.
[in]out_capCapacity of out in bytes.
[out]out_sizeOn success: bytes written (== w * h).
Returns
Error code.
Return values
k_ra8_okCopied successfully.
k_ra8_err_null_ptrgray_pixels, out, or out_size is NULL.
k_ra8_err_no_memout_cap < w * h.
Precondition
gray_pixels holds at least w * h readable bytes.
out_cap >= w * h, and out does not overlap gray_pixels.
Postcondition
*out_size == w * h (0 when w or h is 0).
out[0..w*h) equals gray_pixels[0..w*h) byte for byte.
Note
When w or h is 0, *out_size is set to 0 and k_ra8_ok is returned.
Not thread-safe.
See also
ra8_rabook_gray4_encode The 4-bpp (quantise + nibble-pack) counterpart.
Since
Version 0.1.0

Definition at line 260 of file ra8_rabook_gray4.c.

References k_ra8_err_no_mem, k_ra8_ok, memcpy(), RA8_CHECK_NULL_PTR, ra8_log_error, and s_tag.

Referenced by internal_encode(), and internal_encode_gray().

Variable Documentation

◆ s_tag

const char* const s_tag = "ra8_rabook_gray4"
static

Definition at line 50 of file ra8_rabook_gray4.c.