@@ -123,6 +123,49 @@ bool TileProcessorCompress::preCompressTile([[maybe_unused]] size_t thread_id)
123123 return false ;
124124 auto unreducedTileComp = tileComp;
125125 tileComp->createWindow (Rect32 (unreducedTileComp));
126+
127+ // 16-bit forward DWT eligibility.
128+ //
129+ // Reversible 5/3 (ITU-T T.800 Annex F.3.4):
130+ // The 5/3 analysis lifting steps are:
131+ // D[n] -= floor((S[n] + S[n+1]) / 2) (prediction)
132+ // S[n] += floor((D[n-1] + D[n] + 2) / 4) (update)
133+ // BIBO (Bounded-Input Bounded-Output) gain analysis shows intermediate
134+ // values can grow by at most 2^3 (≤6 levels) or 2^4 (>6 levels), plus
135+ // 1 extra bit when the reversible colour transform (RCT, ITU-T T.800
136+ // Annex G.2) is applied. The update step uses an overflow-safe
137+ // averaging operator (see WaveletFwd.cpp) so only the prediction step's
138+ // pre-accumulation headroom limits the working precision:
139+ // prec + headroom ≤ 16
140+ // where headroom = 4 (no MCT) or 5 (MCT, RCT component).
141+ //
142+ // Irreversible 9/7 (ITU-T T.800 Annex F.3.5):
143+ // The 9/7 analysis uses four lifting steps with coefficients
144+ // α=-1.586, β=-0.053, γ=0.883, δ=0.444 followed by K-scaling.
145+ // Because the lowpass BIBO gain per level ≈ 6× (dominated by the large
146+ // |α| coefficient), intermediate values compound across decomposition
147+ // levels. Fixed-point 16-bit processing is feasible only when
148+ // prec + 6 ≤ 16 → prec ≤ 10.
149+ // The implementation uses an odd-branch (high-pass) halving strategy
150+ // that stores D samples at half magnitude through the lifting chain,
151+ // with adjusted coefficients and a normalizing factor computed from
152+ // BIBO gains (see WaveletFwd.cpp).
153+ // MCT components are excluded because the irreversible colour transform
154+ // (ICT) operates on float buffers.
155+ auto tccp = tcp_->tccps_ + compno;
156+ if (tccp->qmfbid_ == 1 )
157+ {
158+ bool isMctComp = needsMctDecompress (compno) && tcp_->mct_ == 1 ;
159+ uint32_t headroom = isMctComp ? 5 : 4 ;
160+ if (imageComp->prec + headroom <= 16 )
161+ tileComp->setUse16BitDwt (true );
162+ }
163+ else if (tccp->qmfbid_ == 0 )
164+ {
165+ bool isMctComp = needsMctDecompress (compno) && tcp_->mct_ == 1 ;
166+ if (!isMctComp && imageComp->prec + 6 <= 16 )
167+ tileComp->setUse16BitDwt (true );
168+ }
126169 }
127170 uint32_t numTiles = (uint32_t )cp_->t_grid_height_ * cp_->t_grid_width_ ;
128171
0 commit comments