-
Notifications
You must be signed in to change notification settings - Fork 91
Add the ability to scale down images during decode (IDCT scaling) #117
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
3123fc5
cb87665
85adaf5
d28ea6f
168ee6b
12920df
67dc09e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -50,6 +50,7 @@ pub struct ImageInfo { | |
/// JPEG decoder | ||
pub struct Decoder<R> { | ||
reader: R, | ||
requested_size: Option<Dimensions>, | ||
|
||
frame: Option<FrameInfo>, | ||
dc_huffman_tables: Vec<Option<HuffmanTable>>, | ||
|
@@ -70,8 +71,26 @@ pub struct Decoder<R> { | |
impl<R: Read> Decoder<R> { | ||
/// Creates a new `Decoder` using the reader `reader`. | ||
pub fn new(reader: R) -> Decoder<R> { | ||
Decoder::init(reader, None) | ||
} | ||
|
||
/// Creates a new `Decoder` using the reader `reader` that returns a | ||
/// scaled image that is equal to or larger than the requested size in at | ||
/// least one axis, or the full size of the image if the requested size is | ||
/// larger. | ||
/// | ||
/// This efficiently scales down the image by one of a fixed set of | ||
/// available ratios during decoding. To generate a thumbnail of an | ||
/// exact size, pass the desired size or larger and then scale to the | ||
/// final size using a traditional resampling algorithm. | ||
pub fn scaled(reader: R, requested_width: u16, requested_height: u16) -> Decoder<R> { | ||
Decoder::init(reader, Some(Dimensions{ width: requested_width, height: requested_height })) | ||
} | ||
|
||
fn init(reader: R, requested_size: Option<Dimensions>) -> Decoder<R> { | ||
Decoder { | ||
reader: reader, | ||
requested_size, | ||
frame: None, | ||
dc_huffman_tables: vec![None, None, None, None], | ||
ac_huffman_tables: vec![None, None, None, None], | ||
|
@@ -100,8 +119,8 @@ impl<R: Read> Decoder<R> { | |
}; | ||
|
||
Some(ImageInfo { | ||
width: frame.image_size.width, | ||
height: frame.image_size.height, | ||
width: frame.output_size.width, | ||
height: frame.output_size.height, | ||
pixel_format: pixel_format, | ||
}) | ||
}, | ||
|
@@ -153,7 +172,7 @@ impl<R: Read> Decoder<R> { | |
return Err(Error::Unsupported(UnsupportedFeature::Hierarchical)); | ||
} | ||
|
||
let frame = parse_sof(&mut self.reader, marker)?; | ||
let frame = parse_sof(&mut self.reader, marker, self.requested_size)?; | ||
let component_count = frame.components.len(); | ||
|
||
if frame.is_differential { | ||
|
@@ -329,7 +348,7 @@ impl<R: Read> Decoder<R> { | |
} | ||
|
||
let frame = self.frame.as_ref().unwrap(); | ||
compute_image(&frame.components, &planes, frame.image_size, self.is_jfif, self.color_transform) | ||
compute_image(&frame.components, &planes, frame.output_size, self.is_jfif, self.color_transform) | ||
} | ||
|
||
fn read_marker(&mut self) -> Result<Marker> { | ||
|
@@ -436,7 +455,7 @@ impl<R: Read> Decoder<R> { | |
let x = (block_num % blocks_per_row) as u16; | ||
let y = (block_num / blocks_per_row) as u16; | ||
|
||
if x * 8 >= component.size.width || y * 8 >= component.size.height { | ||
if x * component.dct_scale as u16 >= component.size.width || y * component.dct_scale as u16 >= component.size.height { | ||
continue; | ||
} | ||
|
||
|
@@ -762,12 +781,15 @@ fn compute_image(components: &[Component], | |
return Ok(data[0].clone()) | ||
} | ||
|
||
let mut buffer = vec![0u8; component.size.width as usize * component.size.height as usize]; | ||
let line_stride = component.block_size.width as usize * 8; | ||
let width = component.size.width as usize; | ||
let height = component.size.height as usize; | ||
|
||
let mut buffer = vec![0u8; width * height]; | ||
let line_stride = width * component.dct_scale; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this was inadvertently changed from |
||
|
||
for y in 0 .. component.size.height as usize { | ||
for x in 0 .. component.size.width as usize { | ||
buffer[y * component.size.width as usize + x] = data[0][y * line_stride + x]; | ||
for y in 0 .. width { | ||
for x in 0 .. height { | ||
buffer[y * width + x] = data[0][y * line_stride + x]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #125 seems to have been introduced by this line There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like I swapped Also, this presumably means there are no single-channel JPEG images in the test suite? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wow, I missed that ! I fixed that too in #126 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The test suite could clearly be more extensive ! |
||
} | ||
} | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As written, this description says we can always just return the original image size and only hints that it sometimes won't. Perhaps it could instead say something along the lines of "scales by the smallest supported scale factor that produces an image larger or equal to (min_width, min_height) if possible. Otherwise scales by the largest supported factor".