Format code using 'cargo fmt'

This commit is contained in:
Atul Bhosale committed 2019-04-18 00:04:43 +05:30
1 parent fc743cfd27
commit 522fbd1a69
10 files changed
+488 -292

No files matched your search

+40 -34
View File
@@ -1,12 +1,12 @@
//! Function for reading TIFF tags
use std::collections::HashMap;
use std::io::{self, Read, Seek};
use std::collections::{HashMap};
use super::stream::{ByteOrder, SmartReader, EndianReader};
use ::{TiffError, TiffFormatError, TiffUnsupportedError, TiffResult};
use super::stream::{ByteOrder, EndianReader, SmartReader};
use {TiffError, TiffFormatError, TiffResult, TiffUnsupportedError};
use self::Value::{Unsigned, List, Rational, Ascii};
use self::Value::{Ascii, List, Rational, Unsigned};
macro_rules! tags {
{$(
@@ -37,7 +37,7 @@ macro_rules! tags {
}
// Note: These tags appear in the order they are mentioned in the TIFF reference
tags!{
tags! {
// Baseline tags:
Artist 315;
// grayscale images PhotometricInterpretation 1 or 3
@@ -90,7 +90,6 @@ pub enum Type {
RATIONAL = 5,
}
#[allow(unused_qualifications)]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum Value {
@@ -98,14 +97,16 @@ pub enum Value {
Unsigned(u32),
List(Vec<Value>),
Rational(u32, u32),
Ascii(String)
Ascii(String),
}
impl Value {
pub fn into_u32(self) -> TiffResult<u32> {
match self {
Unsigned(val) => Ok(val),
val => Err(TiffError::FormatError(TiffFormatError::UnsignedIntegerExpected(val))),
val => Err(TiffError::FormatError(
TiffFormatError::UnsignedIntegerExpected(val),
)),
}
}
pub fn into_u32_vec(self) -> TiffResult<Vec<u32>> {
@@ -116,10 +117,10 @@ impl Value {
new_vec.push(v.into_u32()?)
}
Ok(new_vec)
},
}
Unsigned(val) => Ok(vec![val]),
Rational(numerator, denominator) => Ok(vec![numerator, denominator]),
Ascii(val) => Ok(val.chars().map(|x| x as u32).collect())
Ascii(val) => Ok(val.chars().map(|x| x as u32).collect()),
}
}
}
@@ -133,29 +134,32 @@ pub struct Entry {
impl ::std::fmt::Debug for Entry {
fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> Result<(), ::std::fmt::Error> {
fmt.write_str(&format!("Entry {{ type_: {:?}, count: {:?}, offset: {:?} }}",
self.type_,
self.count,
&self.offset
fmt.write_str(&format!(
"Entry {{ type_: {:?}, count: {:?}, offset: {:?} }}",
self.type_, self.count, &self.offset
))
}
}
impl Entry {
pub fn new(type_: Type, count: u32, offset: [u8; 4]) -> Entry {
Entry { type_, count, offset }
Entry {
type_,
count,
offset,
}
}
/// Returns a mem_reader for the offset/value field
fn r(&self, byte_order: ByteOrder) -> SmartReader<io::Cursor<Vec<u8>>> {
SmartReader::wrap(
io::Cursor::new(self.offset.to_vec()),
byte_order
)
SmartReader::wrap(io::Cursor::new(self.offset.to_vec()), byte_order)
}
pub fn val<R: Read + Seek>(&self, limits: &super::Limits, decoder: &mut super::Decoder<R>)
-> TiffResult<Value> {
pub fn val<R: Read + Seek>(
&self,
limits: &super::Limits,
decoder: &mut super::Decoder<R>,
) -> TiffResult<Value> {
let bo = decoder.byte_order();
match (self.type_, self.count) {
// TODO check if this could give wrong results
@@ -166,28 +170,28 @@ impl Entry {
let mut r = self.r(bo);
Ok(List(vec![
Unsigned(u32::from(r.read_u16()?)),
Unsigned(u32::from(r.read_u16()?))
Unsigned(u32::from(r.read_u16()?)),
]))
},
}
(Type::SHORT, n) => {
if n as usize > limits.decoding_buffer_size / std::mem::size_of::<Value>() {
return Err(TiffError::LimitsExceeded)
return Err(TiffError::LimitsExceeded);
}
let mut v = Vec::with_capacity(n as usize);
try!(decoder.goto_offset(try!(self.r(bo).read_u32())));
for _ in 0 .. n {
for _ in 0..n {
v.push(Unsigned(u32::from(decoder.read_short()?)))
}
Ok(List(v))
},
}
(Type::LONG, 1) => Ok(Unsigned(try!(self.r(bo).read_u32()))),
(Type::LONG, n) => {
if n as usize > limits.decoding_buffer_size / std::mem::size_of::<Value>() {
return Err(TiffError::LimitsExceeded)
return Err(TiffError::LimitsExceeded);
}
let mut v = Vec::with_capacity(n as usize);
try!(decoder.goto_offset(try!(self.r(bo).read_u32())));
for _ in 0 .. n {
for _ in 0..n {
v.push(Unsigned(try!(decoder.read_long())))
}
Ok(List(v))
@@ -197,29 +201,31 @@ impl Entry {
let numerator = try!(decoder.read_long());
let denominator = try!(decoder.read_long());
Ok(Rational(numerator, denominator))
},
}
(Type::RATIONAL, n) => {
if n as usize > limits.decoding_buffer_size / std::mem::size_of::<Value>() {
return Err(TiffError::LimitsExceeded)
return Err(TiffError::LimitsExceeded);
}
let mut v = Vec::with_capacity(n as usize);
try!(decoder.goto_offset(try!(self.r(bo).read_u32())));
for _ in 0 .. n {
for _ in 0..n {
let numerator = try!(decoder.read_long());
let denominator = try!(decoder.read_long());
v.push(Rational(numerator, denominator))
}
Ok(List(v))
},
}
(Type::ASCII, n) => {
if n as usize > limits.decoding_buffer_size {
return Err(TiffError::LimitsExceeded)
return Err(TiffError::LimitsExceeded);
}
try!(decoder.goto_offset(try!(self.r(bo).read_u32())));
let string = try!(decoder.read_string(n as usize));
Ok(Ascii(string))
}
_ => Err(TiffError::UnsupportedError(TiffUnsupportedError::UnsupportedDataType))
_ => Err(TiffError::UnsupportedError(
TiffUnsupportedError::UnsupportedDataType,
)),
}
}
}
+226 -109
View File
@@ -1,18 +1,12 @@
use std::io::{self, Read, Seek};
use num_traits::{FromPrimitive, Num};
use std::collections::HashMap;
use std::io::{self, Read, Seek};
use ::{ColorType, TiffError, TiffFormatError, TiffUnsupportedError, TiffResult};
use {ColorType, TiffError, TiffFormatError, TiffResult, TiffUnsupportedError};
use self::ifd::Directory;
use self::stream::{
ByteOrder,
EndianReader,
SmartReader,
LZWReader,
PackBitsReader
};
use self::stream::{ByteOrder, EndianReader, LZWReader, PackBitsReader, SmartReader};
pub mod ifd;
mod stream;
@@ -23,15 +17,14 @@ pub enum DecodingResult {
/// A vector of unsigned bytes
U8(Vec<u8>),
/// A vector of unsigned words
U16(Vec<u16>)
U16(Vec<u16>),
}
impl DecodingResult {
fn new_u8(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
if size > limits.decoding_buffer_size {
Err(TiffError::LimitsExceeded)
}
else {
} else {
Ok(DecodingResult::U8(vec![0; size]))
}
}
@@ -39,8 +32,7 @@ impl DecodingResult {
fn new_u16(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
if size > limits.decoding_buffer_size / 2 {
Err(TiffError::LimitsExceeded)
}
else {
} else {
Ok(DecodingResult::U16(vec![0; size]))
}
}
@@ -58,7 +50,7 @@ pub enum DecodingBuffer<'a> {
/// A slice of unsigned bytes
U8(&'a mut [u8]),
/// A slice of unsigned words
U16(&'a mut [u16])
U16(&'a mut [u16]),
}
impl<'a> DecodingBuffer<'a> {
@@ -76,7 +68,10 @@ impl<'a> DecodingBuffer<'a> {
}
}
fn copy<'b>(&'b mut self) -> DecodingBuffer<'b> where 'a: 'b {
fn copy<'b>(&'b mut self) -> DecodingBuffer<'b>
where
'a: 'b,
{
match self {
DecodingBuffer::U8(ref mut buf) => DecodingBuffer::U8(buf),
DecodingBuffer::U16(ref mut buf) => DecodingBuffer::U16(buf),
@@ -104,19 +99,19 @@ pub enum CompressionMethod {
Fax4 = 4,
LZW = 5,
JPEG = 6,
PackBits = 0x8005
PackBits = 0x8005,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, FromPrimitive)]
pub enum PlanarConfiguration {
Chunky = 1,
Planar = 2
Planar = 2,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, FromPrimitive)]
enum Predictor {
None = 1,
Horizontal = 2
Horizontal = 2,
}
#[derive(Debug)]
@@ -129,12 +124,12 @@ struct StripDecodeState {
/// Decoding limits
#[derive(Clone, Debug)]
pub struct Limits {
/// The maximum size of any `DecodingResult` in bytes, the default is
/// The maximum size of any `DecodingResult` in bytes, the default is
/// 256MiB. If the entire image is decoded at once, then this will
/// be the maximum size of the image. If it is decoded one strip at a
/// time, this will be the maximum size of a strip.
decoding_buffer_size: usize,
/// The maximum size of any ifd value in bytes, the default is
/// The maximum size of any ifd value in bytes, the default is
/// 1MiB.
ifd_value_size: usize,
}
@@ -142,8 +137,8 @@ pub struct Limits {
impl Default for Limits {
fn default() -> Limits {
Limits {
decoding_buffer_size: 256*1024*1024,
ifd_value_size: 1024*1024,
decoding_buffer_size: 256 * 1024 * 1024,
ifd_value_size: 1024 * 1024,
}
}
}
@@ -152,7 +147,10 @@ impl Default for Limits {
///
/// Currently does not support decoding of interlaced images
#[derive(Debug)]
pub struct Decoder<R> where R: Read + Seek {
pub struct Decoder<R>
where
R: Read + Seek,
{
reader: SmartReader<R>,
byte_order: ByteOrder,
limits: Limits,
@@ -183,10 +181,10 @@ impl Wrapping for u16 {
}
}
fn rev_hpredict_nsamp<T>(image: &mut [T],
size: (u32, u32),
samples: usize)
where T: Num + Copy + Wrapping {
fn rev_hpredict_nsamp<T>(image: &mut [T], size: (u32, u32), samples: usize)
where
T: Num + Copy + Wrapping,
{
let width = size.0 as usize;
let height = size.1 as usize;
for row in 0..height {
@@ -203,12 +201,16 @@ fn rev_hpredict(image: DecodingBuffer, size: (u32, u32), color_type: ColorType)
ColorType::Gray(8) | ColorType::Gray(16) => 1,
ColorType::RGB(8) | ColorType::RGB(16) => 3,
ColorType::RGBA(8) | ColorType::RGBA(16) | ColorType::CMYK(8) => 4,
_ => return Err(TiffError::UnsupportedError(TiffUnsupportedError::HorizontalPredictor(color_type)))
_ => {
return Err(TiffError::UnsupportedError(
TiffUnsupportedError::HorizontalPredictor(color_type),
))
}
};
match image {
DecodingBuffer::U8(buf) => {
rev_hpredict_nsamp(buf, size, samples);
},
}
DecodingBuffer::U16(buf) => {
rev_hpredict_nsamp(buf, size, samples);
}
@@ -232,7 +234,8 @@ impl<R: Read + Seek> Decoder<R> {
photometric_interpretation: PhotometricInterpretation::BlackIsZero,
compression_method: CompressionMethod::None,
strip_decoder: None,
}.init()
}
.init()
}
pub fn with_limits(mut self, limits: Limits) -> Decoder<R> {
@@ -247,16 +250,34 @@ impl<R: Read + Seek> Decoder<R> {
pub fn colortype(&mut self) -> TiffResult<ColorType> {
match self.photometric_interpretation {
// TODO: catch also [ 8, 8, 8, _] this does not work due to a bug in rust atm
PhotometricInterpretation::RGB if self.bits_per_sample == [8, 8, 8, 8] => Ok(ColorType::RGBA(8)),
PhotometricInterpretation::RGB if self.bits_per_sample == [8, 8, 8] => Ok(ColorType::RGB(8)),
PhotometricInterpretation::RGB if self.bits_per_sample == [16, 16, 16, 16] => Ok(ColorType::RGBA(16)),
PhotometricInterpretation::RGB if self.bits_per_sample == [16, 16, 16] => Ok(ColorType::RGB(16)),
PhotometricInterpretation::CMYK if self.bits_per_sample == [8, 8, 8, 8] => Ok(ColorType::CMYK(8)),
PhotometricInterpretation::RGB if self.bits_per_sample == [8, 8, 8, 8] => {
Ok(ColorType::RGBA(8))
}
PhotometricInterpretation::RGB if self.bits_per_sample == [8, 8, 8] => {
Ok(ColorType::RGB(8))
}
PhotometricInterpretation::RGB if self.bits_per_sample == [16, 16, 16, 16] => {
Ok(ColorType::RGBA(16))
}
PhotometricInterpretation::RGB if self.bits_per_sample == [16, 16, 16] => {
Ok(ColorType::RGB(16))
}
PhotometricInterpretation::CMYK if self.bits_per_sample == [8, 8, 8, 8] => {
Ok(ColorType::CMYK(8))
}
PhotometricInterpretation::BlackIsZero | PhotometricInterpretation::WhiteIsZero
if self.bits_per_sample.len() == 1 => Ok(ColorType::Gray(self.bits_per_sample[0])),
if self.bits_per_sample.len() == 1 =>
{
Ok(ColorType::Gray(self.bits_per_sample[0]))
}
// TODO: this is bad we should not fail at this point
_ => Err(TiffError::UnsupportedError(TiffUnsupportedError::InterpretationWithBits(self.photometric_interpretation, self.bits_per_sample.clone())))
_ => Err(TiffError::UnsupportedError(
TiffUnsupportedError::InterpretationWithBits(
self.photometric_interpretation,
self.bits_per_sample.clone(),
),
)),
}
}
@@ -266,18 +287,26 @@ impl<R: Read + Seek> Decoder<R> {
match &*endianess {
b"II" => {
self.byte_order = ByteOrder::LittleEndian;
self.reader.byte_order = ByteOrder::LittleEndian; },
self.reader.byte_order = ByteOrder::LittleEndian;
}
b"MM" => {
self.byte_order = ByteOrder::BigEndian;
self.reader.byte_order = ByteOrder::BigEndian; },
_ => return Err(TiffError::FormatError(TiffFormatError::TiffSignatureNotFound))
self.reader.byte_order = ByteOrder::BigEndian;
}
_ => {
return Err(TiffError::FormatError(
TiffFormatError::TiffSignatureNotFound,
))
}
}
if try!(self.read_short()) != 42 {
return Err(TiffError::FormatError(TiffFormatError::TiffSignatureInvalid))
return Err(TiffError::FormatError(
TiffFormatError::TiffSignatureInvalid,
));
}
self.next_ifd = match try!(self.read_long()) {
0 => None,
n => Some(n)
n => Some(n),
};
Ok(())
}
@@ -296,18 +325,24 @@ impl<R: Read + Seek> Decoder<R> {
self.width = try!(self.get_tag_u32(ifd::Tag::ImageWidth));
self.height = try!(self.get_tag_u32(ifd::Tag::ImageLength));
self.strip_decoder = None;
self.photometric_interpretation = match FromPrimitive::from_u32(
try!(self.get_tag_u32(ifd::Tag::PhotometricInterpretation))
) {
self.photometric_interpretation = match FromPrimitive::from_u32(try!(
self.get_tag_u32(ifd::Tag::PhotometricInterpretation)
)) {
Some(val) => val,
None => return Err(TiffError::UnsupportedError(TiffUnsupportedError::UnknownInterpretation))
None => {
return Err(TiffError::UnsupportedError(
TiffUnsupportedError::UnknownInterpretation,
))
}
};
if let Some(val) = try!(self.find_tag_u32(ifd::Tag::Compression)) {
match FromPrimitive::from_u32(val) {
Some(method) => {
self.compression_method = method
},
None => return Err(TiffError::UnsupportedError(TiffUnsupportedError::UnknownCompressionMethod))
Some(method) => self.compression_method = method,
None => {
return Err(TiffError::UnsupportedError(
TiffUnsupportedError::UnknownCompressionMethod,
))
}
}
}
if let Some(val) = try!(self.find_tag_u32(ifd::Tag::SamplesPerPixel)) {
@@ -323,9 +358,12 @@ impl<R: Read + Seek> Decoder<R> {
if let Some(val) = try!(self.find_tag_u32_vec(ifd::Tag::BitsPerSample)) {
self.bits_per_sample = val.iter().map(|&v| v as u8).collect()
}
}
_ => return Err(TiffError::UnsupportedError(TiffUnsupportedError::UnsupportedSampleDepth(self.samples)))
_ => {
return Err(TiffError::UnsupportedError(
TiffUnsupportedError::UnsupportedSampleDepth(self.samples),
))
}
}
Ok(self)
}
@@ -373,7 +411,9 @@ impl<R: Read + Seek> Decoder<R> {
/// Moves the cursor to the specified offset
#[inline]
pub fn goto_offset(&mut self, offset: u32) -> io::Result<()> {
self.reader.seek(io::SeekFrom::Start(u64::from(offset))).map(|_| ())
self.reader
.seek(io::SeekFrom::Start(u64::from(offset)))
.map(|_| ())
}
/// Reads a IFD entry.
@@ -391,34 +431,40 @@ impl<R: Read + Seek> Decoder<R> {
// Unknown type. Skip this entry according to spec.
try!(self.read_long());
try!(self.read_long());
return Ok(None)
return Ok(None);
}
};
Ok(Some((tag, ifd::Entry::new(
type_,
try!(self.read_long()), // count
try!(self.read_offset()) // offset
))))
Ok(Some((
tag,
ifd::Entry::new(
type_,
try!(self.read_long()), // count
try!(self.read_offset()), // offset
),
)))
}
/// Reads the next IFD
fn read_ifd(&mut self) -> TiffResult<Directory> {
let mut dir: Directory = HashMap::new();
match self.next_ifd {
None => return Err(TiffError::FormatError(TiffFormatError::ImageFileDirectoryNotFound)),
Some(offset) => try!(self.goto_offset(offset))
None => {
return Err(TiffError::FormatError(
TiffFormatError::ImageFileDirectoryNotFound,
))
}
Some(offset) => try!(self.goto_offset(offset)),
}
for _ in 0..try!(self.read_short()) {
let (tag, entry) = match try!(self.read_entry()) {
Some(val) => val,
None => continue // Unknown data type in tag, skip
None => continue, // Unknown data type in tag, skip
};
dir.insert(tag, entry);
}
self.next_ifd = match try!(self.read_long()) {
0 => None,
n => Some(n)
n => Some(n),
};
Ok(dir)
}
@@ -440,7 +486,7 @@ impl<R: Read + Seek> Decoder<R> {
pub fn find_tag_u32(&mut self, tag: ifd::Tag) -> TiffResult<Option<u32>> {
match self.find_tag(tag)? {
Some(val) => val.into_u32().map(Some),
None => Ok(None)
None => Ok(None),
}
}
@@ -448,7 +494,7 @@ impl<R: Read + Seek> Decoder<R> {
pub fn find_tag_u32_vec(&mut self, tag: ifd::Tag) -> TiffResult<Option<Vec<u32>>> {
match self.find_tag(tag)? {
Some(val) => val.into_u32_vec().map(Some),
None => Ok(None)
None => Ok(None),
}
}
@@ -457,7 +503,9 @@ impl<R: Read + Seek> Decoder<R> {
pub fn get_tag(&mut self, tag: ifd::Tag) -> TiffResult<ifd::Value> {
match try!(self.find_tag(tag)) {
Some(val) => Ok(val),
None => Err(TiffError::FormatError(TiffFormatError::RequiredTagNotFound(tag))),
None => Err(TiffError::FormatError(
TiffFormatError::RequiredTagNotFound(tag),
)),
}
}
@@ -473,50 +521,73 @@ impl<R: Read + Seek> Decoder<R> {
/// Decompresses the strip into the supplied buffer.
/// Returns the number of bytes read.
fn expand_strip<'a>(&mut self, buffer: DecodingBuffer<'a>, offset: u32, length: u32, max_uncompressed_length: usize) -> TiffResult<usize> {
fn expand_strip<'a>(
&mut self,
buffer: DecodingBuffer<'a>,
offset: u32,
length: u32,
max_uncompressed_length: usize,
) -> TiffResult<usize> {
let color_type = try!(self.colortype());
try!(self.goto_offset(offset));
let (bytes, mut reader): (usize, Box<EndianReader>) = match self.compression_method {
CompressionMethod::None => {
let order = self.reader.byte_order;
(length as usize, Box::new(SmartReader::wrap(&mut self.reader, order)))
},
(
length as usize,
Box::new(SmartReader::wrap(&mut self.reader, order)),
)
}
CompressionMethod::LZW => {
let (bytes, reader) = try!(LZWReader::new(&mut self.reader, length as usize, max_uncompressed_length));
let (bytes, reader) = try!(LZWReader::new(
&mut self.reader,
length as usize,
max_uncompressed_length
));
(bytes, Box::new(reader))
},
}
CompressionMethod::PackBits => {
let order = self.reader.byte_order;
let (bytes, reader) = try!(PackBitsReader::new(&mut self.reader, order, length as usize));
let (bytes, reader) = try!(PackBitsReader::new(
&mut self.reader,
order,
length as usize
));
(bytes, Box::new(reader))
},
method => return Err(TiffError::UnsupportedError(TiffUnsupportedError::UnsupportedCompressionMethod(method)))
}
method => {
return Err(TiffError::UnsupportedError(
TiffUnsupportedError::UnsupportedCompressionMethod(method),
))
}
};
if bytes / buffer.byte_len() > max_uncompressed_length {
return Err(TiffError::FormatError(TiffFormatError::InconsistentSizesEncountered));
return Err(TiffError::FormatError(
TiffFormatError::InconsistentSizesEncountered,
));
}
Ok(match (color_type, buffer) {
(ColorType:: RGB(8), DecodingBuffer::U8(ref mut buffer)) |
(ColorType::RGBA(8), DecodingBuffer::U8(ref mut buffer)) |
(ColorType::CMYK(8), DecodingBuffer::U8(ref mut buffer)) => {
(ColorType::RGB(8), DecodingBuffer::U8(ref mut buffer))
| (ColorType::RGBA(8), DecodingBuffer::U8(ref mut buffer))
| (ColorType::CMYK(8), DecodingBuffer::U8(ref mut buffer)) => {
try!(reader.read_exact(&mut buffer[..bytes]));
bytes
}
(ColorType::RGBA(16), DecodingBuffer::U16(ref mut buffer)) |
(ColorType:: RGB(16), DecodingBuffer::U16(ref mut buffer)) => {
try!(reader.read_u16_into(&mut buffer[..bytes/2]));
bytes/2
(ColorType::RGBA(16), DecodingBuffer::U16(ref mut buffer))
| (ColorType::RGB(16), DecodingBuffer::U16(ref mut buffer)) => {
try!(reader.read_u16_into(&mut buffer[..bytes / 2]));
bytes / 2
}
(ColorType::Gray(16), DecodingBuffer::U16(ref mut buffer)) => {
try!(reader.read_u16_into(&mut buffer[..bytes/2]));
try!(reader.read_u16_into(&mut buffer[..bytes / 2]));
if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero {
for datum in buffer[..bytes/2].iter_mut() {
for datum in buffer[..bytes / 2].iter_mut() {
*datum = 0xffff - *datum
}
}
bytes/2
bytes / 2
}
(ColorType::Gray(n), DecodingBuffer::U8(ref mut buffer)) if n <= 8 => {
try!(reader.read_exact(&mut buffer[..bytes]));
@@ -527,15 +598,20 @@ impl<R: Read + Seek> Decoder<R> {
}
bytes
}
(type_, _) => return Err(TiffError::UnsupportedError(TiffUnsupportedError::UnsupportedColorType(type_))),
(type_, _) => {
return Err(TiffError::UnsupportedError(
TiffUnsupportedError::UnsupportedColorType(type_),
))
}
})
}
/// Number of strips in image
pub fn strip_count(&mut self) -> TiffResult<u32> {
let rows_per_strip = self.get_tag_u32(ifd::Tag::RowsPerStrip)
let rows_per_strip = self
.get_tag_u32(ifd::Tag::RowsPerStrip)
.unwrap_or(self.height);
Ok((self.height + rows_per_strip - 1) / rows_per_strip)
}
@@ -557,20 +633,40 @@ impl<R: Read + Seek> Decoder<R> {
self.initialize_strip_decoder()?;
let index = self.strip_decoder.as_ref().unwrap().strip_index;
let offset = *self.strip_decoder.as_ref().unwrap().strip_offsets.get(index)
.ok_or(TiffError::FormatError(TiffFormatError::InconsistentSizesEncountered))?;
let byte_count = *self.strip_decoder.as_ref().unwrap().strip_bytes.get(index)
.ok_or(TiffError::FormatError(TiffFormatError::InconsistentSizesEncountered))?;
let offset = *self
.strip_decoder
.as_ref()
.unwrap()
.strip_offsets
.get(index)
.ok_or(TiffError::FormatError(
TiffFormatError::InconsistentSizesEncountered,
))?;
let byte_count = *self
.strip_decoder
.as_ref()
.unwrap()
.strip_bytes
.get(index)
.ok_or(TiffError::FormatError(
TiffFormatError::InconsistentSizesEncountered,
))?;
let rows_per_strip = self.get_tag_u32(ifd::Tag::RowsPerStrip)
let rows_per_strip = self
.get_tag_u32(ifd::Tag::RowsPerStrip)
.unwrap_or(self.height) as usize;
let strip_height = std::cmp::min(rows_per_strip, self.height as usize - index * rows_per_strip);
let strip_height = std::cmp::min(
rows_per_strip,
self.height as usize - index * rows_per_strip,
);
let buffer_size = self.width as usize * strip_height * self.bits_per_sample.len();
if buffer.len() < buffer_size || byte_count as usize / buffer.byte_len() > buffer_size {
return Err(TiffError::FormatError(TiffFormatError::InconsistentSizesEncountered));
return Err(TiffError::FormatError(
TiffFormatError::InconsistentSizesEncountered,
));
}
let units_read = self.expand_strip(buffer.copy(), offset, byte_count, buffer_size)?;
@@ -582,7 +678,9 @@ impl<R: Read + Seek> Decoder<R> {
}
if units_read < buffer_size {
return Err(TiffError::FormatError(TiffFormatError::InconsistentSizesEncountered));
return Err(TiffError::FormatError(
TiffFormatError::InconsistentSizesEncountered,
));
}
if let Ok(predictor) = self.get_tag_u32(ifd::Tag::Predictor) {
match FromPrimitive::from_u32(predictor) {
@@ -591,10 +689,14 @@ impl<R: Read + Seek> Decoder<R> {
rev_hpredict(
buffer.copy(),
(self.width, strip_height as u32),
self.colortype()?
self.colortype()?,
)?;
},
None => return Err(TiffError::FormatError(TiffFormatError::UnknownPredictor(predictor))),
}
None => {
return Err(TiffError::FormatError(TiffFormatError::UnknownPredictor(
predictor,
)))
}
}
}
Ok(())
@@ -605,17 +707,25 @@ impl<R: Read + Seek> Decoder<R> {
self.initialize_strip_decoder()?;
let index = self.strip_decoder.as_ref().unwrap().strip_index;
let rows_per_strip = self.get_tag_u32(ifd::Tag::RowsPerStrip)
let rows_per_strip = self
.get_tag_u32(ifd::Tag::RowsPerStrip)
.unwrap_or(self.height) as usize;
let strip_height = std::cmp::min(rows_per_strip, self.height as usize - index * rows_per_strip);
let strip_height = std::cmp::min(
rows_per_strip,
self.height as usize - index * rows_per_strip,
);
let buffer_size = self.width as usize * strip_height * self.bits_per_sample.iter().count();
let mut result = match self.bits_per_sample.iter().cloned().max().unwrap_or(8) {
n if n <= 8 => DecodingResult::new_u8(buffer_size, &self.limits)?,
n if n <= 16 => DecodingResult::new_u16(buffer_size, &self.limits)?,
n => return Err(TiffError::UnsupportedError(TiffUnsupportedError::UnsupportedBitsPerChannel(n))),
n => {
return Err(TiffError::UnsupportedError(
TiffUnsupportedError::UnsupportedBitsPerChannel(n),
))
}
};
self.read_strip_to_buffer(result.as_buffer(0))?;
@@ -626,17 +736,24 @@ impl<R: Read + Seek> Decoder<R> {
/// Decodes the entire image and return it as a Vector
pub fn read_image(&mut self) -> TiffResult<DecodingResult> {
self.initialize_strip_decoder()?;
let rows_per_strip = self.get_tag_u32(ifd::Tag::RowsPerStrip)
let rows_per_strip = self
.get_tag_u32(ifd::Tag::RowsPerStrip)
.unwrap_or(self.height) as usize;
let samples_per_strip = self.width as usize * rows_per_strip * self.bits_per_sample.iter().count();
let samples_per_strip =
self.width as usize * rows_per_strip * self.bits_per_sample.iter().count();
let buffer_size = self.width as usize * self.height as usize * self.bits_per_sample.iter().count();
let buffer_size =
self.width as usize * self.height as usize * self.bits_per_sample.iter().count();
let mut result = match self.bits_per_sample.iter().cloned().max().unwrap_or(8) {
n if n <= 8 => DecodingResult::new_u8(buffer_size, &self.limits)?,
n if n <= 16 => DecodingResult::new_u16(buffer_size, &self.limits)?,
n => return Err(TiffError::UnsupportedError(TiffUnsupportedError::UnsupportedBitsPerChannel(n))),
n => {
return Err(TiffError::UnsupportedError(
TiffUnsupportedError::UnsupportedBitsPerChannel(n),
))
}
};
for i in 0..self.strip_count()? as usize {
+66 -33
View File
@@ -1,8 +1,8 @@
//! All IO functionality needed for TIFF decoding
use std::io::{self, Read, Seek};
use byteorder::{ReadBytesExt, BigEndian, LittleEndian};
use byteorder::{BigEndian, LittleEndian, ReadBytesExt};
use lzw;
use std::io::{self, Read, Seek};
/// Byte order of the TIFF file.
#[derive(Clone, Copy, Debug)]
@@ -10,10 +10,9 @@ pub enum ByteOrder {
/// little endian byte order
LittleEndian,
/// big endian byte order
BigEndian
BigEndian,
}
/// Reader that is aware of the byte order.
pub trait EndianReader: Read {
/// Byte order that should be adhered to
@@ -24,15 +23,19 @@ pub trait EndianReader: Read {
fn read_u16(&mut self) -> Result<u16, io::Error> {
match self.byte_order() {
ByteOrder::LittleEndian => <Self as ReadBytesExt>::read_u16::<LittleEndian>(self),
ByteOrder::BigEndian => <Self as ReadBytesExt>::read_u16::<BigEndian>(self)
ByteOrder::BigEndian => <Self as ReadBytesExt>::read_u16::<BigEndian>(self),
}
}
#[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)
ByteOrder::LittleEndian => {
<Self as ReadBytesExt>::read_u16_into::<LittleEndian>(self, buffer)
}
ByteOrder::BigEndian => {
<Self as ReadBytesExt>::read_u16_into::<BigEndian>(self, buffer)
}
}
}
@@ -41,7 +44,7 @@ pub trait EndianReader: Read {
fn read_u32(&mut self) -> Result<u32, io::Error> {
match self.byte_order() {
ByteOrder::LittleEndian => <Self as ReadBytesExt>::read_u32::<LittleEndian>(self),
ByteOrder::BigEndian => <Self as ReadBytesExt>::read_u32::<BigEndian>(self)
ByteOrder::BigEndian => <Self as ReadBytesExt>::read_u32::<BigEndian>(self),
}
}
}
@@ -49,12 +52,19 @@ pub trait EndianReader: Read {
/// Reader that decompresses LZW streams
pub struct LZWReader {
buffer: io::Cursor<Vec<u8>>,
byte_order: ByteOrder
byte_order: ByteOrder,
}
impl LZWReader {
/// Wraps a reader
pub fn new<R>(reader: &mut SmartReader<R>, compressed_length: usize, max_uncompressed_length: usize) -> io::Result<(usize, LZWReader)> where R: Read + Seek {
pub fn new<R>(
reader: &mut SmartReader<R>,
compressed_length: usize,
max_uncompressed_length: usize,
) -> io::Result<(usize, LZWReader)>
where
R: Read + Seek,
{
let order = reader.byte_order;
let mut compressed = vec![0; compressed_length as usize];
try!(reader.read_exact(&mut compressed[..]));
@@ -68,10 +78,13 @@ impl LZWReader {
}
let bytes = uncompressed.len();
Ok((bytes, LZWReader {
buffer: io::Cursor::new(uncompressed),
byte_order: order
}))
Ok((
bytes,
LZWReader {
buffer: io::Cursor::new(uncompressed),
byte_order: order,
},
))
}
}
@@ -92,25 +105,32 @@ impl EndianReader for LZWReader {
/// Reader that unpacks Apple's `PackBits` format
pub struct PackBitsReader {
buffer: io::Cursor<Vec<u8>>,
byte_order: ByteOrder
byte_order: ByteOrder,
}
impl PackBitsReader {
/// Wraps a reader
pub fn new<R: Read + Seek>(mut reader: R, byte_order: ByteOrder, length: usize) -> io::Result<(usize, PackBitsReader)> {
pub fn new<R: Read + Seek>(
mut reader: R,
byte_order: ByteOrder,
length: usize,
) -> io::Result<(usize, PackBitsReader)> {
let mut buffer = Vec::new();
let mut read: usize = 0;
while read < length {
let lread = read_packbits_run(&mut reader, &mut buffer)?;
if lread == 0 {
return Err(io::ErrorKind::UnexpectedEof.into())
return Err(io::ErrorKind::UnexpectedEof.into());
}
read += lread;
}
Ok((buffer.len(), PackBitsReader {
buffer: io::Cursor::new(buffer),
byte_order
}))
Ok((
buffer.len(),
PackBitsReader {
buffer: io::Cursor::new(buffer),
byte_order,
},
))
}
}
@@ -128,7 +148,7 @@ fn read_packbits_run<R: Read + Seek>(reader: &mut R, buffer: &mut Vec<u8>) -> io
try!(reader.read_exact(&mut header));
buffer.resize(new_len, header[0]);
Ok(2)
},
}
h => {
let num_vals = h as usize + 1;
let start = buffer.len();
@@ -136,7 +156,7 @@ fn read_packbits_run<R: Read + Seek>(reader: &mut R, buffer: &mut Vec<u8>) -> io
try!(reader.read_exact(&mut buffer[start..]));
Ok(num_vals + 1)
}
}
},
}
}
@@ -156,19 +176,28 @@ impl EndianReader for PackBitsReader {
/// Reader that is aware of the byte order.
#[derive(Debug)]
pub struct SmartReader<R> where R: Read + Seek {
pub struct SmartReader<R>
where
R: Read + Seek,
{
reader: R,
pub byte_order: ByteOrder
pub byte_order: ByteOrder,
}
impl<R> SmartReader<R> where R: Read + Seek {
impl<R> SmartReader<R>
where
R: Read + Seek,
{
/// Wraps a reader
pub fn wrap(reader: R, byte_order: ByteOrder) -> SmartReader<R> {
SmartReader { reader, byte_order }
}
}
impl<R> EndianReader for SmartReader<R> where R: Read + Seek {
impl<R> EndianReader for SmartReader<R>
where
R: Read + Seek,
{
#[inline(always)]
fn byte_order(&self) -> ByteOrder {
self.byte_order
@@ -195,19 +224,23 @@ mod test {
#[test]
fn test_packbits() {
let encoded = vec![0xFE, 0xAA, 0x02, 0x80, 0x00, 0x2A, 0xFD, 0xAA,
0x03, 0x80, 0x00, 0x2A, 0x22, 0xF7, 0xAA];
let encoded = vec![
0xFE, 0xAA, 0x02, 0x80, 0x00, 0x2A, 0xFD, 0xAA, 0x03, 0x80, 0x00, 0x2A, 0x22, 0xF7,
0xAA,
];
let encoded_len = encoded.len();
let buff = io::Cursor::new(encoded);
let (_, mut decoder) = PackBitsReader::new(buff, ByteOrder::LittleEndian, encoded_len).unwrap();
let (_, mut decoder) =
PackBitsReader::new(buff, ByteOrder::LittleEndian, encoded_len).unwrap();
let mut decoded = Vec::new();
decoder.read_to_end(&mut decoded).unwrap();
let expected = vec![0xAA, 0xAA, 0xAA, 0x80, 0x00, 0x2A, 0xAA, 0xAA,
0xAA, 0xAA, 0x80, 0x00, 0x2A, 0x22, 0xAA, 0xAA,
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA];
let expected = vec![
0xAA, 0xAA, 0xAA, 0x80, 0x00, 0x2A, 0xAA, 0xAA, 0xAA, 0xAA, 0x80, 0x00, 0x2A, 0x22,
0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
];
assert_eq!(decoded, expected);
}
}
+51 -32
View File
@@ -1,15 +1,15 @@
use std::io::{Write, Seek};
use byteorder::NativeEndian;
use std::collections::BTreeMap;
use byteorder::{NativeEndian};
use std::io::{Seek, Write};
use crate::decoder::ifd::{self, Tag};
use crate::error::{TiffResult, TiffFormatError, TiffError};
use crate::error::{TiffError, TiffFormatError, TiffResult};
mod writer;
pub mod colortype;
mod writer;
use self::writer::*;
use self::colortype::*;
use self::writer::*;
/// Type to represent tiff values of type `RATIONAL`
#[derive(Clone)]
@@ -60,9 +60,8 @@ impl TiffValue for [u16] {
fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
// We write using nativeedian so this sould be safe
let slice = unsafe {
std::slice::from_raw_parts(self.as_ptr() as *const u8, self.len()*2)
};
let slice =
unsafe { std::slice::from_raw_parts(self.as_ptr() as *const u8, self.len() * 2) };
writer.write_bytes(slice)?;
Ok(())
}
@@ -78,9 +77,8 @@ impl TiffValue for [u32] {
fn write<W: Write>(&self, writer: &mut TiffWriter<W>) -> TiffResult<()> {
// We write using nativeedian so this sould be safe
let slice = unsafe {
std::slice::from_raw_parts(self.as_ptr() as *const u8, self.len()*4)
};
let slice =
unsafe { std::slice::from_raw_parts(self.as_ptr() as *const u8, self.len() * 4) };
writer.write_bytes(slice)?;
Ok(())
}
@@ -172,8 +170,7 @@ impl TiffValue for str {
writer.write_bytes(self.as_bytes())?;
writer.write_u8(0)?;
Ok(())
}
else {
} else {
Err(TiffError::FormatError(TiffFormatError::InvalidTag))
}
}
@@ -219,7 +216,7 @@ impl<W: Write + Seek> TiffEncoder<W> {
let mut encoder = TiffEncoder {
writer: TiffWriter::new(writer),
};
NativeEndian::write_header(&mut encoder.writer)?;
Ok(encoder)
@@ -231,20 +228,32 @@ impl<W: Write + Seek> TiffEncoder<W> {
}
/// Create an 'ImageEncoder' to encode an image one slice at a time.
pub fn new_image<C: ColorType>(&mut self, width: u32, height: u32) -> TiffResult<ImageEncoder<W, C>> {
pub fn new_image<C: ColorType>(
&mut self,
width: u32,
height: u32,
) -> TiffResult<ImageEncoder<W, C>> {
let encoder = DirectoryEncoder::new(&mut self.writer)?;
ImageEncoder::new(encoder, width, height)
}
/// Convenience function to write an entire image from memory.
pub fn write_image<C: ColorType>(&mut self, width: u32, height: u32, data: &[C::Inner]) -> TiffResult<()> where [C::Inner]: TiffValue {
pub fn write_image<C: ColorType>(
&mut self,
width: u32,
height: u32,
data: &[C::Inner],
) -> TiffResult<()>
where
[C::Inner]: TiffValue,
{
let encoder = DirectoryEncoder::new(&mut self.writer)?;
let mut image: ImageEncoder<W, C> = ImageEncoder::new(encoder, width, height).unwrap();
let mut idx = 0;
while image.next_strip_sample_count() > 0 {
let sample_count = image.next_strip_sample_count() as usize;
image.write_strip(&data[idx..idx+sample_count]).unwrap();
image.write_strip(&data[idx..idx + sample_count]).unwrap();
idx += sample_count;
}
image.finish()
@@ -285,7 +294,8 @@ impl<'a, W: Write + Seek> DirectoryEncoder<'a, W> {
value.write(&mut writer).unwrap();
}
self.ifd.insert(tag.to_u16(), (<T>::FIELD_TYPE as u16, value.count(), bytes));
self.ifd
.insert(tag.to_u16(), (<T>::FIELD_TYPE as u16, value.count(), bytes));
}
fn write_directory(&mut self) -> TiffResult<u64> {
@@ -297,15 +307,14 @@ impl<'a, W: Write + Seek> DirectoryEncoder<'a, W> {
*bytes = vec![0, 0, 0, 0];
let mut writer = TiffWriter::new(bytes as &mut [u8]);
writer.write_u32(offset as u32)?;
}
else {
} else {
while bytes.len() < 4 {
bytes.push(0);
}
}
}
let offset = self.writer.offset();
let offset = self.writer.offset();
self.writer.write_u16(self.ifd.len() as u16)?;
for (tag, (field_type, count, offset)) in self.ifd.iter() {
@@ -355,7 +364,6 @@ impl<'a, W: Write + Seek> Drop for DirectoryEncoder<'a, W> {
}
}
/// Type to encode images strip by strip.
///
/// You should call `finish` on this when you are finished with it.
@@ -393,7 +401,11 @@ pub struct ImageEncoder<'a, W: Write + Seek, C: ColorType> {
}
impl<'a, W: Write + Seek, T: ColorType> ImageEncoder<'a, W, T> {
fn new(mut encoder: DirectoryEncoder<'a, W>, width: u32, height: u32) -> TiffResult<ImageEncoder<'a, W, T>> {
fn new(
mut encoder: DirectoryEncoder<'a, W>,
width: u32,
height: u32,
) -> TiffResult<ImageEncoder<'a, W, T>> {
let row_samples = u64::from(width) * <T>::BITS_PER_SAMPLE.len() as u64;
let row_bytes = row_samples * u64::from(<T::Inner>::BYTE_LEN);
@@ -412,10 +424,10 @@ impl<'a, W: Write + Seek, T: ColorType> ImageEncoder<'a, W, T> {
encoder.write_tag(Tag::RowsPerStrip, rows_per_strip as u32);
encoder.write_tag(Tag::SamplesPerPixel, <T>::BITS_PER_SAMPLE.len() as u16);
encoder.write_tag(Tag::XResolution, Rational {n: 1, d: 1});
encoder.write_tag(Tag::YResolution, Rational {n: 1, d: 1});
encoder.write_tag(Tag::XResolution, Rational { n: 1, d: 1 });
encoder.write_tag(Tag::YResolution, Rational { n: 1, d: 1 });
encoder.write_tag(Tag::ResolutionUnit, 1u16);
Ok(ImageEncoder {
encoder,
strip_count,
@@ -433,17 +445,23 @@ impl<'a, W: Write + Seek, T: ColorType> ImageEncoder<'a, W, T> {
/// Number of samples the next strip should have.
pub fn next_strip_sample_count(&self) -> u64 {
if self.strip_idx >= self.strip_count {
return 0
return 0;
}
let start_row = std::cmp::min(u64::from(self.height), self.strip_idx * self.rows_per_strip);
let end_row = std::cmp::min(u64::from(self.height), (self.strip_idx+1)*self.rows_per_strip);
let end_row = std::cmp::min(
u64::from(self.height),
(self.strip_idx + 1) * self.rows_per_strip,
);
(end_row - start_row) * self.row_samples
}
/// Write a single strip.
pub fn write_strip(&mut self, value: &[T::Inner]) -> TiffResult<()> where [T::Inner]: TiffValue {
pub fn write_strip(&mut self, value: &[T::Inner]) -> TiffResult<()>
where
[T::Inner]: TiffValue,
{
// TODO: Compression
let samples = self.next_strip_sample_count();
assert_eq!(value.len() as u64, samples);
@@ -479,8 +497,10 @@ impl<'a, W: Write + Seek, T: ColorType> ImageEncoder<'a, W, T> {
}
fn finish_internal(&mut self) -> TiffResult<()> {
self.encoder.write_tag(Tag::StripOffsets, &*self.strip_offsets);
self.encoder.write_tag(Tag::StripByteCounts, &*self.strip_byte_count);
self.encoder
.write_tag(Tag::StripOffsets, &*self.strip_offsets);
self.encoder
.write_tag(Tag::StripByteCounts, &*self.strip_byte_count);
self.dropped = true;
self.encoder.finish_internal()
@@ -504,4 +524,3 @@ impl<'a, W: Write + Seek, C: ColorType> Drop for ImageEncoder<'a, W, C> {
}
}
}
+4 -7
View File
@@ -1,6 +1,6 @@
use std::io::{self, Write, Seek, SeekFrom};
use byteorder::{ByteOrder, WriteBytesExt, BigEndian, LittleEndian, NativeEndian};
use crate::error::TiffResult;
use byteorder::{BigEndian, ByteOrder, LittleEndian, NativeEndian, WriteBytesExt};
use std::io::{self, Seek, SeekFrom, Write};
pub trait TiffByteOrder: ByteOrder {
fn write_header<W: Write>(writer: &mut TiffWriter<W>) -> TiffResult<()>;
@@ -33,10 +33,7 @@ pub struct TiffWriter<W> {
impl<W: Write> TiffWriter<W> {
pub fn new(writer: W) -> Self {
Self {
writer,
offset: 0,
}
Self { writer, offset: 0 }
}
pub fn offset(&self) -> u64 {
@@ -82,7 +79,7 @@ impl<W: Write> TiffWriter<W> {
let padd_len = 4 - (self.offset % 4);
self.writer.write_all(&padding[..padd_len as usize])?;
}
Ok(())
}
}
+45 -18
View File
@@ -4,7 +4,7 @@ use std::io;
use std::string;
use decoder::ifd::{Tag, Value};
use decoder::{PhotometricInterpretation, CompressionMethod, PlanarConfiguration};
use decoder::{CompressionMethod, PhotometricInterpretation, PlanarConfiguration};
use ColorType;
/// Tiff error kinds.
@@ -45,8 +45,12 @@ impl fmt::Display for TiffFormatError {
InconsistentSizesEncountered => write!(fmt, "Inconsistent sizes encountered."),
InvalidTag => write!(fmt, "Image contains invalid tag."),
RequiredTagNotFound(ref tag) => write!(fmt, "Required tag `{:?}` not found.", tag),
UnknownPredictor(ref predictor) => write!(fmt, "Unknown predictor “{}” encountered", predictor),
UnsignedIntegerExpected(ref val) => write!(fmt, "Expected unsigned integer, {:?} found.", val),
UnknownPredictor(ref predictor) => {
write!(fmt, "Unknown predictor “{}” encountered", predictor)
}
UnsignedIntegerExpected(ref val) => {
write!(fmt, "Expected unsigned integer, {:?} found.", val)
}
}
}
}
@@ -69,17 +73,36 @@ impl fmt::Display for TiffUnsupportedError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
use self::TiffUnsupportedError::*;
match *self {
HorizontalPredictor(color_type) => write!(fmt, "Horizontal predictor for {:?} is unsupported.", color_type),
InterpretationWithBits(ref photometric_interpretation, ref bits_per_sample) => {
write!(fmt, "{:?} with {:?} bits per sample is unsupported", photometric_interpretation, bits_per_sample)
},
UnknownInterpretation => write!(fmt, "The image is using an unknown photometric interpretation."),
HorizontalPredictor(color_type) => write!(
fmt,
"Horizontal predictor for {:?} is unsupported.",
color_type
),
InterpretationWithBits(ref photometric_interpretation, ref bits_per_sample) => write!(
fmt,
"{:?} with {:?} bits per sample is unsupported",
photometric_interpretation, bits_per_sample
),
UnknownInterpretation => write!(
fmt,
"The image is using an unknown photometric interpretation."
),
UnknownCompressionMethod => write!(fmt, "Unknown compression method."),
UnsupportedCompressionMethod(method) => write!(fmt, "Compression method {:?} is unsupported", method),
UnsupportedSampleDepth(samples) => write!(fmt, "{} samples per pixel is supported.", samples),
UnsupportedColorType(color_type) => write!(fmt, "Color type {:?} is unsupported", color_type),
UnsupportedBitsPerChannel(bits) => write!(fmt, "{} bits per channel not supported", bits),
UnsupportedPlanarConfig(config) => write!(fmt, "Unsupported planar configuration “{:?}”.", config),
UnsupportedCompressionMethod(method) => {
write!(fmt, "Compression method {:?} is unsupported", method)
}
UnsupportedSampleDepth(samples) => {
write!(fmt, "{} samples per pixel is supported.", samples)
}
UnsupportedColorType(color_type) => {
write!(fmt, "Color type {:?} is unsupported", color_type)
}
UnsupportedBitsPerChannel(bits) => {
write!(fmt, "{} bits per channel not supported", bits)
}
UnsupportedPlanarConfig(config) => {
write!(fmt, "Unsupported planar configuration “{:?}”.", config)
}
UnsupportedDataType => write!(fmt, "Unsupported data type."),
}
}
@@ -89,8 +112,12 @@ impl fmt::Display for TiffError {
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
match *self {
TiffError::FormatError(ref e) => write!(fmt, "Format error: {}", e),
TiffError::UnsupportedError(ref f) => write!(fmt, "The Decoder does not support the \
image format `{}`", f),
TiffError::UnsupportedError(ref f) => write!(
fmt,
"The Decoder does not support the \
image format `{}`",
f
),
TiffError::IoError(ref e) => e.fmt(fmt),
TiffError::LimitsExceeded => write!(fmt, "The Decoder limits are exceeded"),
}
@@ -98,7 +125,7 @@ impl fmt::Display for TiffError {
}
impl Error for TiffError {
fn description (&self) -> &str {
fn description(&self) -> &str {
match *self {
TiffError::FormatError(..) => "Format error",
TiffError::UnsupportedError(..) => "Unsupported error",
@@ -107,10 +134,10 @@ impl Error for TiffError {
}
}
fn cause (&self) -> Option<&Error> {
fn cause(&self) -> Option<&Error> {
match *self {
TiffError::IoError(ref e) => Some(e),
_ => None
_ => None,
}
}
}
+3 -2
View File
@@ -8,14 +8,15 @@
extern crate byteorder;
extern crate lzw;
#[macro_use] extern crate num_derive;
#[macro_use]
extern crate num_derive;
extern crate num_traits;
pub mod decoder;
pub mod encoder;
mod error;
pub use self::error::{TiffError, TiffFormatError, TiffUnsupportedError, TiffResult};
pub use self::error::{TiffError, TiffFormatError, TiffResult, TiffUnsupportedError};
/// An enumeration over supported color types and their bit depths
#[derive(Copy, PartialEq, Eq, Debug, Clone, Hash)]
+22 -23
View File
@@ -1,14 +1,14 @@
extern crate tiff;
use tiff::decoder::{ifd::Tag, ifd::Value, Decoder, DecodingResult};
use tiff::ColorType;
use tiff::decoder::{Decoder, DecodingResult, ifd::Tag, ifd::Value};
use std::fs::File;
#[test]
fn test_gray_u8()
{
let img_file = File::open("./tests/images/minisblack-1c-8b.tiff").expect("Cannot find test image!");
fn test_gray_u8() {
let img_file =
File::open("./tests/images/minisblack-1c-8b.tiff").expect("Cannot find test image!");
let mut decoder = Decoder::new(img_file).expect("Cannot create decoder");
assert_eq!(decoder.colortype().unwrap(), ColorType::Gray(8));
let img_res = decoder.read_image();
@@ -16,8 +16,7 @@ fn test_gray_u8()
}
#[test]
fn test_rgb_u8()
{
fn test_rgb_u8() {
let img_file = File::open("./tests/images/rgb-3c-8b.tiff").expect("Cannot find test image!");
let mut decoder = Decoder::new(img_file).expect("Cannot create decoder");
assert_eq!(decoder.colortype().unwrap(), ColorType::RGB(8));
@@ -26,9 +25,9 @@ fn test_rgb_u8()
}
#[test]
fn test_gray_u16()
{
let img_file = File::open("./tests/images/minisblack-1c-16b.tiff").expect("Cannot find test image!");
fn test_gray_u16() {
let img_file =
File::open("./tests/images/minisblack-1c-16b.tiff").expect("Cannot find test image!");
let mut decoder = Decoder::new(img_file).expect("Cannot create decoder");
assert_eq!(decoder.colortype().unwrap(), ColorType::Gray(16));
let img_res = decoder.read_image();
@@ -36,8 +35,7 @@ fn test_gray_u16()
}
#[test]
fn test_rgb_u16()
{
fn test_rgb_u16() {
let img_file = File::open("./tests/images/rgb-3c-16b.tiff").expect("Cannot find test image!");
let mut decoder = Decoder::new(img_file).expect("Cannot create decoder");
assert_eq!(decoder.colortype().unwrap(), ColorType::RGB(16));
@@ -46,8 +44,7 @@ fn test_rgb_u16()
}
#[test]
fn test_string_tags()
{
fn test_string_tags() {
// these files have null-terminated strings for their Software tag. One has extra bytes after
// the null byte, so we check both to ensure that we're truncating properly
let filenames = vec!["minisblack-1c-16b.tiff", "rgb-3c-16b.tiff"];
@@ -55,10 +52,13 @@ fn test_string_tags()
let path = format!("./tests/images/{}", filename);
let img_file = File::open(path).expect("can't open file");
let mut decoder = Decoder::new(img_file).expect("Cannot create decoder");
let software= decoder.get_tag(Tag::Software).unwrap();
let software = decoder.get_tag(Tag::Software).unwrap();
match software {
Value::Ascii(s) => assert_eq!(s, String::from("GraphicsMagick 1.2 unreleased Q16 http://www.GraphicsMagick.org/")),
_ => assert!(false)
Value::Ascii(s) => assert_eq!(
s,
String::from("GraphicsMagick 1.2 unreleased Q16 http://www.GraphicsMagick.org/")
),
_ => assert!(false),
};
}
}
@@ -80,8 +80,7 @@ fn test_decode_data() {
assert_eq!(decoder.dimensions().unwrap(), (100, 100));
if let DecodingResult::U8(img_res) = decoder.read_image().unwrap() {
assert_eq!(image_data, img_res);
}
else {
} else {
panic!("Wrong data type");
}
}
@@ -90,9 +89,9 @@ fn test_decode_data() {
//#[test]
//fn test_gray_alpha_u8()
//{
//let img_file = File::open("./tests/images/minisblack-2c-8b-alpha.tiff").expect("Cannot find test image!");
//let mut decoder = Decoder::new(img_file).expect("Cannot create decoder");
//assert_eq!(decoder.colortype().unwrap(), ColorType::GrayA(8));
//let img_res = decoder.read_image();
//assert!(img_res.is_ok());
//let img_file = File::open("./tests/images/minisblack-2c-8b-alpha.tiff").expect("Cannot find test image!");
//let mut decoder = Decoder::new(img_file).expect("Cannot create decoder");
//assert_eq!(decoder.colortype().unwrap(), ColorType::GrayA(8));
//let img_res = decoder.read_image();
//assert!(img_res.is_ok());
//}
+30 -33
View File
@@ -1,12 +1,12 @@
extern crate tiff;
extern crate tempfile;
extern crate tiff;
use tiff::ColorType;
use tiff::decoder::{Decoder, DecodingResult};
use tiff::encoder::{colortype, TiffEncoder};
use tiff::ColorType;
use std::io::{Seek, SeekFrom};
use std::fs::File;
use std::io::{Seek, SeekFrom};
#[test]
fn encode_decode() {
@@ -23,7 +23,8 @@ fn encode_decode() {
{
let mut tiff = TiffEncoder::new(&mut file).unwrap();
tiff.write_image::<colortype::RGB8>(100, 100, &image_data).unwrap();
tiff.write_image::<colortype::RGB8>(100, 100, &image_data)
.unwrap();
}
{
file.seek(SeekFrom::Start(0)).unwrap();
@@ -32,18 +33,16 @@ fn encode_decode() {
assert_eq!(decoder.dimensions().unwrap(), (100, 100));
if let DecodingResult::U8(img_res) = decoder.read_image().unwrap() {
assert_eq!(image_data, img_res);
}
else {
} else {
panic!("Wrong data type");
}
}
}
#[test]
fn test_gray_u8_roundtrip()
{
let img_file = File::open("./tests/images/minisblack-1c-8b.tiff").expect("Cannot find test image!");
fn test_gray_u8_roundtrip() {
let img_file =
File::open("./tests/images/minisblack-1c-8b.tiff").expect("Cannot find test image!");
let mut decoder = Decoder::new(img_file).expect("Cannot create decoder");
assert_eq!(decoder.colortype().unwrap(), ColorType::Gray(8));
@@ -55,25 +54,24 @@ fn test_gray_u8_roundtrip()
let mut file = tempfile::tempfile().unwrap();
{
let mut tiff = TiffEncoder::new(&mut file).unwrap();
let (width, height) = decoder.dimensions().unwrap();
tiff.write_image::<colortype::Gray8>(width, height, &image_data).unwrap();
tiff.write_image::<colortype::Gray8>(width, height, &image_data)
.unwrap();
}
file.seek(SeekFrom::Start(0)).unwrap();
{
let mut decoder = Decoder::new(&mut file).unwrap();
if let DecodingResult::U8(img_res) = decoder.read_image().unwrap() {
assert_eq!(image_data, img_res);
}
else {
} else {
panic!("Wrong data type");
}
}
}
#[test]
fn test_rgb_u8_roundtrip()
{
fn test_rgb_u8_roundtrip() {
let img_file = File::open("./tests/images/rgb-3c-8b.tiff").expect("Cannot find test image!");
let mut decoder = Decoder::new(img_file).expect("Cannot create decoder");
assert_eq!(decoder.colortype().unwrap(), ColorType::RGB(8));
@@ -86,26 +84,26 @@ fn test_rgb_u8_roundtrip()
let mut file = tempfile::tempfile().unwrap();
{
let mut tiff = TiffEncoder::new(&mut file).unwrap();
let (width, height) = decoder.dimensions().unwrap();
tiff.write_image::<colortype::RGB8>(width, height, &image_data).unwrap();
tiff.write_image::<colortype::RGB8>(width, height, &image_data)
.unwrap();
}
file.seek(SeekFrom::Start(0)).unwrap();
{
let mut decoder = Decoder::new(&mut file).unwrap();
if let DecodingResult::U8(img_res) = decoder.read_image().unwrap() {
assert_eq!(image_data, img_res);
}
else {
} else {
panic!("Wrong data type");
}
}
}
#[test]
fn test_gray_u16_roundtrip()
{
let img_file = File::open("./tests/images/minisblack-1c-16b.tiff").expect("Cannot find test image!");
fn test_gray_u16_roundtrip() {
let img_file =
File::open("./tests/images/minisblack-1c-16b.tiff").expect("Cannot find test image!");
let mut decoder = Decoder::new(img_file).expect("Cannot create decoder");
assert_eq!(decoder.colortype().unwrap(), ColorType::Gray(16));
@@ -117,25 +115,24 @@ fn test_gray_u16_roundtrip()
let mut file = tempfile::tempfile().unwrap();
{
let mut tiff = TiffEncoder::new(&mut file).unwrap();
let (width, height) = decoder.dimensions().unwrap();
tiff.write_image::<colortype::Gray16>(width, height, &image_data).unwrap();
tiff.write_image::<colortype::Gray16>(width, height, &image_data)
.unwrap();
}
file.seek(SeekFrom::Start(0)).unwrap();
{
let mut decoder = Decoder::new(&mut file).unwrap();
if let DecodingResult::U16(img_res) = decoder.read_image().unwrap() {
assert_eq!(image_data, img_res);
}
else {
} else {
panic!("Wrong data type");
}
}
}
#[test]
fn test_rgb_u16_roundtrip()
{
fn test_rgb_u16_roundtrip() {
let img_file = File::open("./tests/images/rgb-3c-16b.tiff").expect("Cannot find test image!");
let mut decoder = Decoder::new(img_file).expect("Cannot create decoder");
assert_eq!(decoder.colortype().unwrap(), ColorType::RGB(16));
@@ -148,17 +145,17 @@ fn test_rgb_u16_roundtrip()
let mut file = tempfile::tempfile().unwrap();
{
let mut tiff = TiffEncoder::new(&mut file).unwrap();
let (width, height) = decoder.dimensions().unwrap();
tiff.write_image::<colortype::RGB16>(width, height, &image_data).unwrap();
tiff.write_image::<colortype::RGB16>(width, height, &image_data)
.unwrap();
}
file.seek(SeekFrom::Start(0)).unwrap();
{
let mut decoder = Decoder::new(&mut file).unwrap();
if let DecodingResult::U16(img_res) = decoder.read_image().unwrap() {
assert_eq!(image_data, img_res);
}
else {
} else {
panic!("Wrong data type");
}
}
+1 -1
View File
@@ -1,7 +1,7 @@
extern crate tiff;
use tiff::TiffResult;
use tiff::decoder::Decoder;
use tiff::TiffResult;
use std::fs::File;