ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
jof_png_chunk.c
Go to the documentation of this file.
1
20
21#include <stddef.h>
22#include <stdint.h>
23#include <string.h>
24
25#include "jof_internal.h"
26#include "jof_png_internal.h"
27#include "ra8_attributes.h"
28#include "ra8_err.h"
29
48{
49 uint32_t done = 0U;
50 while (done < len) {
51 size_t got = 0U;
52 const ra8_err_t err = st->pull(st->pull_ctx, &buf[done], (size_t)(len - done), &got);
53 if (err != k_ra8_ok) {
54 return err;
55 }
56 if (got == 0U) {
58 }
59 done += (uint32_t)got;
60 }
61 return k_ra8_ok;
62}
63
81{
82 uint8_t scratch[k_ra8_png_skip_chunk];
83 uint32_t left = len;
84 while (left > 0U) {
85 const uint32_t take =
86 (left < (uint32_t)k_ra8_png_skip_chunk) ? left : (uint32_t)k_ra8_png_skip_chunk;
87 const ra8_err_t err = priv_jof_png_pull_exact(st, scratch, take);
88 if (err != k_ra8_ok) {
89 return err;
90 }
91 left -= take;
92 }
93 return k_ra8_ok;
94}
95
114 uint32_t* out_len,
115 uint32_t* out_type)
116{
117 uint8_t hdr[k_ra8_png_chunk_hdr] = {};
118 const ra8_err_t err = priv_jof_png_pull_exact(st, hdr, sizeof(hdr));
119 if (err != k_ra8_ok) {
120 return err;
121 }
122 const uint32_t len = ((uint32_t)hdr[0] << k_ra8_png_be_sh24) |
123 ((uint32_t)hdr[1] << k_ra8_png_be_sh16) |
124 ((uint32_t)hdr[2] << k_ra8_png_be_sh8) | (uint32_t)hdr[3];
125 const uint32_t type = ((uint32_t)hdr[4] << k_ra8_png_be_sh24) |
126 ((uint32_t)hdr[5] << k_ra8_png_be_sh16) |
127 ((uint32_t)hdr[6] << k_ra8_png_be_sh8) | (uint32_t)hdr[7];
128 if (len > (uint32_t)k_ra8_png_max_len) {
130 }
131 *out_len = len;
132 *out_type = type;
133 return k_ra8_ok;
134}
135
151RA8_INTERNAL static uint8_t internal_png_src_channels(uint8_t color_type)
152{
153 switch (color_type) {
155 return (uint8_t)k_ra8_png_ch_1;
157 return (uint8_t)k_ra8_png_ch_3;
159 return (uint8_t)k_ra8_png_ch_1;
161 return (uint8_t)k_ra8_png_ch_2;
163 return (uint8_t)k_ra8_png_ch_4;
164 default:
165 return 0U;
166 }
167}
168
191internal_png_check_ihdr(ra8_png_state_t* st, const uint8_t* ihdr, uint16_t max_w, uint16_t max_h)
192{
193 const uint32_t w32 = ((uint32_t)ihdr[0] << k_ra8_png_be_sh24) |
194 ((uint32_t)ihdr[1] << k_ra8_png_be_sh16) |
195 ((uint32_t)ihdr[2] << k_ra8_png_be_sh8) | (uint32_t)ihdr[3];
196 const uint32_t h32 = ((uint32_t)ihdr[4] << k_ra8_png_be_sh24) |
197 ((uint32_t)ihdr[5] << k_ra8_png_be_sh16) |
198 ((uint32_t)ihdr[6] << k_ra8_png_be_sh8) | (uint32_t)ihdr[7];
199 if ((w32 == 0U) || (w32 > (uint32_t)max_w)) {
201 }
202 if ((h32 == 0U) || (h32 > (uint32_t)max_h)) {
204 }
205 if (ihdr[k_ra8_png_ihdr_ofs_depth] != (uint8_t)k_ra8_png_depth_8) {
207 }
209 if (st->src_ch == 0U) {
211 }
212 if (ihdr[k_ra8_png_ihdr_ofs_compress] != 0U) {
214 }
215 if (ihdr[k_ra8_png_ihdr_ofs_filter] != 0U) {
217 }
218 if (ihdr[k_ra8_png_ihdr_ofs_interlace] != 0U) {
219 return k_ra8_err_not_supported; /* Adam7 breaks streaming; fail closed */
220 }
221 st->w = (uint16_t)w32;
222 st->h = (uint16_t)h32;
224 return k_ra8_ok;
225}
226
248internal_png_parse_ihdr(ra8_png_state_t* st, uint16_t max_w, uint16_t max_h)
249{
250 uint32_t len = 0U;
251 uint32_t type = 0U;
252 ra8_err_t err = priv_jof_png_chunk_hdr(st, &len, &type);
253 if (err != k_ra8_ok) {
254 return err;
255 }
256 if ((type != (uint32_t)k_ra8_png_type_ihdr) || (len != (uint32_t)k_ra8_png_ihdr_len)) {
258 }
259 uint8_t ihdr[k_ra8_png_ihdr_len] = {};
260 err = priv_jof_png_pull_exact(st, ihdr, sizeof(ihdr));
261 if (err != k_ra8_ok) {
262 return err;
263 }
264 err = internal_png_check_ihdr(st, ihdr, max_w, max_h);
265 if (err != k_ra8_ok) {
266 return err;
267 }
268 return priv_jof_png_skip(st, (uint32_t)k_ra8_png_crc_bytes);
269}
270
290{
291 if ((len == 0U) || ((len % (uint32_t)k_ra8_png_ch_3) != 0U) ||
292 (len > (uint32_t)k_ra8_png_plte_max) || (st->has_plte != 0U)) {
294 }
295 const ra8_err_t err = priv_jof_png_pull_exact(st, st->palette, len);
296 if (err != k_ra8_ok) {
297 return err;
298 }
299 st->plte_count = (uint16_t)(len / (uint32_t)k_ra8_png_ch_3);
300 st->has_plte = 1U;
301 return priv_jof_png_skip(st, (uint32_t)k_ra8_png_crc_bytes);
302}
303
325{
326 if (st->color_type != (uint8_t)k_ra8_png_color_pal) {
328 }
329 if ((len > (uint32_t)k_ra8_png_trns_max) || (st->has_plte == 0U) || (st->has_trns != 0U)) {
331 }
332 const ra8_err_t err = priv_jof_png_pull_exact(st, st->trns, len);
333 if (err != k_ra8_ok) {
334 return err;
335 }
336 st->trns_count = (uint16_t)len;
337 st->has_trns = 1U;
338 return priv_jof_png_skip(st, (uint32_t)k_ra8_png_crc_bytes);
339}
340
357RA8_PRIV ra8_err_t priv_jof_png_prologue(ra8_png_state_t* st, uint16_t max_w, uint16_t max_h)
358{
359 static const uint8_t s_png_sig[k_ra8_png_sig_bytes] = {k_ra8_png_sig_high,
360 'P',
361 'N',
362 'G',
367 uint8_t sig[k_ra8_png_sig_bytes] = {};
368 const ra8_err_t err = priv_jof_png_pull_exact(st, sig, sizeof(sig));
369 if (err != k_ra8_ok) {
370 return err;
371 }
372 if (memcmp(sig, s_png_sig, sizeof(sig)) != 0) {
374 }
375 return internal_png_parse_ihdr(st, max_w, max_h);
376}
377
395{
396 if (type == (uint32_t)k_ra8_png_type_plte) {
397 return internal_png_parse_plte(st, len);
398 }
399 if (type == (uint32_t)k_ra8_png_type_trns) {
400 return internal_png_parse_trns(st, len);
401 }
402 if (type == (uint32_t)k_ra8_png_type_iend) {
403 return k_ra8_err_protocol_error; /* IEND before any IDAT */
404 }
405 return priv_jof_png_skip(st, len + (uint32_t)k_ra8_png_crc_bytes);
406}
407
427{
428 uint32_t len = st->pending_len;
429 uint32_t type = st->pending_type;
430 if (st->pending_valid == 0U) {
431 ra8_err_t err = priv_jof_png_skip(st, (uint32_t)k_ra8_png_crc_bytes); /* last IDAT's CRC */
432 if (err != k_ra8_ok) {
433 return err;
434 }
435 err = priv_jof_png_chunk_hdr(st, &len, &type);
436 if (err != k_ra8_ok) {
437 return err;
438 }
439 }
440 for (uint32_t guard = 0U; guard < (uint32_t)k_ra8_png_max_chunks; guard++) {
441 if (type == (uint32_t)k_ra8_png_type_iend) {
442 return k_ra8_ok;
443 }
444 if (type == (uint32_t)k_ra8_png_type_idat) {
445 return k_ra8_err_protocol_error; /* IDAT after the stream completed */
446 }
447 ra8_err_t err = priv_jof_png_skip(st, len + (uint32_t)k_ra8_png_crc_bytes);
448 if (err != k_ra8_ok) {
449 return err;
450 }
451 err = priv_jof_png_chunk_hdr(st, &len, &type);
452 if (err != k_ra8_ok) {
453 return err;
454 }
455 }
457}
Module-private seams shared by the producer translation units.
static ra8_err_t internal_png_parse_ihdr(ra8_png_state_t *st, uint16_t max_w, uint16_t max_h)
Read the IHDR chunk (must be first) and validate its payload.
ra8_err_t priv_jof_png_chunk_hdr(ra8_png_state_t *st, uint32_t *out_len, uint32_t *out_type)
Read one 8-byte chunk header (length + type, both big-endian).
static ra8_err_t internal_png_check_ihdr(ra8_png_state_t *st, const uint8_t *ihdr, uint16_t max_w, uint16_t max_h)
Validate the 13 IHDR payload bytes and bind the geometry fields.
ra8_err_t priv_jof_png_pre_idat(ra8_png_state_t *st, uint32_t len, uint32_t type)
Dispatch one pre-IDAT chunk (PLTE / tRNS / ancillary / stray IEND).
static ra8_err_t internal_png_parse_plte(ra8_png_state_t *st, uint32_t len)
Parse a PLTE chunk into the palette table (colour type 3).
static ra8_err_t internal_png_parse_trns(ra8_png_state_t *st, uint32_t len)
Parse a tRNS chunk (palette alpha; colour type 3 only).
ra8_err_t priv_jof_png_prologue(ra8_png_state_t *st, uint16_t max_w, uint16_t max_h)
Verify the 8-byte signature, then parse + validate the IHDR.
ra8_err_t priv_jof_png_pull_exact(ra8_png_state_t *st, uint8_t *buf, uint32_t len)
Pull exactly len bytes; EOF mid-read is a protocol error.
ra8_err_t priv_jof_png_skip(ra8_png_state_t *st, uint32_t len)
Discard exactly len source bytes (unknown / ancillary chunks).
static uint8_t internal_png_src_channels(uint8_t color_type)
Map an IHDR colour type to its source bytes-per-pixel, or 0.
ra8_err_t priv_jof_png_finish(ra8_png_state_t *st)
Walk the post-IDAT chunks until IEND (ancillary chunks skipped).
Module-private declarations shared by the two PNG decoder units.
@ k_ra8_png_color_rgba
Truecolour + alpha.
@ k_ra8_png_ch_3
3 bytes per pixel.
@ k_ra8_png_color_gray
Grayscale.
@ k_ra8_png_ihdr_ofs_filter
Filter-method offset.
@ k_ra8_png_ihdr_ofs_compress
Compression-method offset.
@ k_ra8_png_be_sh24
Big-endian assembly shifts.
@ k_ra8_png_ihdr_ofs_depth
Bit-depth byte offset.
@ k_ra8_png_color_ga
Grayscale + alpha.
@ k_ra8_png_ihdr_ofs_interlace
Interlace-method offset.
@ k_ra8_png_be_sh16
Big-endian assembly shifts.
@ k_ra8_png_color_pal
Indexed-colour.
@ k_ra8_png_depth_8
Only supported bit depth.
@ k_ra8_png_ch_2
2 bytes per pixel.
@ k_ra8_png_color_rgb
Truecolour.
@ k_ra8_png_ihdr_ofs_color
Colour-type byte offset.
@ k_ra8_png_ch_1
1 byte per pixel.
@ k_ra8_png_ch_4
4 bytes per pixel.
@ k_ra8_png_be_sh8
Big-endian assembly shifts.
@ k_ra8_png_sig_lf
Line feed byte.
@ k_ra8_png_sig_cr
Carriage return byte.
@ k_ra8_png_sig_sub
DOS EOF byte.
@ k_ra8_png_sig_high
High-bit signature byte.
@ k_ra8_png_type_trns
"tRNS" big-endian.
@ k_ra8_png_sig_bytes
Signature length.
@ k_ra8_png_type_ihdr
"IHDR" big-endian.
@ k_ra8_png_skip_chunk
Discard-buffer granularity.
@ k_ra8_png_type_plte
"PLTE" big-endian.
@ k_ra8_png_ihdr_len
IHDR payload length.
@ k_ra8_png_max_chunks
Chunk-walk budget (hostile cap).
@ k_ra8_png_type_idat
"IDAT" big-endian.
@ k_ra8_png_plte_max
Max PLTE payload (256 * 3).
@ k_ra8_png_type_iend
"IEND" big-endian.
@ k_ra8_png_chunk_hdr
Chunk length + type fields.
@ k_ra8_png_trns_max
Max palette tRNS payload.
@ k_ra8_png_max_len
Max legal chunk length.
@ k_ra8_png_crc_bytes
Trailing chunk CRC field.
Annotation-attribute framework macros for ra8-firmware.
#define RA8_PRIV
Module-private helper: shared across TUs but only inside one library.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
Error Code Definitions for ra8-firmware.
@ k_ra8_err_not_supported
Requested feature not compiled in, not wired, or not supported by this MCU variant.
Definition ra8_err.h:180
@ k_ra8_err_validation_failed
Validation rule failed (caller-supplied invariant not satisfied).
Definition ra8_err.h:459
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_protocol_error
Protocol-level error (e.g.
Definition ra8_err.h:429
@ 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
int memcmp(const void *a, const void *b, size_t n)
Compare bytes in two memory areas.
Whole streaming PNG decode state (module-static instance).
uint16_t trns_count
tRNS entries present.
uint32_t pending_type
Pending chunk type (big-endian value).
uint8_t pending_valid
1 when a pending chunk header is held.
uint8_t src_ch
Source bytes per pixel (filter bpp).
void * pull_ctx
Context for pull.
uint32_t pending_len
Pending chunk payload length.
jof_pull_fn pull
Sequential byte source.
uint8_t trns[k_ra8_png_trns_max]
Palette alpha (tRNS).
uint8_t has_trns
1 once tRNS parsed.
uint16_t h
Image height, pixels.
uint16_t plte_count
Palette entries present.
uint8_t palette[k_ra8_png_plte_max]
PLTE payload (RGB triples).
uint8_t has_plte
1 once PLTE parsed.
uint8_t color_type
IHDR colour type.
uint16_t w
Image width, pixels.