1 use num_traits::{FromPrimitive, Num};
2 use std::collections::HashMap;
3 use std::io::{self, Read, Seek};
4 use std::cmp;
5
6 use {ColorType, TiffError, TiffFormatError, TiffResult, TiffUnsupportedError};
7
8 use self::ifd::Directory;
9
10 use self::stream::{ByteOrder, EndianReader, LZWReader, PackBitsReader, SmartReader};
11
12 pub mod ifd;
13 mod stream;
14
15 /// Result of a decoding process
16 #[derive(Debug)]
17 pub enum DecodingResult {
18 /// A vector of unsigned bytes
19 U8(Vec<u8>),
20 /// A vector of unsigned words
21 U16(Vec<u16>),
22 }
23
24 impl DecodingResult {
new_u8(size: usize, limits: &Limits) -> TiffResult<DecodingResult>25 fn new_u8(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
26 if size > limits.decoding_buffer_size {
27 Err(TiffError::LimitsExceeded)
28 } else {
29 Ok(DecodingResult::U8(vec![0; size]))
30 }
31 }
32
new_u16(size: usize, limits: &Limits) -> TiffResult<DecodingResult>33 fn new_u16(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
34 if size > limits.decoding_buffer_size / 2 {
35 Err(TiffError::LimitsExceeded)
36 } else {
37 Ok(DecodingResult::U16(vec![0; size]))
38 }
39 }
40
as_buffer(&mut self, start: usize) -> DecodingBuffer41 pub fn as_buffer(&mut self, start: usize) -> DecodingBuffer {
42 match *self {
43 DecodingResult::U8(ref mut buf) => DecodingBuffer::U8(&mut buf[start..]),
44 DecodingResult::U16(ref mut buf) => DecodingBuffer::U16(&mut buf[start..]),
45 }
46 }
47 }
48
49 // A buffer for image decoding
50 pub enum DecodingBuffer<'a> {
51 /// A slice of unsigned bytes
52 U8(&'a mut [u8]),
53 /// A slice of unsigned words
54 U16(&'a mut [u16]),
55 }
56
57 impl<'a> DecodingBuffer<'a> {
len(&self) -> usize58 fn len(&self) -> usize {
59 match *self {
60 DecodingBuffer::U8(ref buf) => buf.len(),
61 DecodingBuffer::U16(ref buf) => buf.len(),
62 }
63 }
64
byte_len(&self) -> usize65 fn byte_len(&self) -> usize {
66 match *self {
67 DecodingBuffer::U8(_) => 1,
68 DecodingBuffer::U16(_) => 2,
69 }
70 }
71
copy<'b>(&'b mut self) -> DecodingBuffer<'b> where 'a: 'b,72 fn copy<'b>(&'b mut self) -> DecodingBuffer<'b>
73 where
74 'a: 'b,
75 {
76 match *self {
77 DecodingBuffer::U8(ref mut buf) => DecodingBuffer::U8(buf),
78 DecodingBuffer::U16(ref mut buf) => DecodingBuffer::U16(buf),
79 }
80 }
81 }
82
83 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, FromPrimitive)]
84 pub enum PhotometricInterpretation {
85 WhiteIsZero = 0,
86 BlackIsZero = 1,
87 RGB = 2,
88 RGBPalette = 3,
89 TransparencyMask = 4,
90 CMYK = 5,
91 YCbCr = 6,
92 CIELab = 8,
93 }
94
95 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, FromPrimitive)]
96 pub enum CompressionMethod {
97 None = 1,
98 Huffman = 2,
99 Fax3 = 3,
100 Fax4 = 4,
101 LZW = 5,
102 JPEG = 6,
103 PackBits = 0x8005,
104 }
105
106 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, FromPrimitive)]
107 pub enum PlanarConfiguration {
108 Chunky = 1,
109 Planar = 2,
110 }
111
112 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, FromPrimitive)]
113 enum Predictor {
114 None = 1,
115 Horizontal = 2,
116 }
117
118 #[derive(Debug)]
119 struct StripDecodeState {
120 strip_index: usize,
121 strip_offsets: Vec<u32>,
122 strip_bytes: Vec<u32>,
123 }
124
125 /// Decoding limits
126 #[derive(Clone, Debug)]
127 pub struct Limits {
128 /// The maximum size of any `DecodingResult` in bytes, the default is
129 /// 256MiB. If the entire image is decoded at once, then this will
130 /// be the maximum size of the image. If it is decoded one strip at a
131 /// time, this will be the maximum size of a strip.
132 decoding_buffer_size: usize,
133 /// The maximum size of any ifd value in bytes, the default is
134 /// 1MiB.
135 ifd_value_size: usize,
136 }
137
138 impl Default for Limits {
default() -> Limits139 fn default() -> Limits {
140 Limits {
141 decoding_buffer_size: 256 * 1024 * 1024,
142 ifd_value_size: 1024 * 1024,
143 }
144 }
145 }
146
147 /// The representation of a TIFF decoder
148 ///
149 /// Currently does not support decoding of interlaced images
150 #[derive(Debug)]
151 pub struct Decoder<R>
152 where
153 R: Read + Seek,
154 {
155 reader: SmartReader<R>,
156 byte_order: ByteOrder,
157 limits: Limits,
158 next_ifd: Option<u32>,
159 ifd: Option<Directory>,
160 width: u32,
161 height: u32,
162 bits_per_sample: Vec<u8>,
163 samples: u8,
164 photometric_interpretation: PhotometricInterpretation,
165 compression_method: CompressionMethod,
166 strip_decoder: Option<StripDecodeState>,
167 }
168
169 trait Wrapping {
wrapping_add(&self, other: Self) -> Self170 fn wrapping_add(&self, other: Self) -> Self;
171 }
172
173 impl Wrapping for u8 {
wrapping_add(&self, other: Self) -> Self174 fn wrapping_add(&self, other: Self) -> Self {
175 u8::wrapping_add(*self, other)
176 }
177 }
178
179 impl Wrapping for u16 {
wrapping_add(&self, other: Self) -> Self180 fn wrapping_add(&self, other: Self) -> Self {
181 u16::wrapping_add(*self, other)
182 }
183 }
184
rev_hpredict_nsamp<T>(image: &mut [T], size: (u32, u32), samples: usize) where T: Num + Copy + Wrapping,185 fn rev_hpredict_nsamp<T>(image: &mut [T], size: (u32, u32), samples: usize)
186 where
187 T: Num + Copy + Wrapping,
188 {
189 let width = size.0 as usize;
190 let height = size.1 as usize;
191 for row in 0..height {
192 for col in samples..width * samples {
193 let prev_pixel = image[(row * width * samples + col - samples)];
194 let pixel = &mut image[(row * width * samples + col)];
195 *pixel = pixel.wrapping_add(prev_pixel);
196 }
197 }
198 }
199
rev_hpredict(image: DecodingBuffer, size: (u32, u32), color_type: ColorType) -> TiffResult<()>200 fn rev_hpredict(image: DecodingBuffer, size: (u32, u32), color_type: ColorType) -> TiffResult<()> {
201 let samples = match color_type {
202 ColorType::Gray(8) | ColorType::Gray(16) => 1,
203 ColorType::RGB(8) | ColorType::RGB(16) => 3,
204 ColorType::RGBA(8) | ColorType::RGBA(16) | ColorType::CMYK(8) => 4,
205 _ => {
206 return Err(TiffError::UnsupportedError(
207 TiffUnsupportedError::HorizontalPredictor(color_type),
208 ))
209 }
210 };
211 match image {
212 DecodingBuffer::U8(buf) => {
213 rev_hpredict_nsamp(buf, size, samples);
214 }
215 DecodingBuffer::U16(buf) => {
216 rev_hpredict_nsamp(buf, size, samples);
217 }
218 }
219 Ok(())
220 }
221
222 impl<R: Read + Seek> Decoder<R> {
223 /// Create a new decoder that decodes from the stream ```r```
new(r: R) -> TiffResult<Decoder<R>>224 pub fn new(r: R) -> TiffResult<Decoder<R>> {
225 Decoder {
226 reader: SmartReader::wrap(r, ByteOrder::LittleEndian),
227 byte_order: ByteOrder::LittleEndian,
228 limits: Default::default(),
229 next_ifd: None,
230 ifd: None,
231 width: 0,
232 height: 0,
233 bits_per_sample: vec![1],
234 samples: 1,
235 photometric_interpretation: PhotometricInterpretation::BlackIsZero,
236 compression_method: CompressionMethod::None,
237 strip_decoder: None,
238 }
239 .init()
240 }
241
with_limits(mut self, limits: Limits) -> Decoder<R>242 pub fn with_limits(mut self, limits: Limits) -> Decoder<R> {
243 self.limits = limits;
244 self
245 }
246
dimensions(&mut self) -> TiffResult<(u32, u32)>247 pub fn dimensions(&mut self) -> TiffResult<(u32, u32)> {
248 Ok((self.width, self.height))
249 }
250
colortype(&mut self) -> TiffResult<ColorType>251 pub fn colortype(&mut self) -> TiffResult<ColorType> {
252 match self.photometric_interpretation {
253 // TODO: catch also [ 8, 8, 8, _] this does not work due to a bug in rust atm
254 PhotometricInterpretation::RGB if self.bits_per_sample == [8, 8, 8, 8] => {
255 Ok(ColorType::RGBA(8))
256 }
257 PhotometricInterpretation::RGB if self.bits_per_sample == [8, 8, 8] => {
258 Ok(ColorType::RGB(8))
259 }
260 PhotometricInterpretation::RGB if self.bits_per_sample == [16, 16, 16, 16] => {
261 Ok(ColorType::RGBA(16))
262 }
263 PhotometricInterpretation::RGB if self.bits_per_sample == [16, 16, 16] => {
264 Ok(ColorType::RGB(16))
265 }
266 PhotometricInterpretation::CMYK if self.bits_per_sample == [8, 8, 8, 8] => {
267 Ok(ColorType::CMYK(8))
268 }
269 PhotometricInterpretation::BlackIsZero | PhotometricInterpretation::WhiteIsZero
270 if self.bits_per_sample.len() == 1 =>
271 {
272 Ok(ColorType::Gray(self.bits_per_sample[0]))
273 }
274
275 // TODO: this is bad we should not fail at this point
276 _ => Err(TiffError::UnsupportedError(
277 TiffUnsupportedError::InterpretationWithBits(
278 self.photometric_interpretation,
279 self.bits_per_sample.clone(),
280 ),
281 )),
282 }
283 }
284
read_header(&mut self) -> TiffResult<()>285 fn read_header(&mut self) -> TiffResult<()> {
286 let mut endianess = Vec::with_capacity(2);
287 try!(self.reader.by_ref().take(2).read_to_end(&mut endianess));
288 match &*endianess {
289 b"II" => {
290 self.byte_order = ByteOrder::LittleEndian;
291 self.reader.byte_order = ByteOrder::LittleEndian;
292 }
293 b"MM" => {
294 self.byte_order = ByteOrder::BigEndian;
295 self.reader.byte_order = ByteOrder::BigEndian;
296 }
297 _ => {
298 return Err(TiffError::FormatError(
299 TiffFormatError::TiffSignatureNotFound,
300 ))
301 }
302 }
303 if try!(self.read_short()) != 42 {
304 return Err(TiffError::FormatError(
305 TiffFormatError::TiffSignatureInvalid,
306 ));
307 }
308 self.next_ifd = match try!(self.read_long()) {
309 0 => None,
310 n => Some(n),
311 };
312 Ok(())
313 }
314
315 /// Initializes the decoder.
init(mut self) -> TiffResult<Decoder<R>>316 pub fn init(mut self) -> TiffResult<Decoder<R>> {
317 try!(self.read_header());
318 self.next_image()?;
319 Ok(self)
320 }
321
322 /// Reads in the next image.
323 /// If there is no further image in the TIFF file a format error is returned.
324 /// To determine whether there are more images call `TIFFDecoder::more_images` instead.
next_image(&mut self) -> TiffResult<()>325 pub fn next_image(&mut self) -> TiffResult<()> {
326 self.ifd = Some(try!(self.read_ifd()));
327 self.width = try!(self.get_tag_u32(ifd::Tag::ImageWidth));
328 self.height = try!(self.get_tag_u32(ifd::Tag::ImageLength));
329 self.strip_decoder = None;
330 self.photometric_interpretation = match FromPrimitive::from_u32(try!(
331 self.get_tag_u32(ifd::Tag::PhotometricInterpretation)
332 )) {
333 Some(val) => val,
334 None => {
335 return Err(TiffError::UnsupportedError(
336 TiffUnsupportedError::UnknownInterpretation,
337 ))
338 }
339 };
340 if let Some(val) = try!(self.find_tag_u32(ifd::Tag::Compression)) {
341 match FromPrimitive::from_u32(val) {
342 Some(method) => self.compression_method = method,
343 None => {
344 return Err(TiffError::UnsupportedError(
345 TiffUnsupportedError::UnknownCompressionMethod,
346 ))
347 }
348 }
349 }
350 if let Some(val) = try!(self.find_tag_u32(ifd::Tag::SamplesPerPixel)) {
351 self.samples = val as u8
352 }
353 match self.samples {
354 1 => {
355 if let Some(val) = try!(self.find_tag_u32(ifd::Tag::BitsPerSample)) {
356 self.bits_per_sample = vec![val as u8]
357 }
358 }
359 3 | 4 => {
360 if let Some(val) = try!(self.find_tag_u32_vec(ifd::Tag::BitsPerSample)) {
361 self.bits_per_sample = val.iter().map(|&v| v as u8).collect()
362 }
363 }
364 _ => {
365 return Err(TiffError::UnsupportedError(
366 TiffUnsupportedError::UnsupportedSampleDepth(self.samples),
367 ))
368 }
369 }
370 Ok(())
371 }
372
373 /// Returns `true` if there is at least one more image available.
more_images(&self) -> bool374 pub fn more_images(&self) -> bool {
375 self.next_ifd.is_some()
376 }
377
378 /// Returns the byte_order
byte_order(&self) -> ByteOrder379 pub fn byte_order(&self) -> ByteOrder {
380 self.byte_order
381 }
382
383 /// Reads a TIFF short value
384 #[inline]
read_short(&mut self) -> Result<u16, io::Error>385 pub fn read_short(&mut self) -> Result<u16, io::Error> {
386 self.reader.read_u16()
387 }
388
389 /// Reads a TIFF long value
390 #[inline]
read_long(&mut self) -> Result<u32, io::Error>391 pub fn read_long(&mut self) -> Result<u32, io::Error> {
392 self.reader.read_u32()
393 }
394
395 /// Reads a string
396 #[inline]
read_string(&mut self, length: usize) -> TiffResult<String>397 pub fn read_string(&mut self, length: usize) -> TiffResult<String> {
398 let mut out = String::with_capacity(length);
399 self.reader.read_to_string(&mut out)?;
400 // Strings may be null-terminated, so we trim anything downstream of the null byte
401 let trimmed = out.bytes().take_while(|&n| n != 0).collect::<Vec<u8>>();
402 Ok(String::from_utf8(trimmed)?)
403 }
404
405 /// Reads a TIFF IFA offset/value field
406 #[inline]
read_offset(&mut self) -> Result<[u8; 4], io::Error>407 pub fn read_offset(&mut self) -> Result<[u8; 4], io::Error> {
408 let mut val = [0; 4];
409 try!(self.reader.read_exact(&mut val));
410 Ok(val)
411 }
412
413 /// Moves the cursor to the specified offset
414 #[inline]
goto_offset(&mut self, offset: u32) -> io::Result<()>415 pub fn goto_offset(&mut self, offset: u32) -> io::Result<()> {
416 self.reader
417 .seek(io::SeekFrom::Start(u64::from(offset)))
418 .map(|_| ())
419 }
420
421 /// Reads a IFD entry.
422 // An IFD entry has four fields:
423 //
424 // Tag 2 bytes
425 // Type 2 bytes
426 // Count 4 bytes
427 // Value 4 bytes either a pointer the value itself
read_entry(&mut self) -> TiffResult<Option<(ifd::Tag, ifd::Entry)>>428 fn read_entry(&mut self) -> TiffResult<Option<(ifd::Tag, ifd::Entry)>> {
429 let tag = ifd::Tag::from_u16(try!(self.read_short()));
430 let type_: ifd::Type = match FromPrimitive::from_u16(try!(self.read_short())) {
431 Some(t) => t,
432 None => {
433 // Unknown type. Skip this entry according to spec.
434 try!(self.read_long());
435 try!(self.read_long());
436 return Ok(None);
437 }
438 };
439 Ok(Some((
440 tag,
441 ifd::Entry::new(
442 type_,
443 try!(self.read_long()), // count
444 try!(self.read_offset()), // offset
445 ),
446 )))
447 }
448
449 /// Reads the next IFD
read_ifd(&mut self) -> TiffResult<Directory>450 fn read_ifd(&mut self) -> TiffResult<Directory> {
451 let mut dir: Directory = HashMap::new();
452 match self.next_ifd {
453 None => {
454 return Err(TiffError::FormatError(
455 TiffFormatError::ImageFileDirectoryNotFound,
456 ))
457 }
458 Some(offset) => try!(self.goto_offset(offset)),
459 }
460 for _ in 0..try!(self.read_short()) {
461 let (tag, entry) = match try!(self.read_entry()) {
462 Some(val) => val,
463 None => continue, // Unknown data type in tag, skip
464 };
465 dir.insert(tag, entry);
466 }
467 self.next_ifd = match try!(self.read_long()) {
468 0 => None,
469 n => Some(n),
470 };
471 Ok(dir)
472 }
473
474 /// Tries to retrieve a tag.
475 /// Return `Ok(None)` if the tag is not present.
find_tag(&mut self, tag: ifd::Tag) -> TiffResult<Option<ifd::Value>>476 pub fn find_tag(&mut self, tag: ifd::Tag) -> TiffResult<Option<ifd::Value>> {
477 let entry = match self.ifd.as_ref().unwrap().get(&tag) {
478 None => return Ok(None),
479 Some(entry) => entry.clone(),
480 };
481
482 let limits = self.limits.clone();
483
484 Ok(Some(try!(entry.val(&limits, self))))
485 }
486
487 /// Tries to retrieve a tag and convert it to the desired type.
find_tag_u32(&mut self, tag: ifd::Tag) -> TiffResult<Option<u32>>488 pub fn find_tag_u32(&mut self, tag: ifd::Tag) -> TiffResult<Option<u32>> {
489 match self.find_tag(tag)? {
490 Some(val) => val.into_u32().map(Some),
491 None => Ok(None),
492 }
493 }
494
495 /// Tries to retrieve a tag and convert it to the desired type.
find_tag_u32_vec(&mut self, tag: ifd::Tag) -> TiffResult<Option<Vec<u32>>>496 pub fn find_tag_u32_vec(&mut self, tag: ifd::Tag) -> TiffResult<Option<Vec<u32>>> {
497 match self.find_tag(tag)? {
498 Some(val) => val.into_u32_vec().map(Some),
499 None => Ok(None),
500 }
501 }
502
503 /// Tries to retrieve a tag.
504 /// Returns an error if the tag is not present
get_tag(&mut self, tag: ifd::Tag) -> TiffResult<ifd::Value>505 pub fn get_tag(&mut self, tag: ifd::Tag) -> TiffResult<ifd::Value> {
506 match try!(self.find_tag(tag)) {
507 Some(val) => Ok(val),
508 None => Err(TiffError::FormatError(
509 TiffFormatError::RequiredTagNotFound(tag),
510 )),
511 }
512 }
513
514 /// Tries to retrieve a tag and convert it to the desired type.
get_tag_u32(&mut self, tag: ifd::Tag) -> TiffResult<u32>515 pub fn get_tag_u32(&mut self, tag: ifd::Tag) -> TiffResult<u32> {
516 self.get_tag(tag)?.into_u32()
517 }
518
519 /// Tries to retrieve a tag and convert it to the desired type.
get_tag_u32_vec(&mut self, tag: ifd::Tag) -> TiffResult<Vec<u32>>520 pub fn get_tag_u32_vec(&mut self, tag: ifd::Tag) -> TiffResult<Vec<u32>> {
521 self.get_tag(tag)?.into_u32_vec()
522 }
523
524 /// Decompresses the strip into the supplied buffer.
525 /// Returns the number of bytes read.
expand_strip<'a>( &mut self, buffer: DecodingBuffer<'a>, offset: u32, length: u32, max_uncompressed_length: usize, ) -> TiffResult<usize>526 fn expand_strip<'a>(
527 &mut self,
528 buffer: DecodingBuffer<'a>,
529 offset: u32,
530 length: u32,
531 max_uncompressed_length: usize,
532 ) -> TiffResult<usize> {
533 let color_type = try!(self.colortype());
534 try!(self.goto_offset(offset));
535 let (bytes, mut reader): (usize, Box<EndianReader>) = match self.compression_method {
536 CompressionMethod::None => {
537 let order = self.reader.byte_order;
538 (
539 length as usize,
540 Box::new(SmartReader::wrap(&mut self.reader, order)),
541 )
542 }
543 CompressionMethod::LZW => {
544 let (bytes, reader) = try!(LZWReader::new(
545 &mut self.reader,
546 length as usize,
547 max_uncompressed_length
548 ));
549 (bytes, Box::new(reader))
550 }
551 CompressionMethod::PackBits => {
552 let order = self.reader.byte_order;
553 let (bytes, reader) = try!(PackBitsReader::new(
554 &mut self.reader,
555 order,
556 length as usize
557 ));
558 (bytes, Box::new(reader))
559 }
560 method => {
561 return Err(TiffError::UnsupportedError(
562 TiffUnsupportedError::UnsupportedCompressionMethod(method),
563 ))
564 }
565 };
566
567 if bytes / buffer.byte_len() > max_uncompressed_length {
568 return Err(TiffError::FormatError(
569 TiffFormatError::InconsistentSizesEncountered,
570 ));
571 }
572
573 Ok(match (color_type, buffer) {
574 (ColorType::RGB(8), DecodingBuffer::U8(ref mut buffer))
575 | (ColorType::RGBA(8), DecodingBuffer::U8(ref mut buffer))
576 | (ColorType::CMYK(8), DecodingBuffer::U8(ref mut buffer)) => {
577 try!(reader.read_exact(&mut buffer[..bytes]));
578 bytes
579 }
580 (ColorType::RGBA(16), DecodingBuffer::U16(ref mut buffer))
581 | (ColorType::RGB(16), DecodingBuffer::U16(ref mut buffer)) => {
582 try!(reader.read_u16_into(&mut buffer[..bytes / 2]));
583 bytes / 2
584 }
585 (ColorType::Gray(16), DecodingBuffer::U16(ref mut buffer)) => {
586 try!(reader.read_u16_into(&mut buffer[..bytes / 2]));
587 if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero {
588 for datum in buffer[..bytes / 2].iter_mut() {
589 *datum = 0xffff - *datum
590 }
591 }
592 bytes / 2
593 }
594 (ColorType::Gray(n), DecodingBuffer::U8(ref mut buffer)) if n <= 8 => {
595 try!(reader.read_exact(&mut buffer[..bytes]));
596 if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero {
597 for byte in buffer[..bytes].iter_mut() {
598 *byte = 0xff - *byte
599 }
600 }
601 bytes
602 }
603 (type_, _) => {
604 return Err(TiffError::UnsupportedError(
605 TiffUnsupportedError::UnsupportedColorType(type_),
606 ))
607 }
608 })
609 }
610
611 /// Number of strips in image
strip_count(&mut self) -> TiffResult<u32>612 pub fn strip_count(&mut self) -> TiffResult<u32> {
613 let rows_per_strip = self
614 .get_tag_u32(ifd::Tag::RowsPerStrip)
615 .unwrap_or(self.height);
616
617 if rows_per_strip == 0 {
618 return Ok(0);
619 }
620
621 Ok((self.height + rows_per_strip - 1) / rows_per_strip)
622 }
623
initialize_strip_decoder(&mut self) -> TiffResult<()>624 fn initialize_strip_decoder(&mut self) -> TiffResult<()> {
625 if self.strip_decoder.is_none() {
626 let strip_offsets = self.get_tag_u32_vec(ifd::Tag::StripOffsets)?;
627 let strip_bytes = self.get_tag_u32_vec(ifd::Tag::StripByteCounts)?;
628
629 self.strip_decoder = Some(StripDecodeState {
630 strip_index: 0,
631 strip_offsets,
632 strip_bytes,
633 });
634 }
635 Ok(())
636 }
637
read_strip_to_buffer(&mut self, mut buffer: DecodingBuffer) -> TiffResult<()>638 pub fn read_strip_to_buffer(&mut self, mut buffer: DecodingBuffer) -> TiffResult<()> {
639 self.initialize_strip_decoder()?;
640
641 let index = self.strip_decoder.as_ref().unwrap().strip_index;
642 let offset = *self
643 .strip_decoder
644 .as_ref()
645 .unwrap()
646 .strip_offsets
647 .get(index)
648 .ok_or(TiffError::FormatError(
649 TiffFormatError::InconsistentSizesEncountered,
650 ))?;
651 let byte_count = *self
652 .strip_decoder
653 .as_ref()
654 .unwrap()
655 .strip_bytes
656 .get(index)
657 .ok_or(TiffError::FormatError(
658 TiffFormatError::InconsistentSizesEncountered,
659 ))?;
660
661 let rows_per_strip = self
662 .get_tag_u32(ifd::Tag::RowsPerStrip)
663 .unwrap_or(self.height) as usize;
664
665 let strip_height = cmp::min(
666 rows_per_strip,
667 self.height as usize - index * rows_per_strip,
668 );
669
670 let buffer_size = self.width as usize * strip_height * self.bits_per_sample.len();
671
672 if buffer.len() < buffer_size || byte_count as usize / buffer.byte_len() > buffer_size {
673 return Err(TiffError::FormatError(
674 TiffFormatError::InconsistentSizesEncountered,
675 ));
676 }
677
678 let units_read = self.expand_strip(buffer.copy(), offset, byte_count, buffer_size)?;
679
680 self.strip_decoder.as_mut().unwrap().strip_index += 1;
681
682 if index as u32 == self.strip_count()? {
683 self.strip_decoder = None;
684 }
685
686 if units_read < buffer_size {
687 return Err(TiffError::FormatError(
688 TiffFormatError::InconsistentSizesEncountered,
689 ));
690 }
691 if let Ok(predictor) = self.get_tag_u32(ifd::Tag::Predictor) {
692 match FromPrimitive::from_u32(predictor) {
693 Some(Predictor::None) => (),
694 Some(Predictor::Horizontal) => {
695 rev_hpredict(
696 buffer.copy(),
697 (self.width, strip_height as u32),
698 self.colortype()?,
699 )?;
700 }
701 None => {
702 return Err(TiffError::FormatError(TiffFormatError::UnknownPredictor(
703 predictor,
704 )))
705 }
706 }
707 }
708 Ok(())
709 }
710
711 /// Read a single strip from the image and return it as a Vector
read_strip(&mut self) -> TiffResult<DecodingResult>712 pub fn read_strip(&mut self) -> TiffResult<DecodingResult> {
713 self.initialize_strip_decoder()?;
714 let index = self.strip_decoder.as_ref().unwrap().strip_index;
715
716 let rows_per_strip = self
717 .get_tag_u32(ifd::Tag::RowsPerStrip)
718 .unwrap_or(self.height) as usize;
719
720 let strip_height = cmp::min(
721 rows_per_strip,
722 self.height as usize - index * rows_per_strip,
723 );
724
725 let buffer_size = self.width as usize * strip_height * self.bits_per_sample.iter().count();
726
727 let mut result = match self.bits_per_sample.iter().cloned().max().unwrap_or(8) {
728 n if n <= 8 => DecodingResult::new_u8(buffer_size, &self.limits)?,
729 n if n <= 16 => DecodingResult::new_u16(buffer_size, &self.limits)?,
730 n => {
731 return Err(TiffError::UnsupportedError(
732 TiffUnsupportedError::UnsupportedBitsPerChannel(n),
733 ))
734 }
735 };
736
737 self.read_strip_to_buffer(result.as_buffer(0))?;
738
739 Ok(result)
740 }
741
742 /// Decodes the entire image and return it as a Vector
read_image(&mut self) -> TiffResult<DecodingResult>743 pub fn read_image(&mut self) -> TiffResult<DecodingResult> {
744 self.initialize_strip_decoder()?;
745 let rows_per_strip = self
746 .get_tag_u32(ifd::Tag::RowsPerStrip)
747 .unwrap_or(self.height) as usize;
748
749 let samples_per_strip =
750 self.width as usize * rows_per_strip * self.bits_per_sample.iter().count();
751
752 let buffer_size =
753 self.width as usize * self.height as usize * self.bits_per_sample.iter().count();
754
755 let mut result = match self.bits_per_sample.iter().cloned().max().unwrap_or(8) {
756 n if n <= 8 => DecodingResult::new_u8(buffer_size, &self.limits)?,
757 n if n <= 16 => DecodingResult::new_u16(buffer_size, &self.limits)?,
758 n => {
759 return Err(TiffError::UnsupportedError(
760 TiffUnsupportedError::UnsupportedBitsPerChannel(n),
761 ))
762 }
763 };
764
765 for i in 0..self.strip_count()? as usize {
766 self.read_strip_to_buffer(result.as_buffer(samples_per_strip * i))?;
767 }
768
769 Ok(result)
770 }
771 }
772