dicom_toolkit_codec/jpeg_ls/
decoder.rs1use dicom_toolkit_core::error::{DcmError, DcmResult};
10
11use super::marker;
12use super::params::{compute_default, DerivedTraits, InterleaveMode, BASIC_RESET};
13use super::sample::{needs_u16, Sample};
14use super::scan::ScanDecoder;
15
16pub struct DecodedFrame {
18 pub pixels: Vec<u8>,
20 pub width: u32,
21 pub height: u32,
22 pub bits_per_sample: u8,
23 pub components: u8,
24}
25
26pub fn decode_jpeg_ls(data: &[u8]) -> DcmResult<DecodedFrame> {
28 let frame_info = marker::parse_markers(data)?;
29 let params = &frame_info.params;
30
31 if frame_info.scan_offsets.is_empty() {
32 return Err(DcmError::DecompressionError {
33 reason: "JPEG-LS: no scan data found".into(),
34 });
35 }
36
37 let max_val = if params.custom.max_val > 0 {
38 params.custom.max_val
39 } else {
40 (1i32 << params.bits_per_sample) - 1
41 };
42
43 let defaults = compute_default(max_val, params.near);
44 let t1 = if params.custom.t1 > 0 {
45 params.custom.t1
46 } else {
47 defaults.t1
48 };
49 let t2 = if params.custom.t2 > 0 {
50 params.custom.t2
51 } else {
52 defaults.t2
53 };
54 let t3 = if params.custom.t3 > 0 {
55 params.custom.t3
56 } else {
57 defaults.t3
58 };
59 let reset = if params.custom.reset > 0 {
60 params.custom.reset
61 } else {
62 BASIC_RESET
63 };
64
65 let w = params.width as usize;
66 let h = params.height as usize;
67 let components = params.components as usize;
68
69 let traits = DerivedTraits::new(max_val, params.near, reset);
70
71 match params.interleave {
72 InterleaveMode::None => {
73 if frame_info.scan_offsets.len() < components {
75 return Err(DcmError::DecompressionError {
76 reason: format!(
77 "JPEG-LS: expected {} scans for ILV_NONE, found {}",
78 components,
79 frame_info.scan_offsets.len()
80 ),
81 });
82 }
83
84 let mut all_pixels: Vec<Vec<i32>> = Vec::with_capacity(components);
85 for c in 0..components {
86 let scan_start = frame_info.scan_offsets[c];
87 let scan_data = &data[scan_start..];
88 let mut decoder = ScanDecoder::new(scan_data, traits, t1, t2, t3, w, h);
89 all_pixels.push(decoder.decode()?);
90 }
91
92 if needs_u16(params.bits_per_sample) {
94 let mut output = vec![0u8; w * h * components * 2];
95 for pixel in 0..(w * h) {
96 for (c, pixels) in all_pixels.iter().enumerate().take(components) {
97 let val = pixels[pixel] as u16;
98 let offset = (pixel * components + c) * 2;
99 u16::write_le(&mut output, offset, val);
100 }
101 }
102 Ok(DecodedFrame {
103 pixels: output,
104 width: params.width,
105 height: params.height,
106 bits_per_sample: params.bits_per_sample,
107 components: params.components,
108 })
109 } else {
110 let mut output = vec![0u8; w * h * components];
111 for pixel in 0..(w * h) {
112 for (c, pixels) in all_pixels.iter().enumerate().take(components) {
113 output[pixel * components + c] = pixels[pixel] as u8;
114 }
115 }
116 Ok(DecodedFrame {
117 pixels: output,
118 width: params.width,
119 height: params.height,
120 bits_per_sample: params.bits_per_sample,
121 components: params.components,
122 })
123 }
124 }
125
126 InterleaveMode::Line | InterleaveMode::Sample => {
127 if components == 1 {
131 let scan_start = frame_info.scan_offsets[0];
132 let scan_data = &data[scan_start..];
133 let mut decoder = ScanDecoder::new(scan_data, traits, t1, t2, t3, w, h);
134 let decoded = decoder.decode()?;
135
136 if needs_u16(params.bits_per_sample) {
137 let mut output = vec![0u8; w * h * 2];
138 for (i, &val) in decoded.iter().enumerate() {
139 u16::write_le(&mut output, i * 2, val as u16);
140 }
141 Ok(DecodedFrame {
142 pixels: output,
143 width: params.width,
144 height: params.height,
145 bits_per_sample: params.bits_per_sample,
146 components: 1,
147 })
148 } else {
149 let output: Vec<u8> = decoded.iter().map(|&v| v as u8).collect();
150 Ok(DecodedFrame {
151 pixels: output,
152 width: params.width,
153 height: params.height,
154 bits_per_sample: params.bits_per_sample,
155 components: 1,
156 })
157 }
158 } else {
159 if params.interleave == InterleaveMode::Line {
164 decode_line_interleaved(
165 data,
166 &frame_info,
167 traits,
168 t1,
169 t2,
170 t3,
171 w,
172 h,
173 components,
174 params,
175 )
176 } else {
177 Err(DcmError::DecompressionError {
179 reason: "JPEG-LS: ILV_SAMPLE multi-component not yet implemented".into(),
180 })
181 }
182 }
183 }
184 }
185}
186
187#[allow(clippy::too_many_arguments)]
189fn decode_line_interleaved(
190 data: &[u8],
191 frame_info: &marker::FrameInfo,
192 traits: DerivedTraits,
193 t1: i32,
194 t2: i32,
195 t3: i32,
196 w: usize,
197 h: usize,
198 components: usize,
199 params: &super::params::JlsParameters,
200) -> DcmResult<DecodedFrame> {
201 let scan_start = frame_info.scan_offsets[0];
205 let scan_data = &data[scan_start..];
206
207 let effective_w = w;
210 let effective_h = h * components;
211 let mut decoder = ScanDecoder::new(scan_data, traits, t1, t2, t3, effective_w, effective_h);
212 let decoded = decoder.decode()?;
213
214 let needs16 = needs_u16(params.bits_per_sample);
217 let bytes_per_sample = if needs16 { 2 } else { 1 };
218 let mut output = vec![0u8; w * h * components * bytes_per_sample];
219
220 for y in 0..h {
221 for c in 0..components {
222 let src_line = y * components + c;
223 for x in 0..w {
224 let val = decoded[src_line * w + x];
225 let dst_offset = (y * w + x) * components + c;
226 if needs16 {
227 u16::write_le(&mut output, dst_offset * 2, val as u16);
228 } else {
229 output[dst_offset] = val as u8;
230 }
231 }
232 }
233 }
234
235 Ok(DecodedFrame {
236 pixels: output,
237 width: params.width,
238 height: params.height,
239 bits_per_sample: params.bits_per_sample,
240 components: params.components,
241 })
242}