nx_jpeg_idct.nx
buildroot/runtime/nx_jpeg_idct.nx
about
nx_jpeg_idct.nx -- 8x8 inverse DCT for JPEG decode.
Implements the separable row-then-column inverse DCT-II per the
ITU-T Rec. T.81 Annex A.3.3 / IEEE 1180-1990 (Standard
Specifications for the Implementations of 8x8 Inverse Discrete
Cosine Transform).
Math (natural-order coefficients F[u,v], output samples s[x,y]):
s[x,y] = (1/4) * sum_{u=0..7} sum_{v=0..7}
Cu * Cv * F[u,v]
* cos((2x+1) u pi / 16)
* cos((2y+1) v pi / 16)
where C0 = 1/sqrt(2), Ck = 1 for k > 0
We use the well-known AAN-equivalent fixed-point factorisation:
scale the coefficients by per-position constants that fold the
1/4 and Cu Cv factors into the quantization table, then do a
pure cosine-sum. This file uses the direct cosine-sum form for
clarity + simplicity; performance optimisation is a follow-on
stone once nx_jpeg_decode is end-to-end working with real JPEGs.
All arithmetic is integer fixed-point: we multiply by 2^12 = 4096
to give cosines 12 fractional bits, do the 16-bit-input * 12-bit-cosine
arithmetic in i64 (no overflow), and right-shift the final result
back by FX_SHIFT + 3 = 15 bits (the 1/4 = >>2 plus row/col combine
shift; AAN literature explains this).
Substrate-honesty: this is the unoptimised reference implementation.
1024 muls + 1024 adds per 8x8 block. Real decoders use Loeffler-
Lieberknecht-Moschytz (LLM) factorisation for ~16 muls + 26 adds
per row. That swap is a future arc once the full JPEG pipeline
is proven end-to-end against real images.
nx_safety_envelope:
intended_use: "Inverse 8x8 DCT for JPEG decode pipeline."
sil_target: SIL1
evidence: [t81_annex_a3_3_canonical_basis,
ieee1180_1990_conformance_target,
dependencies 1 imports · 4 importers
imports: nx_syscalls.nx
imported by: nx_jpeg_idct_test.nxnx_jpeg_mcu.nxnx_jpeg_mcu_test.nxnx_jpeg_progressive.nx
structs
| none |
consts
| 50 | const NX_MAGIC_4096: i64 = 4096 |
| 51 | const NX_MAGIC_4017: i64 = 4017 |
| 52 | const NX_MAGIC_3784: i64 = 3784 |
| 53 | const NX_MAGIC_3406: i64 = 3406 |
| 54 | const NX_MAGIC_2896: i64 = 2896 |
| 55 | const NX_MAGIC_2276: i64 = 2276 |
| 56 | const NX_MAGIC_1567: i64 = 1567 |
| 59 | const NX_IDCT_FX_SHIFT: i64 = 12 |
| 60 | const NX_IDCT_FX_ONE: i64 = 4096 // 1 << 12 |
functions
| 84 | func nx_jpeg_idct_init_cos_table(table: *i64) -> i64 |
| 152 | func nx_jpeg_idct_8x8(coeffs: *i64, samples: *i64, cos_tbl: *i64) -> i64 |
| 231 | func nx_jpeg_idct_dc_only_block(dc: i64, samples: *i64) -> i64 called by 1: main |