Merge pull request #10 from zroug/16bit-performance
Bug fix in `Decoder::expand_strip` + greatly improved performance for 16 bit images
This commit is contained in:
2 files changed
+17
-23
No files matched your search
+9
-23
@@ -416,19 +416,18 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
(ColorType:: RGB(8), DecodingBuffer::U8(ref mut buffer)) |
|
(ColorType:: RGB(8), DecodingBuffer::U8(ref mut buffer)) |
|
||||||
(ColorType::RGBA(8), DecodingBuffer::U8(ref mut buffer)) |
|
(ColorType::RGBA(8), DecodingBuffer::U8(ref mut buffer)) |
|
||||||
(ColorType::CMYK(8), DecodingBuffer::U8(ref mut buffer)) => {
|
(ColorType::CMYK(8), DecodingBuffer::U8(ref mut buffer)) => {
|
||||||
try!(reader.read(&mut buffer[..bytes]))
|
try!(reader.read_exact(&mut buffer[..bytes]));
|
||||||
|
bytes
|
||||||
}
|
}
|
||||||
(ColorType::RGBA(16), DecodingBuffer::U16(ref mut buffer)) |
|
(ColorType::RGBA(16), DecodingBuffer::U16(ref mut buffer)) |
|
||||||
(ColorType:: RGB(16), DecodingBuffer::U16(ref mut buffer)) => {
|
(ColorType:: RGB(16), DecodingBuffer::U16(ref mut buffer)) => {
|
||||||
for datum in buffer[..bytes/2].iter_mut() {
|
try!(reader.read_u16_into(&mut buffer[..bytes/2]));
|
||||||
*datum = try!(reader.read_u16())
|
|
||||||
}
|
|
||||||
bytes/2
|
bytes/2
|
||||||
}
|
}
|
||||||
(ColorType::Gray(16), DecodingBuffer::U16(ref mut buffer)) => {
|
(ColorType::Gray(16), DecodingBuffer::U16(ref mut buffer)) => {
|
||||||
for datum in buffer[..bytes/2].iter_mut() {
|
try!(reader.read_u16_into(&mut buffer[..bytes/2]));
|
||||||
*datum = try!(reader.read_u16());
|
if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero {
|
||||||
if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero {
|
for datum in buffer[..bytes/2].iter_mut() {
|
||||||
*datum = 0xffff - *datum
|
*datum = 0xffff - *datum
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -459,8 +458,8 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
* self.height as usize
|
* self.height as usize
|
||||||
* self.bits_per_sample.iter().count();
|
* self.bits_per_sample.iter().count();
|
||||||
let mut result = match self.bits_per_sample.iter().cloned().max().unwrap_or(8) {
|
let mut result = match self.bits_per_sample.iter().cloned().max().unwrap_or(8) {
|
||||||
n if n <= 8 => DecodingResult::U8(Vec::with_capacity(buffer_size)),
|
n if n <= 8 => DecodingResult::U8(vec![0; buffer_size]),
|
||||||
n if n <= 16 => DecodingResult::U16(Vec::with_capacity(buffer_size)),
|
n if n <= 16 => DecodingResult::U16(vec![0; buffer_size]),
|
||||||
n => return Err(TiffError::UnsupportedError(TiffUnsupportedError::UnsupportedBitsPerChannel(n))),
|
n => return Err(TiffError::UnsupportedError(TiffUnsupportedError::UnsupportedBitsPerChannel(n))),
|
||||||
};
|
};
|
||||||
if let Ok(config) = self.get_tag_u32(ifd::Tag::PlanarConfiguration) {
|
if let Ok(config) = self.get_tag_u32(ifd::Tag::PlanarConfiguration) {
|
||||||
@@ -469,13 +468,6 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
config => return Err(TiffError::UnsupportedError(TiffUnsupportedError::UnsupportedPlanarConfig(config)))
|
config => return Err(TiffError::UnsupportedError(TiffUnsupportedError::UnsupportedPlanarConfig(config)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Safe since the uninitialized values are never read.
|
|
||||||
match result {
|
|
||||||
DecodingResult::U8(ref mut buffer) =>
|
|
||||||
unsafe { buffer.set_len(buffer_size) },
|
|
||||||
DecodingResult::U16(ref mut buffer) =>
|
|
||||||
unsafe { buffer.set_len(buffer_size) },
|
|
||||||
}
|
|
||||||
let mut units_read = 0;
|
let mut units_read = 0;
|
||||||
for (i, (&offset, &byte_count)) in try!(self.get_tag_u32_vec(ifd::Tag::StripOffsets))
|
for (i, (&offset, &byte_count)) in try!(self.get_tag_u32_vec(ifd::Tag::StripOffsets))
|
||||||
.iter().zip(try!(self.get_tag_u32_vec(ifd::Tag::StripByteCounts)).iter()).enumerate() {
|
.iter().zip(try!(self.get_tag_u32_vec(ifd::Tag::StripByteCounts)).iter()).enumerate() {
|
||||||
@@ -500,14 +492,8 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Shrink length such that the uninitialized memory is not exposed.
|
|
||||||
if units_read < buffer_size {
|
if units_read < buffer_size {
|
||||||
match result {
|
return Err(TiffError::FormatError("Inconsistent sizes encountered.".to_string()));
|
||||||
DecodingResult::U8(ref mut buffer) =>
|
|
||||||
unsafe { buffer.set_len(units_read) },
|
|
||||||
DecodingResult::U16(ref mut buffer) =>
|
|
||||||
unsafe { buffer.set_len(units_read) },
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if let Ok(predictor) = self.get_tag_u32(ifd::Tag::Predictor) {
|
if let Ok(predictor) = self.get_tag_u32(ifd::Tag::Predictor) {
|
||||||
result = match FromPrimitive::from_u32(predictor) {
|
result = match FromPrimitive::from_u32(predictor) {
|
||||||
|
|||||||
@@ -28,6 +28,14 @@ pub trait EndianReader: Read {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn read_u16_into(&mut self, buffer: &mut [u16]) -> Result<(), io::Error> {
|
||||||
|
match self.byte_order() {
|
||||||
|
ByteOrder::LittleEndian => <Self as ReadBytesExt>::read_u16_into::<LittleEndian>(self, buffer),
|
||||||
|
ByteOrder::BigEndian => <Self as ReadBytesExt>::read_u16_into::<BigEndian>(self, buffer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Reads an u32
|
/// Reads an u32
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn read_u32(&mut self) -> Result<u32, io::Error> {
|
fn read_u32(&mut self) -> Result<u32, io::Error> {
|
||||||
|
|||||||
Reference in new issue
Block a user