1use core::fmt;
6use std::time::Instant;
7
8use j2k::{
9 CpuOnlyJ2kEncodeStageAccelerator, J2kEncodeDispatchReport, J2kEncodeStageAccelerator,
10 J2kForwardDwt53Level, J2kForwardDwt53Output, J2kForwardDwt97Level, J2kForwardDwt97Output,
11 PrecomputedHtj2k53Component, PrecomputedHtj2k53Image, PrecomputedHtj2k97Component,
12 PrecomputedHtj2k97Image, PreencodedHtj2k97CompactComponent, PreencodedHtj2k97CompactImage,
13 PreencodedHtj2k97Component, PreencodedHtj2k97Image, PrequantizedHtj2k97Component,
14 PrequantizedHtj2k97Image,
15};
16use j2k_jpeg::transcode::{
17 extract_dct_blocks, idct_islow_block, DctExtractOptions, JpegDctComponent, JpegDctImage,
18};
19use j2k_native::{
20 encode_precomputed_htj2k_53_with_accelerator_and_max_host_bytes,
21 encode_precomputed_htj2k_97_batch_owned_with_accelerator_and_max_host_bytes,
22 encode_precomputed_htj2k_97_with_accelerator_and_max_host_bytes,
23 encode_preencoded_htj2k_97_compact_owned_with_accelerator_and_max_host_bytes,
24 encode_preencoded_htj2k_97_compact_owned_with_accelerator_and_max_host_bytes_and_required_magnitude_bound,
25 encode_preencoded_htj2k_97_owned_with_accelerator_and_max_host_bytes,
26 encode_preencoded_htj2k_97_owned_with_accelerator_and_max_host_bytes_and_required_magnitude_bound,
27 encode_prequantized_htj2k_97_with_accelerator_and_max_host_bytes,
28};
29use rayon::prelude::*;
30
31use crate::allocation::try_vec_with_capacity;
32use crate::dct53_2d::{
33 dct8x8_blocks_then_dwt53_float, dct8x8_blocks_to_dwt53_float_linear_with_scratch,
34 linearized_53_2d_from_plane, Dct53GridScratch,
35};
36use crate::dct97_2d::{
37 dct8x8_blocks_then_dwt97_float, dct8x8_blocks_then_dwt97_float_with_scratch,
38 linearized_97_2d_from_plane_with_scratch, Dct97GridScratch,
39};
40use crate::metrics::{error_metrics_i32_with_live_budget, ErrorMetrics, MetricsError};
41use crate::reversible53::{
42 reversible_lift_53_high_at_fallible, reversible_lift_53_i32, reversible_lift_53_low_at_fallible,
43};
44use crate::{
45 CpuOnlyDctToWaveletStageAccelerator, DctGridI16ToHtj2k97CodeBlockBatch,
46 DctGridI16ToHtj2k97CodeBlockJob, DctGridToDwt53Job, DctGridToDwt97Job,
47 DctGridToHtj2k97CodeBlockJob, DctGridToReversibleDwt53Job, DctToWaveletStageAccelerator,
48 DctTransformError, Dwt53TwoDimensional, Dwt97BatchStageTimings, Dwt97TwoDimensional,
49 Htj2k97CodeBlockOptions, ReversibleDwt53FirstLevel, TranscodeStageError,
50};
51
52mod options;
53pub use self::options::{
54 JpegToHtj2kCoefficientPath, JpegToHtj2kEncodeOptions, JpegToHtj2kOptions,
55 JPEG_TO_HTJ2K_LOSSY_97_QUANTIZATION_SCALE,
56};
57mod report;
58pub use self::report::{
59 BatchTranscodeReport, TranscodeBatchProfileRequest, TranscodeBatchProfileRow,
60 TranscodeComponentReport, TranscodeReport, TranscodeTimingReport,
61 TranscodeValidationClassification, TranscodeValidationMetrics,
62};
63mod error;
64use self::error::{dct53_transform_error, dct97_transform_error, map_encode_error};
65pub use self::error::{Htj2kEncodeError, Htj2kEncodeErrorKind, JpegToHtj2kError};
66mod validation;
67use self::validation::{
68 component_sampling_for_jpeg, decomposition_levels_for_components,
69 validate_component_block_grid, validate_transcode_options,
70};
71mod workspace;
72use self::workspace::validate_jpeg_transcode_workspace;
73mod scratch;
74use self::scratch::JpegToHtj2kScratch;
75mod output;
76pub use self::output::{EncodedTranscode, EncodedTranscodeBatch, JpegTileBatchInput};
77mod live_budget;
78use self::live_budget::{
79 encoded_transcode_retained_bytes, precomputed_batch_retained_bytes,
80 validation_metrics_retained_bytes, HostLiveBudget,
81};
82mod component_plan;
83use self::component_plan::{
84 integer_dct_job_for_component, transcode_component_batch, transcode_path_name,
85 ComponentBatchRequest, ComponentTranscodeBatch, PrecomputedComponentBatch,
86};
87mod component_groups;
88use self::component_groups::same_geometry_component_groups;
89mod float_reference;
90use self::float_reference::{
91 dct_blocks_to_8x8_f64, decompose_97_from_first_level, float97_reference_coefficients,
92 float_direct_97_wavelet_from_component, float_direct_wavelet_from_component,
93 float_reference_coefficients, ComponentWavelet, ComponentWavelet97,
94};
95mod float_output;
96use self::float_output::{
97 j2k_dwt97_from_wavelet, j2k_dwt_from_integer_wavelet, j2k_dwt_from_wavelet,
98 rounded_wavelet97_i32, rounded_wavelet_i32,
99};
100mod integer_reference;
101use self::integer_reference::{
102 flatten_integer_wavelet, integer_direct_wavelet_from_component, integer_reference_coefficients,
103 integer_wavelet_from_first_level, IntegerWavelet,
104};
105mod integer_storage;
106mod single;
107use self::single::jpeg_to_htj2k_with_scratch;
108mod single_tile_encode;
109use self::single_tile_encode::encode_component_batch;
110mod batch;
111pub use self::batch::jpeg_to_htj2k_batch;
112#[cfg(test)]
113use self::batch::{
114 encode_float97_prepared_tiles, store_compact_preencoded_component,
115 transform_float97_batch_tiles, Float97BatchTile,
116};
117use self::batch::{
118 jpeg_tile_batch_to_htj2k_with_scratch, record_accelerator_attempt, record_accelerator_dispatch,
119 record_batch_attempt, record_cpu_fallback, record_encode_dispatch_delta,
120};
121
122#[derive(Debug, Default)]
128pub struct JpegToHtj2kTranscoder {
129 scratch: JpegToHtj2kScratch,
130}
131
132impl JpegToHtj2kTranscoder {
133 pub fn transcode(
136 &mut self,
137 bytes: &[u8],
138 options: &JpegToHtj2kOptions,
139 ) -> Result<EncodedTranscode, JpegToHtj2kError> {
140 let mut accelerator = CpuOnlyDctToWaveletStageAccelerator;
141 self.transcode_with_accelerator(bytes, options, &mut accelerator)
142 }
143
144 pub fn transcode_with_accelerator<A: DctToWaveletStageAccelerator>(
150 &mut self,
151 bytes: &[u8],
152 options: &JpegToHtj2kOptions,
153 accelerator: &mut A,
154 ) -> Result<EncodedTranscode, JpegToHtj2kError> {
155 let mut encode_accelerator = CpuOnlyJ2kEncodeStageAccelerator;
156 self.transcode_with_accelerators(bytes, options, accelerator, &mut encode_accelerator)
157 }
158
159 pub fn transcode_with_accelerators<
162 A: DctToWaveletStageAccelerator,
163 E: J2kEncodeStageAccelerator,
164 >(
165 &mut self,
166 bytes: &[u8],
167 options: &JpegToHtj2kOptions,
168 transform_accelerator: &mut A,
169 encode_accelerator: &mut E,
170 ) -> Result<EncodedTranscode, JpegToHtj2kError> {
171 jpeg_to_htj2k_with_scratch(
172 bytes,
173 options,
174 &mut self.scratch,
175 transform_accelerator,
176 encode_accelerator,
177 0,
178 )
179 }
180
181 pub fn transcode_batch(
185 &mut self,
186 tiles: &[JpegTileBatchInput<'_>],
187 options: &JpegToHtj2kOptions,
188 ) -> Result<EncodedTranscodeBatch, JpegToHtj2kError> {
189 let mut accelerator = CpuOnlyDctToWaveletStageAccelerator;
190 self.transcode_batch_with_accelerator(tiles, options, &mut accelerator)
191 }
192
193 pub fn transcode_batch_with_accelerator<A: DctToWaveletStageAccelerator>(
195 &mut self,
196 tiles: &[JpegTileBatchInput<'_>],
197 options: &JpegToHtj2kOptions,
198 accelerator: &mut A,
199 ) -> Result<EncodedTranscodeBatch, JpegToHtj2kError> {
200 let mut encode_accelerator = CpuOnlyJ2kEncodeStageAccelerator;
201 self.transcode_batch_with_accelerators(tiles, options, accelerator, &mut encode_accelerator)
202 }
203
204 pub fn transcode_batch_with_accelerators<
207 A: DctToWaveletStageAccelerator,
208 E: J2kEncodeStageAccelerator,
209 >(
210 &mut self,
211 tiles: &[JpegTileBatchInput<'_>],
212 options: &JpegToHtj2kOptions,
213 transform_accelerator: &mut A,
214 encode_accelerator: &mut E,
215 ) -> Result<EncodedTranscodeBatch, JpegToHtj2kError> {
216 jpeg_tile_batch_to_htj2k_with_scratch(
217 tiles,
218 options,
219 &mut self.scratch,
220 transform_accelerator,
221 encode_accelerator,
222 )
223 }
224}
225
226pub fn jpeg_to_htj2k(
233 bytes: &[u8],
234 options: &JpegToHtj2kOptions,
235) -> Result<EncodedTranscode, JpegToHtj2kError> {
236 JpegToHtj2kTranscoder::default().transcode(bytes, options)
237}
238
239#[cfg(test)]
240mod tests;