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_owned_with_accelerator_and_max_host_bytes,
25 encode_prequantized_htj2k_97_with_accelerator_and_max_host_bytes,
26};
27use rayon::prelude::*;
28
29use crate::allocation::try_vec_with_capacity;
30use crate::dct53_2d::{
31 dct8x8_blocks_then_dwt53_float, dct8x8_blocks_to_dwt53_float_linear_with_scratch,
32 linearized_53_2d_from_plane, Dct53GridScratch,
33};
34use crate::dct97_2d::{
35 dct8x8_blocks_then_dwt97_float, dct8x8_blocks_then_dwt97_float_with_scratch,
36 linearized_97_2d_from_plane_with_scratch, Dct97GridScratch,
37};
38use crate::metrics::{error_metrics_i32_with_live_budget, ErrorMetrics, MetricsError};
39use crate::reversible53::{
40 reversible_lift_53_high_at_fallible, reversible_lift_53_i32, reversible_lift_53_low_at_fallible,
41};
42use crate::{
43 CpuOnlyDctToWaveletStageAccelerator, DctGridI16ToHtj2k97CodeBlockBatch,
44 DctGridI16ToHtj2k97CodeBlockJob, DctGridToDwt53Job, DctGridToDwt97Job,
45 DctGridToHtj2k97CodeBlockJob, DctGridToReversibleDwt53Job, DctToWaveletStageAccelerator,
46 DctTransformError, Dwt53TwoDimensional, Dwt97BatchStageTimings, Dwt97TwoDimensional,
47 Htj2k97CodeBlockOptions, ReversibleDwt53FirstLevel, TranscodeStageError,
48};
49
50mod options;
51pub use self::options::{
52 JpegToHtj2kCoefficientPath, JpegToHtj2kEncodeOptions, JpegToHtj2kOptions,
53 JPEG_TO_HTJ2K_LOSSY_97_QUANTIZATION_SCALE,
54};
55mod report;
56pub use self::report::{
57 BatchTranscodeReport, TranscodeBatchProfileRequest, TranscodeBatchProfileRow,
58 TranscodeComponentReport, TranscodeReport, TranscodeTimingReport,
59 TranscodeValidationClassification, TranscodeValidationMetrics,
60};
61mod error;
62use self::error::{dct53_transform_error, dct97_transform_error, map_encode_error};
63pub use self::error::{Htj2kEncodeError, Htj2kEncodeErrorKind, JpegToHtj2kError};
64mod validation;
65use self::validation::{
66 component_sampling_for_jpeg, decomposition_levels_for_components,
67 validate_component_block_grid, validate_transcode_options,
68};
69mod workspace;
70use self::workspace::validate_jpeg_transcode_workspace;
71mod scratch;
72use self::scratch::JpegToHtj2kScratch;
73mod output;
74pub use self::output::{EncodedTranscode, EncodedTranscodeBatch, JpegTileBatchInput};
75mod live_budget;
76use self::live_budget::{
77 encoded_transcode_retained_bytes, precomputed_batch_retained_bytes,
78 validation_metrics_retained_bytes, HostLiveBudget,
79};
80mod component_plan;
81use self::component_plan::{
82 integer_dct_job_for_component, transcode_component_batch, transcode_path_name,
83 ComponentBatchRequest, ComponentTranscodeBatch, PrecomputedComponentBatch,
84};
85mod component_groups;
86use self::component_groups::same_geometry_component_groups;
87mod float_reference;
88use self::float_reference::{
89 dct_blocks_to_8x8_f64, decompose_97_from_first_level, float97_reference_coefficients,
90 float_direct_97_wavelet_from_component, float_direct_wavelet_from_component,
91 float_reference_coefficients, ComponentWavelet, ComponentWavelet97,
92};
93mod float_output;
94use self::float_output::{
95 j2k_dwt97_from_wavelet, j2k_dwt_from_integer_wavelet, j2k_dwt_from_wavelet,
96 rounded_wavelet97_i32, rounded_wavelet_i32,
97};
98mod integer_reference;
99use self::integer_reference::{
100 flatten_integer_wavelet, integer_direct_wavelet_from_component, integer_reference_coefficients,
101 integer_wavelet_from_first_level, IntegerWavelet,
102};
103mod integer_storage;
104mod single;
105use self::single::jpeg_to_htj2k_with_scratch;
106mod single_tile_encode;
107use self::single_tile_encode::encode_component_batch;
108mod batch;
109pub use self::batch::jpeg_to_htj2k_batch;
110#[cfg(test)]
111use self::batch::{
112 encode_float97_prepared_tiles, store_compact_preencoded_component,
113 transform_float97_batch_tiles, Float97BatchTile,
114};
115use self::batch::{
116 jpeg_tile_batch_to_htj2k_with_scratch, record_accelerator_attempt, record_accelerator_dispatch,
117 record_batch_attempt, record_cpu_fallback, record_encode_dispatch_delta,
118};
119
120#[derive(Debug, Default)]
126pub struct JpegToHtj2kTranscoder {
127 scratch: JpegToHtj2kScratch,
128}
129
130impl JpegToHtj2kTranscoder {
131 pub fn transcode(
134 &mut self,
135 bytes: &[u8],
136 options: &JpegToHtj2kOptions,
137 ) -> Result<EncodedTranscode, JpegToHtj2kError> {
138 let mut accelerator = CpuOnlyDctToWaveletStageAccelerator;
139 self.transcode_with_accelerator(bytes, options, &mut accelerator)
140 }
141
142 pub fn transcode_with_accelerator<A: DctToWaveletStageAccelerator>(
148 &mut self,
149 bytes: &[u8],
150 options: &JpegToHtj2kOptions,
151 accelerator: &mut A,
152 ) -> Result<EncodedTranscode, JpegToHtj2kError> {
153 let mut encode_accelerator = CpuOnlyJ2kEncodeStageAccelerator;
154 self.transcode_with_accelerators(bytes, options, accelerator, &mut encode_accelerator)
155 }
156
157 pub fn transcode_with_accelerators<
160 A: DctToWaveletStageAccelerator,
161 E: J2kEncodeStageAccelerator,
162 >(
163 &mut self,
164 bytes: &[u8],
165 options: &JpegToHtj2kOptions,
166 transform_accelerator: &mut A,
167 encode_accelerator: &mut E,
168 ) -> Result<EncodedTranscode, JpegToHtj2kError> {
169 jpeg_to_htj2k_with_scratch(
170 bytes,
171 options,
172 &mut self.scratch,
173 transform_accelerator,
174 encode_accelerator,
175 0,
176 )
177 }
178
179 pub fn transcode_batch(
183 &mut self,
184 tiles: &[JpegTileBatchInput<'_>],
185 options: &JpegToHtj2kOptions,
186 ) -> Result<EncodedTranscodeBatch, JpegToHtj2kError> {
187 let mut accelerator = CpuOnlyDctToWaveletStageAccelerator;
188 self.transcode_batch_with_accelerator(tiles, options, &mut accelerator)
189 }
190
191 pub fn transcode_batch_with_accelerator<A: DctToWaveletStageAccelerator>(
193 &mut self,
194 tiles: &[JpegTileBatchInput<'_>],
195 options: &JpegToHtj2kOptions,
196 accelerator: &mut A,
197 ) -> Result<EncodedTranscodeBatch, JpegToHtj2kError> {
198 let mut encode_accelerator = CpuOnlyJ2kEncodeStageAccelerator;
199 self.transcode_batch_with_accelerators(tiles, options, accelerator, &mut encode_accelerator)
200 }
201
202 pub fn transcode_batch_with_accelerators<
205 A: DctToWaveletStageAccelerator,
206 E: J2kEncodeStageAccelerator,
207 >(
208 &mut self,
209 tiles: &[JpegTileBatchInput<'_>],
210 options: &JpegToHtj2kOptions,
211 transform_accelerator: &mut A,
212 encode_accelerator: &mut E,
213 ) -> Result<EncodedTranscodeBatch, JpegToHtj2kError> {
214 jpeg_tile_batch_to_htj2k_with_scratch(
215 tiles,
216 options,
217 &mut self.scratch,
218 transform_accelerator,
219 encode_accelerator,
220 )
221 }
222}
223
224pub fn jpeg_to_htj2k(
231 bytes: &[u8],
232 options: &JpegToHtj2kOptions,
233) -> Result<EncodedTranscode, JpegToHtj2kError> {
234 JpegToHtj2kTranscoder::default().transcode(bytes, options)
235}
236
237#[cfg(test)]
238mod tests;