Skip to content

Commit a96dcd2

Browse files
committed
Merge remote-tracking branch 'origin/master' into almost-no_std
2 parents fcba84b + 432b417 commit a96dcd2

32 files changed

+460
-65
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ This project adheres to [Semantic Versioning](http://semver.org/).
44

55
## Unreleased
66

7+
- Added Lossless JPEG support
8+
- Minimum supported rust version changed to 1.36
9+
710
## v0.1.22 (2021-01-27)
811

912
- Fix panic on jpeg without frames.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,4 @@ fn main() {
3232
```
3333

3434
## Requirements
35-
This crate compiles only with rust >= 1.34.
35+
This crate compiles only with rust >= 1.36.

benches/decoding_benchmark.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,9 @@ fn main() {
3333
c.bench_function("extract metadata from an image", |b| b.iter(|| {
3434
read_metadata(include_bytes!("tower.jpg"))
3535
}));
36+
37+
c.bench_function("decode a 3072x2048 RGB Lossless JPEG", |b| b.iter(|| {
38+
read_image(include_bytes!("../tests/reftest/images/lossless/jpeg_lossless_sel1-rgb.jpg"))
39+
}));
3640
c.final_summary();
3741
}

examples/decode.rs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,27 @@ fn main() {
2323

2424
let output_file = File::create(output_path).unwrap();
2525
let mut encoder = png::Encoder::new(output_file, info.width as u32, info.height as u32);
26-
encoder.set_depth(png::BitDepth::Eight);
2726

2827
match info.pixel_format {
29-
jpeg::PixelFormat::L8 => encoder.set_color(png::ColorType::Grayscale),
30-
jpeg::PixelFormat::RGB24 => encoder.set_color(png::ColorType::RGB),
28+
jpeg::PixelFormat::L16 => {
29+
encoder.set_depth(png::BitDepth::Sixteen);
30+
encoder.set_color(png::ColorType::Grayscale);
31+
},
32+
jpeg::PixelFormat::RGB24 => {
33+
encoder.set_depth(png::BitDepth::Eight);
34+
encoder.set_color(png::ColorType::RGB);
35+
},
3136
jpeg::PixelFormat::CMYK32 => {
3237
data = cmyk_to_rgb(&mut data);
38+
encoder.set_depth(png::BitDepth::Eight);
3339
encoder.set_color(png::ColorType::RGB)
3440
},
35-
};
36-
41+
jpeg::PixelFormat::L8 => {
42+
encoder.set_depth(png::BitDepth::Eight);
43+
encoder.set_color(png::ColorType::Grayscale);
44+
},
45+
}
46+
3747
encoder.write_header()
3848
.expect("writing png header failed")
3949
.write_image_data(&data)

src/decoder.rs

Lines changed: 71 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ use worker::{RowData, PlatformWorker, Worker};
1818

1919
pub const MAX_COMPONENTS: usize = 4;
2020

21+
mod lossless;
22+
use self::lossless::compute_image_lossless;
23+
2124
static UNZIGZAG: [u8; 64] = [
2225
0, 1, 8, 16, 9, 2, 3, 10,
2326
17, 24, 32, 25, 18, 11, 4, 5,
@@ -34,6 +37,8 @@ static UNZIGZAG: [u8; 64] = [
3437
pub enum PixelFormat {
3538
/// Luminance (grayscale), 8 bits
3639
L8,
40+
/// Luminance (grayscale), 16 bits
41+
L16,
3742
/// RGB, 8 bits per channel
3843
RGB24,
3944
/// CMYK, 8 bits per channel
@@ -45,6 +50,7 @@ impl PixelFormat {
4550
pub fn pixel_bytes(&self) -> usize {
4651
match self {
4752
PixelFormat::L8 => 1,
53+
PixelFormat::L16 => 2,
4854
PixelFormat::RGB24 => 3,
4955
PixelFormat::CMYK32 => 4,
5056
}
@@ -60,6 +66,8 @@ pub struct ImageInfo {
6066
pub height: u16,
6167
/// The pixel format of the image.
6268
pub pixel_format: PixelFormat,
69+
/// The coding process of the image.
70+
pub coding_process: CodingProcess,
6371
}
6472

6573
/// JPEG decoder
@@ -114,7 +122,11 @@ impl<R: Read> Decoder<R> {
114122
match self.frame {
115123
Some(ref frame) => {
116124
let pixel_format = match frame.components.len() {
117-
1 => PixelFormat::L8,
125+
1 => match frame.precision {
126+
8 => PixelFormat::L8,
127+
16 => PixelFormat::L16,
128+
_ => panic!()
129+
},
118130
3 => PixelFormat::RGB24,
119131
4 => PixelFormat::CMYK32,
120132
_ => panic!(),
@@ -124,6 +136,7 @@ impl<R: Read> Decoder<R> {
124136
width: frame.output_size.width,
125137
height: frame.output_size.height,
126138
pixel_format: pixel_format,
139+
coding_process: frame.coding_process,
127140
})
128141
},
129142
None => None,
@@ -212,7 +225,8 @@ impl<R: Read> Decoder<R> {
212225
let mut pending_marker = None;
213226
let mut worker = None;
214227
let mut scans_processed = 0;
215-
let mut planes = vec![Vec::new(); self.frame.as_ref().map_or(0, |frame| frame.components.len())];
228+
let mut planes = vec![Vec::<u8>::new(); self.frame.as_ref().map_or(0, |frame| frame.components.len())];
229+
let mut planes_u16 = vec![Vec::<u16>::new(); self.frame.as_ref().map_or(0, |frame| frame.components.len())];
216230

217231
loop {
218232
let marker = match pending_marker.take() {
@@ -237,13 +251,13 @@ impl<R: Read> Decoder<R> {
237251
if frame.is_differential {
238252
return Err(Error::Unsupported(UnsupportedFeature::Hierarchical));
239253
}
240-
if frame.coding_process == CodingProcess::Lossless {
241-
return Err(Error::Unsupported(UnsupportedFeature::Lossless));
242-
}
243254
if frame.entropy_coding == EntropyCoding::Arithmetic {
244255
return Err(Error::Unsupported(UnsupportedFeature::ArithmeticEntropyCoding));
245256
}
246-
if frame.precision != 8 {
257+
if frame.precision != 8 && frame.coding_process != CodingProcess::Lossless {
258+
return Err(Error::Unsupported(UnsupportedFeature::SamplePrecision(frame.precision)));
259+
}
260+
if frame.precision != 8 && frame.precision != 16 {
247261
return Err(Error::Unsupported(UnsupportedFeature::SamplePrecision(frame.precision)));
248262
}
249263
if component_count != 1 && component_count != 3 && component_count != 4 {
@@ -260,6 +274,7 @@ impl<R: Read> Decoder<R> {
260274
}
261275

262276
planes = vec![Vec::new(); component_count];
277+
planes_u16 = vec![Vec::new(); component_count];
263278
},
264279

265280
// Scan header
@@ -281,46 +296,57 @@ impl<R: Read> Decoder<R> {
281296
}).collect();
282297
}
283298

284-
// This was previously buggy, so let's explain the log here a bit. When a
285-
// progressive frame is encoded then the coefficients (DC, AC) of each
286-
// component (=color plane) can be split amongst scans. In particular it can
287-
// happen or at least occurs in the wild that a scan contains coefficient 0 of
288-
// all components. If now one but not all components had all other coefficients
289-
// delivered in previous scans then such a scan contains all components but
290-
// completes only some of them! (This is technically NOT permitted for all
291-
// other coefficients as the standard dictates that scans with coefficients
292-
// other than the 0th must only contain ONE component so we would either
293-
// complete it or not. We may want to detect and error in case more component
294-
// are part of a scan than allowed.) What a weird edge case.
295-
//
296-
// But this means we track precisely which components get completed here.
297-
let mut finished = [false; MAX_COMPONENTS];
298-
299-
if scan.successive_approximation_low == 0 {
300-
for (&i, component_finished) in scan.component_indices.iter().zip(&mut finished) {
301-
if self.coefficients_finished[i] == !0 {
302-
continue;
303-
}
304-
for j in scan.spectral_selection.clone() {
305-
self.coefficients_finished[i] |= 1 << j;
306-
}
307-
if self.coefficients_finished[i] == !0 {
308-
*component_finished = true;
309-
}
299+
300+
if frame.coding_process == CodingProcess::Lossless {
301+
let (marker, data) = self.decode_scan_lossless(&frame, &scan)?;
302+
303+
for (i, plane) in data.into_iter().enumerate().filter(|&(_, ref plane)| !plane.is_empty()) {
304+
planes_u16[i] = plane;
310305
}
306+
pending_marker = marker;
311307
}
308+
else {
309+
// This was previously buggy, so let's explain the log here a bit. When a
310+
// progressive frame is encoded then the coefficients (DC, AC) of each
311+
// component (=color plane) can be split amongst scans. In particular it can
312+
// happen or at least occurs in the wild that a scan contains coefficient 0 of
313+
// all components. If now one but not all components had all other coefficients
314+
// delivered in previous scans then such a scan contains all components but
315+
// completes only some of them! (This is technically NOT permitted for all
316+
// other coefficients as the standard dictates that scans with coefficients
317+
// other than the 0th must only contain ONE component so we would either
318+
// complete it or not. We may want to detect and error in case more component
319+
// are part of a scan than allowed.) What a weird edge case.
320+
//
321+
// But this means we track precisely which components get completed here.
322+
let mut finished = [false; MAX_COMPONENTS];
323+
324+
if scan.successive_approximation_low == 0 {
325+
for (&i, component_finished) in scan.component_indices.iter().zip(&mut finished) {
326+
if self.coefficients_finished[i] == !0 {
327+
continue;
328+
}
329+
for j in scan.spectral_selection.clone() {
330+
self.coefficients_finished[i] |= 1 << j;
331+
}
332+
if self.coefficients_finished[i] == !0 {
333+
*component_finished = true;
334+
}
335+
}
336+
}
312337

313-
let (marker, data) = self.decode_scan(&frame, &scan, worker.as_mut().unwrap(), &finished)?;
338+
let (marker, data) = self.decode_scan(&frame, &scan, worker.as_mut().unwrap(), &finished)?;
314339

315-
if let Some(data) = data {
316-
for (i, plane) in data.into_iter().enumerate().filter(|&(_, ref plane)| !plane.is_empty()) {
317-
if self.coefficients_finished[i] == !0 {
318-
planes[i] = plane;
340+
if let Some(data) = data {
341+
for (i, plane) in data.into_iter().enumerate().filter(|&(_, ref plane)| !plane.is_empty()) {
342+
if self.coefficients_finished[i] == !0 {
343+
planes[i] = plane;
344+
}
319345
}
320346
}
347+
pending_marker = marker;
321348
}
322349

323-
pending_marker = marker;
324350
scans_processed += 1;
325351
},
326352

@@ -468,7 +494,12 @@ impl<R: Read> Decoder<R> {
468494
}
469495
}
470496

471-
compute_image(&frame.components, planes, frame.output_size, self.is_jfif, self.color_transform)
497+
if frame.coding_process == CodingProcess::Lossless {
498+
compute_image_lossless(&frame, planes_u16)
499+
}
500+
else{
501+
compute_image(&frame.components, planes, frame.output_size, self.is_jfif, self.color_transform)
502+
}
472503
}
473504

474505
fn read_marker(&mut self) -> Result<Marker> {
@@ -967,6 +998,7 @@ fn compute_image(components: &[Component],
967998
}
968999
}
9691000

1001+
9701002
#[cfg(feature="rayon")]
9711003
fn compute_image_parallel(components: &[Component],
9721004
data: Vec<Vec<u8>>,

0 commit comments

Comments
 (0)