1 #![allow(clippy::too_many_arguments)]
2 use std::convert::TryFrom;
3 use std::ffi::OsStr;
4 use std::io;
5 use std::io::Read;
6 use std::ops::{Deref, DerefMut};
7 use std::path::Path;
8 use std::usize;
9 
10 use crate::ImageBuffer;
11 use crate::color::{ColorType, ExtendedColorType};
12 use crate::error::{ImageError, ImageFormatHint, ImageResult, LimitError, LimitErrorKind, ParameterError, ParameterErrorKind};
13 use crate::math::Rect;
14 use crate::traits::Pixel;
15 
16 use crate::animation::Frames;
17 
18 #[cfg(feature = "pnm")]
19 use crate::pnm::PNMSubtype;
20 
21 /// An enumeration of supported image formats.
22 /// Not all formats support both encoding and decoding.
23 #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
24 pub enum ImageFormat {
25     /// An Image in PNG Format
26     Png,
27 
28     /// An Image in JPEG Format
29     Jpeg,
30 
31     /// An Image in GIF Format
32     Gif,
33 
34     /// An Image in WEBP Format
35     WebP,
36 
37     /// An Image in general PNM Format
38     Pnm,
39 
40     /// An Image in TIFF Format
41     Tiff,
42 
43     /// An Image in TGA Format
44     Tga,
45 
46     /// An Image in DDS Format
47     Dds,
48 
49     /// An Image in BMP Format
50     Bmp,
51 
52     /// An Image in ICO Format
53     Ico,
54 
55     /// An Image in Radiance HDR Format
56     Hdr,
57 
58     /// An Image in farbfeld Format
59     Farbfeld,
60 
61     /// An Image in AVIF format.
62     Avif,
63 
64     #[doc(hidden)]
65     __NonExhaustive(crate::utils::NonExhaustiveMarker),
66 }
67 
68 impl ImageFormat {
69     /// Return the image format specified by a path's file extension.
70     ///
71     /// # Example
72     ///
73     /// ```
74     /// use image::ImageFormat;
75     ///
76     /// let format = ImageFormat::from_extension("jpg");
77     /// assert_eq!(format, Some(ImageFormat::Jpeg));
78     /// ```
79     #[inline]
from_extension<S>(ext: S) -> Option<Self> where S: AsRef<OsStr>80     pub fn from_extension<S>(ext: S) -> Option<Self> where S: AsRef<OsStr> {
81         // thin wrapper function to strip generics
82         fn inner(ext: &OsStr) -> Option<ImageFormat> {
83             let ext = ext.to_str()?.to_ascii_lowercase();
84 
85             Some(match ext.as_str() {
86                 "avif" => ImageFormat::Avif,
87                 "jpg" | "jpeg" => ImageFormat::Jpeg,
88                 "png" => ImageFormat::Png,
89                 "gif" => ImageFormat::Gif,
90                 "webp" => ImageFormat::WebP,
91                 "tif" | "tiff" => ImageFormat::Tiff,
92                 "tga" => ImageFormat::Tga,
93                 "dds" => ImageFormat::Dds,
94                 "bmp" => ImageFormat::Bmp,
95                 "ico" => ImageFormat::Ico,
96                 "hdr" => ImageFormat::Hdr,
97                 "pbm" | "pam" | "ppm" | "pgm" => ImageFormat::Pnm,
98                 "ff" | "farbfeld" => ImageFormat::Farbfeld,
99                 _ => return None,
100             })
101         }
102 
103         inner(ext.as_ref())
104     }
105 
106     /// Return the image format specified by the path's file extension.
107     ///
108     /// # Example
109     ///
110     /// ```
111     /// use image::ImageFormat;
112     ///
113     /// let format = ImageFormat::from_path("images/ferris.png")?;
114     /// assert_eq!(format, ImageFormat::Png);
115     ///
116     /// # Ok::<(), image::error::ImageError>(())
117     /// ```
118     #[inline]
from_path<P>(path: P) -> ImageResult<Self> where P : AsRef<Path>119     pub fn from_path<P>(path: P) -> ImageResult<Self> where P : AsRef<Path> {
120         // thin wrapper function to strip generics
121         fn inner(path: &Path) -> ImageResult<ImageFormat> {
122             let exact_ext = path.extension();
123             exact_ext
124                 .and_then(ImageFormat::from_extension)
125                 .ok_or_else(|| {
126                     let format_hint = match exact_ext {
127                         None => ImageFormatHint::Unknown,
128                         Some(os) => ImageFormatHint::PathExtension(os.into()),
129                     };
130                     ImageError::Unsupported(format_hint.into())
131                 })
132         }
133 
134         inner(path.as_ref())
135     }
136 
137     /// Return if the ImageFormat can be decoded by the lib.
138     #[inline]
can_read(&self) -> bool139     pub fn can_read(&self) -> bool {
140         // Needs to be updated once a new variant's decoder is added to free_functions.rs::load
141         match self {
142             ImageFormat::Png => true,
143             ImageFormat::Gif => true,
144             ImageFormat::Jpeg => true,
145             ImageFormat::WebP => true,
146             ImageFormat::Tiff => true,
147             ImageFormat::Tga => true,
148             ImageFormat::Dds => false,
149             ImageFormat::Bmp => true,
150             ImageFormat::Ico => true,
151             ImageFormat::Hdr => true,
152             ImageFormat::Pnm => true,
153             ImageFormat::Farbfeld => true,
154             ImageFormat::Avif => true,
155             ImageFormat::__NonExhaustive(marker) => match marker._private {},
156         }
157     }
158 
159     /// Return if the ImageFormat can be encoded by the lib.
160     #[inline]
can_write(&self) -> bool161     pub fn can_write(&self) -> bool {
162         // Needs to be updated once a new variant's encoder is added to free_functions.rs::save_buffer_with_format_impl
163         match self {
164             ImageFormat::Gif => true,
165             ImageFormat::Ico => true,
166             ImageFormat::Jpeg => true,
167             ImageFormat::Png => true,
168             ImageFormat::Bmp => true,
169             ImageFormat::Tiff => true,
170             ImageFormat::Tga => true,
171             ImageFormat::Pnm => true,
172             ImageFormat::Farbfeld => true,
173             ImageFormat::Avif => true,
174             ImageFormat::WebP => false,
175             ImageFormat::Hdr => false,
176             ImageFormat::Dds => false,
177             ImageFormat::__NonExhaustive(marker) => match marker._private {},
178         }
179     }
180 
181     /// Return a list of applicable extensions for this format.
182     ///
183     /// All currently recognized image formats specify at least on extension but for future
184     /// compatibility you should not rely on this fact. The list may be empty if the format has no
185     /// recognized file representation, for example in case it is used as a purely transient memory
186     /// format.
187     ///
188     /// The method name `extensions` remains reserved for introducing another method in the future
189     /// that yields a slice of `OsStr` which is blocked by several features of const evaluation.
extensions_str(self) -> &'static [&'static str]190     pub fn extensions_str(self) -> &'static [&'static str] {
191         match self {
192             ImageFormat::Png => &["png"],
193             ImageFormat::Jpeg => &["jpg", "jpeg"],
194             ImageFormat::Gif => &["gif"],
195             ImageFormat::WebP => &["webp"],
196             ImageFormat::Pnm => &["pbm", "pam", "ppm", "pgm"],
197             ImageFormat::Tiff => &["tiff", "tif"],
198             ImageFormat::Tga => &["tga"],
199             ImageFormat::Dds => &["dds"],
200             ImageFormat::Bmp => &["bmp"],
201             ImageFormat::Ico => &["ico"],
202             ImageFormat::Hdr => &["hdr"],
203             ImageFormat::Farbfeld => &["ff"],
204             // According to: https://aomediacodec.github.io/av1-avif/#mime-registration
205             ImageFormat::Avif => &["avif"],
206             ImageFormat::__NonExhaustive(marker) => match marker._private {},
207         }
208     }
209 }
210 
211 /// An enumeration of supported image formats for encoding.
212 #[derive(Clone, PartialEq, Eq, Debug)]
213 pub enum ImageOutputFormat {
214     #[cfg(feature = "png")]
215     /// An Image in PNG Format
216     Png,
217 
218     #[cfg(feature = "jpeg")]
219     /// An Image in JPEG Format with specified quality
220     Jpeg(u8),
221 
222     #[cfg(feature = "pnm")]
223     /// An Image in one of the PNM Formats
224     Pnm(PNMSubtype),
225 
226     #[cfg(feature = "gif")]
227     /// An Image in GIF Format
228     Gif,
229 
230     #[cfg(feature = "ico")]
231     /// An Image in ICO Format
232     Ico,
233 
234     #[cfg(feature = "bmp")]
235     /// An Image in BMP Format
236     Bmp,
237 
238     #[cfg(feature = "farbfeld")]
239     /// An Image in farbfeld Format
240     Farbfeld,
241 
242     #[cfg(feature = "tga")]
243     /// An Image in TGA Format
244     Tga,
245 
246     #[cfg(feature = "avif")]
247     /// An image in AVIF Format
248     Avif,
249 
250     /// A value for signalling an error: An unsupported format was requested
251     // Note: When TryFrom is stabilized, this value should not be needed, and
252     // a TryInto<ImageOutputFormat> should be used instead of an Into<ImageOutputFormat>.
253     Unsupported(String),
254 
255     #[doc(hidden)]
256     __NonExhaustive(crate::utils::NonExhaustiveMarker),
257 }
258 
259 impl From<ImageFormat> for ImageOutputFormat {
from(fmt: ImageFormat) -> Self260     fn from(fmt: ImageFormat) -> Self {
261         match fmt {
262             #[cfg(feature = "png")]
263             ImageFormat::Png => ImageOutputFormat::Png,
264             #[cfg(feature = "jpeg")]
265             ImageFormat::Jpeg => ImageOutputFormat::Jpeg(75),
266             #[cfg(feature = "pnm")]
267             ImageFormat::Pnm => ImageOutputFormat::Pnm(PNMSubtype::ArbitraryMap),
268             #[cfg(feature = "gif")]
269             ImageFormat::Gif => ImageOutputFormat::Gif,
270             #[cfg(feature = "ico")]
271             ImageFormat::Ico => ImageOutputFormat::Ico,
272             #[cfg(feature = "bmp")]
273             ImageFormat::Bmp => ImageOutputFormat::Bmp,
274             #[cfg(feature = "farbfeld")]
275             ImageFormat::Farbfeld => ImageOutputFormat::Farbfeld,
276             #[cfg(feature = "tga")]
277             ImageFormat::Tga => ImageOutputFormat::Tga,
278             #[cfg(feature = "avif")]
279             ImageFormat::Avif => ImageOutputFormat::Avif,
280 
281             f => ImageOutputFormat::Unsupported(format!("{:?}", f)),
282         }
283     }
284 }
285 
286 // This struct manages buffering associated with implementing `Read` and `Seek` on decoders that can
287 // must decode ranges of bytes at a time.
288 #[allow(dead_code)]
289 // When no image formats that use it are enabled
290 pub(crate) struct ImageReadBuffer {
291     scanline_bytes: usize,
292     buffer: Vec<u8>,
293     consumed: usize,
294 
295     total_bytes: u64,
296     offset: u64,
297 }
298 impl ImageReadBuffer {
299     /// Create a new ImageReadBuffer.
300     ///
301     /// Panics if scanline_bytes doesn't fit into a usize, because that would mean reading anything
302     /// from the image would take more RAM than the entire virtual address space. In other words,
303     /// actually using this struct would instantly OOM so just get it out of the way now.
304     #[allow(dead_code)]
305     // When no image formats that use it are enabled
new(scanline_bytes: u64, total_bytes: u64) -> Self306     pub(crate) fn new(scanline_bytes: u64, total_bytes: u64) -> Self {
307         Self {
308             scanline_bytes: usize::try_from(scanline_bytes).unwrap(),
309             buffer: Vec::new(),
310             consumed: 0,
311             total_bytes,
312             offset: 0,
313         }
314     }
315 
316     #[allow(dead_code)]
317     // When no image formats that use it are enabled
read<F>(&mut self, buf: &mut [u8], mut read_scanline: F) -> io::Result<usize> where F: FnMut(&mut [u8]) -> io::Result<usize>,318     pub(crate) fn read<F>(&mut self, buf: &mut [u8], mut read_scanline: F) -> io::Result<usize>
319     where
320         F: FnMut(&mut [u8]) -> io::Result<usize>,
321     {
322         if self.buffer.len() == self.consumed {
323             if self.offset == self.total_bytes {
324                 return Ok(0);
325             } else if buf.len() >= self.scanline_bytes {
326                 // If there is nothing buffered and the user requested a full scanline worth of
327                 // data, skip buffering.
328                 let bytes_read = read_scanline(&mut buf[..self.scanline_bytes])?;
329                 self.offset += u64::try_from(bytes_read).unwrap();
330                 return Ok(bytes_read);
331             } else {
332                 // Lazily allocate buffer the first time that read is called with a buffer smaller
333                 // than the scanline size.
334                 if self.buffer.is_empty() {
335                     self.buffer.resize(self.scanline_bytes, 0);
336                 }
337 
338                 self.consumed = 0;
339                 let bytes_read = read_scanline(&mut self.buffer[..])?;
340                 self.buffer.resize(bytes_read, 0);
341                 self.offset += u64::try_from(bytes_read).unwrap();
342 
343                 assert!(bytes_read == self.scanline_bytes || self.offset == self.total_bytes);
344             }
345         }
346 
347         // Finally, copy bytes into output buffer.
348         let bytes_buffered = self.buffer.len() - self.consumed;
349         if bytes_buffered > buf.len() {
350             crate::copy_memory(&self.buffer[self.consumed..][..buf.len()], &mut buf[..]);
351             self.consumed += buf.len();
352             Ok(buf.len())
353         } else {
354             crate::copy_memory(&self.buffer[self.consumed..], &mut buf[..bytes_buffered]);
355             self.consumed = self.buffer.len();
356             Ok(bytes_buffered)
357         }
358     }
359 }
360 
361 /// Decodes a specific region of the image, represented by the rectangle
362 /// starting from ```x``` and ```y``` and having ```length``` and ```width```
363 #[allow(dead_code)]
364 // When no image formats that use it are enabled
load_rect<'a, D, F, F1, F2, E>(x: u32, y: u32, width: u32, height: u32, buf: &mut [u8], progress_callback: F, decoder: &mut D, mut seek_scanline: F1, mut read_scanline: F2) -> ImageResult<()> where D: ImageDecoder<'a>, F: Fn(Progress), F1: FnMut(&mut D, u64) -> io::Result<()>, F2: FnMut(&mut D, &mut [u8]) -> Result<(), E>, ImageError: From<E>,365 pub(crate) fn load_rect<'a, D, F, F1, F2, E>(x: u32, y: u32, width: u32, height: u32, buf: &mut [u8],
366                                           progress_callback: F,
367                                           decoder: &mut D,
368                                           mut seek_scanline: F1,
369                                           mut read_scanline: F2) -> ImageResult<()>
370     where D: ImageDecoder<'a>,
371           F: Fn(Progress),
372           F1: FnMut(&mut D, u64) -> io::Result<()>,
373           F2: FnMut(&mut D, &mut [u8]) -> Result<(), E>,
374           ImageError: From<E>,
375 {
376     let (x, y, width, height) = (u64::from(x), u64::from(y), u64::from(width), u64::from(height));
377     let dimensions = decoder.dimensions();
378     let bytes_per_pixel = u64::from(decoder.color_type().bytes_per_pixel());
379     let row_bytes = bytes_per_pixel * u64::from(dimensions.0);
380     let scanline_bytes = decoder.scanline_bytes();
381     let total_bytes = width * height * bytes_per_pixel;
382 
383     if buf.len() < usize::try_from(total_bytes).unwrap_or(usize::MAX) {
384         panic!("output buffer too short\n expected `{}`, provided `{}`", total_bytes, buf.len());
385     }
386 
387     let mut bytes_read = 0u64;
388     let mut current_scanline = 0;
389     let mut tmp = Vec::new();
390     let mut tmp_scanline = None;
391 
392     {
393         // Read a range of the image starting from byte number `start` and continuing until byte
394         // number `end`. Updates `current_scanline` and `bytes_read` appropiately.
395         let mut read_image_range = |mut start: u64, end: u64| -> ImageResult<()> {
396             // If the first scanline we need is already stored in the temporary buffer, then handle
397             // it first.
398             let target_scanline = start / scanline_bytes;
399             if tmp_scanline == Some(target_scanline) {
400                 let position = target_scanline * scanline_bytes;
401                 let offset = start.saturating_sub(position);
402                 let len = (end - start)
403                     .min(scanline_bytes - offset)
404                     .min(end - position);
405 
406                 buf[(bytes_read as usize)..][..len as usize]
407                     .copy_from_slice(&tmp[offset as usize..][..len as usize]);
408                 bytes_read += len;
409                 start += len;
410 
411                 progress_callback(Progress {current: bytes_read, total: total_bytes});
412 
413                 if start == end {
414                     return Ok(());
415                 }
416             }
417 
418             let target_scanline = start / scanline_bytes;
419             if target_scanline != current_scanline {
420                 seek_scanline(decoder, target_scanline)?;
421                 current_scanline = target_scanline;
422             }
423 
424             let mut position = current_scanline * scanline_bytes;
425             while position < end {
426                 if position >= start && end - position >= scanline_bytes {
427                     read_scanline(decoder, &mut buf[(bytes_read as usize)..]
428                                                    [..(scanline_bytes as usize)])?;
429                     bytes_read += scanline_bytes;
430                 } else {
431                     tmp.resize(scanline_bytes as usize, 0u8);
432                     read_scanline(decoder, &mut tmp)?;
433                     tmp_scanline = Some(current_scanline);
434 
435                     let offset = start.saturating_sub(position);
436                     let len = (end - start)
437                         .min(scanline_bytes - offset)
438                         .min(end - position);
439 
440                     buf[(bytes_read as usize)..][..len as usize]
441                         .copy_from_slice(&tmp[offset as usize..][..len as usize]);
442                     bytes_read += len;
443                 }
444 
445                 current_scanline += 1;
446                 position += scanline_bytes;
447                 progress_callback(Progress {current: bytes_read, total: total_bytes});
448             }
449             Ok(())
450         };
451 
452         if x + width > u64::from(dimensions.0) || y + height > u64::from(dimensions.1)
453             || width == 0 || height == 0 {
454                 return Err(ImageError::Parameter(ParameterError::from_kind(
455                     ParameterErrorKind::DimensionMismatch,
456                 )));
457             }
458         if scanline_bytes > usize::max_value() as u64 {
459             return Err(ImageError::Limits(LimitError::from_kind(
460                 LimitErrorKind::InsufficientMemory,
461             )));
462         }
463 
464         progress_callback(Progress {current: 0, total: total_bytes});
465         if x == 0 && width == u64::from(dimensions.0) {
466             let start = x * bytes_per_pixel + y * row_bytes;
467             let end = (x + width) * bytes_per_pixel + (y + height - 1) * row_bytes;
468             read_image_range(start, end)?;
469         } else {
470             for row in y..(y+height) {
471                 let start = x * bytes_per_pixel + row * row_bytes;
472                 let end = (x + width) * bytes_per_pixel + row * row_bytes;
473                 read_image_range(start, end)?;
474             }
475         }
476     }
477 
478     // Seek back to the start
479     Ok(seek_scanline(decoder, 0)?)
480 }
481 
482 /// Reads all of the bytes of a decoder into a Vec<T>. No particular alignment
483 /// of the output buffer is guaranteed.
484 ///
485 /// Panics if there isn't enough memory to decode the image.
decoder_to_vec<'a, T>(decoder: impl ImageDecoder<'a>) -> ImageResult<Vec<T>> where T: crate::traits::Primitive + bytemuck::Pod,486 pub(crate) fn decoder_to_vec<'a, T>(decoder: impl ImageDecoder<'a>) -> ImageResult<Vec<T>>
487 where
488     T: crate::traits::Primitive + bytemuck::Pod,
489 {
490     let mut buf = vec![num_traits::Zero::zero(); usize::try_from(decoder.total_bytes()).unwrap() / std::mem::size_of::<T>()];
491     decoder.read_image(bytemuck::cast_slice_mut(buf.as_mut_slice()))?;
492     Ok(buf)
493 }
494 
495 /// Represents the progress of an image operation.
496 ///
497 /// Note that this is not necessarily accurate and no change to the values passed to the progress
498 /// function during decoding will be considered breaking. A decoder could in theory report the
499 /// progress `(0, 0)` if progress is unknown, without violating the interface contract of the type.
500 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
501 pub struct Progress {
502     current: u64,
503     total: u64,
504 }
505 
506 impl Progress {
507     /// A measure of completed decoding.
current(self) -> u64508     pub fn current(self) -> u64 {
509         self.current
510     }
511 
512     /// A measure of all necessary decoding work.
513     ///
514     /// This is in general greater or equal than `current`.
total(self) -> u64515     pub fn total(self) -> u64 {
516         self.total
517     }
518 
519     /// Calculate a measure for remaining decoding work.
remaining(self) -> u64520     pub fn remaining(self) -> u64 {
521         self.total.max(self.current) - self.current
522     }
523 }
524 
525 /// The trait that all decoders implement
526 pub trait ImageDecoder<'a>: Sized {
527     /// The type of reader produced by `into_reader`.
528     type Reader: Read + 'a;
529 
530     /// Returns a tuple containing the width and height of the image
dimensions(&self) -> (u32, u32)531     fn dimensions(&self) -> (u32, u32);
532 
533     /// Returns the color type of the image data produced by this decoder
color_type(&self) -> ColorType534     fn color_type(&self) -> ColorType;
535 
536     /// Retuns the color type of the image file before decoding
original_color_type(&self) -> ExtendedColorType537     fn original_color_type(&self) -> ExtendedColorType {
538         self.color_type().into()
539     }
540 
541     /// Returns a reader that can be used to obtain the bytes of the image. For the best
542     /// performance, always try to read at least `scanline_bytes` from the reader at a time. Reading
543     /// fewer bytes will cause the reader to perform internal buffering.
into_reader(self) -> ImageResult<Self::Reader>544     fn into_reader(self) -> ImageResult<Self::Reader>;
545 
546     /// Returns the total number of bytes in the decoded image.
547     ///
548     /// This is the size of the buffer that must be passed to `read_image` or
549     /// `read_image_with_progress`. The returned value may exceed usize::MAX, in
550     /// which case it isn't actually possible to construct a buffer to decode all the image data
551     /// into.
total_bytes(&self) -> u64552     fn total_bytes(&self) -> u64 {
553         let dimensions = self.dimensions();
554         u64::from(dimensions.0) * u64::from(dimensions.1) * u64::from(self.color_type().bytes_per_pixel())
555     }
556 
557     /// Returns the minimum number of bytes that can be efficiently read from this decoder. This may
558     /// be as few as 1 or as many as `total_bytes()`.
scanline_bytes(&self) -> u64559     fn scanline_bytes(&self) -> u64 {
560         self.total_bytes()
561     }
562 
563     /// Returns all the bytes in the image.
564     ///
565     /// This function takes a slice of bytes and writes the pixel data of the image into it.
566     /// Although not required, for certain color types callers may want to pass buffers which are
567     /// aligned to 2 or 4 byte boundaries to the slice can be cast to a [u16] or [u32]. To accommodate
568     /// such casts, the returned contents will always be in native endian.
569     ///
570     /// # Panics
571     ///
572     /// This function panics if buf.len() != self.total_bytes().
573     ///
574     /// # Examples
575     ///
576     /// ```no_build
577     /// use zerocopy::{AsBytes, FromBytes};
578     /// fn read_16bit_image(decoder: impl ImageDecoder) -> Vec<16> {
579     ///     let mut buf: Vec<u16> = vec![0; decoder.total_bytes()/2];
580     ///     decoder.read_image(buf.as_bytes());
581     ///     buf
582     /// }
read_image(self, buf: &mut [u8]) -> ImageResult<()>583     fn read_image(self, buf: &mut [u8]) -> ImageResult<()> {
584         self.read_image_with_progress(buf, |_| {})
585     }
586 
587     /// Same as `read_image` but periodically calls the provided callback to give updates on loading
588     /// progress.
read_image_with_progress<F: Fn(Progress)>( self, buf: &mut [u8], progress_callback: F, ) -> ImageResult<()>589     fn read_image_with_progress<F: Fn(Progress)>(
590         self,
591         buf: &mut [u8],
592         progress_callback: F,
593     ) -> ImageResult<()> {
594         assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes()));
595 
596         let total_bytes = self.total_bytes() as usize;
597         let scanline_bytes = self.scanline_bytes() as usize;
598         let target_read_size = if scanline_bytes < 4096 {
599             (4096 / scanline_bytes) * scanline_bytes
600         } else {
601             scanline_bytes
602         };
603 
604         let mut reader = self.into_reader()?;
605 
606         let mut bytes_read = 0;
607         while bytes_read < total_bytes {
608             let read_size = target_read_size.min(total_bytes - bytes_read);
609             reader.read_exact(&mut buf[bytes_read..][..read_size])?;
610             bytes_read += read_size;
611 
612             progress_callback(Progress {
613                 current: bytes_read as u64,
614                 total: total_bytes as u64,
615             });
616         }
617 
618         Ok(())
619     }
620 }
621 
622 /// Specialized image decoding not be supported by all formats
623 pub trait ImageDecoderExt<'a>: ImageDecoder<'a> + Sized {
624     /// Decode a rectangular section of the image; see [`read_rect_with_progress()`](#fn.read_rect_with_progress).
read_rect( &mut self, x: u32, y: u32, width: u32, height: u32, buf: &mut [u8], ) -> ImageResult<()>625     fn read_rect(
626         &mut self,
627         x: u32,
628         y: u32,
629         width: u32,
630         height: u32,
631         buf: &mut [u8],
632     ) -> ImageResult<()> {
633         self.read_rect_with_progress(x, y, width, height, buf, |_|{})
634     }
635 
636     /// Decode a rectangular section of the image, periodically reporting progress.
637     ///
638     /// The output buffer will be filled with fields specified by
639     /// [`ImageDecoder::color_type()`](trait.ImageDecoder.html#fn.color_type),
640     /// in that order, each field represented in native-endian.
641     ///
642     /// The progress callback will be called at least once at the start and the end of decoding,
643     /// implementations are encouraged to call this more often,
644     /// with a frequency meaningful for display to the end-user.
645     ///
646     /// This function will panic if the output buffer isn't at least
647     /// `color_type().bytes_per_pixel() * color_type().channel_count() * width * height` bytes long.
read_rect_with_progress<F: Fn(Progress)>( &mut self, x: u32, y: u32, width: u32, height: u32, buf: &mut [u8], progress_callback: F, ) -> ImageResult<()>648     fn read_rect_with_progress<F: Fn(Progress)>(
649         &mut self,
650         x: u32,
651         y: u32,
652         width: u32,
653         height: u32,
654         buf: &mut [u8],
655         progress_callback: F,
656     ) -> ImageResult<()>;
657 }
658 
659 /// AnimationDecoder trait
660 pub trait AnimationDecoder<'a> {
661     /// Consume the decoder producing a series of frames.
into_frames(self) -> Frames<'a>662     fn into_frames(self) -> Frames<'a>;
663 }
664 
665 /// The trait all encoders implement
666 pub trait ImageEncoder {
667     /// Writes all the bytes in an image to the encoder.
668     ///
669     /// This function takes a slice of bytes of the pixel data of the image
670     /// and encodes them. Unlike particular format encoders inherent impl encode
671     /// methods where endianness is not specified, here image data bytes should
672     /// always be in native endian. The implementor will reorder the endianess
673     /// as necessary for the target encoding format.
674     ///
675     /// See also `ImageDecoder::read_image` which reads byte buffers into
676     /// native endian.
write_image( self, buf: &[u8], width: u32, height: u32, color_type: ColorType, ) -> ImageResult<()>677     fn write_image(
678         self,
679         buf: &[u8],
680         width: u32,
681         height: u32,
682         color_type: ColorType,
683     ) -> ImageResult<()>;
684 }
685 
686 /// Immutable pixel iterator
687 #[derive(Debug)]
688 pub struct Pixels<'a, I: ?Sized + 'a> {
689     image: &'a I,
690     x: u32,
691     y: u32,
692     width: u32,
693     height: u32,
694 }
695 
696 impl<'a, I: GenericImageView> Iterator for Pixels<'a, I> {
697     type Item = (u32, u32, I::Pixel);
698 
next(&mut self) -> Option<(u32, u32, I::Pixel)>699     fn next(&mut self) -> Option<(u32, u32, I::Pixel)> {
700         if self.x >= self.width {
701             self.x = 0;
702             self.y += 1;
703         }
704 
705         if self.y >= self.height {
706             None
707         } else {
708             let pixel = self.image.get_pixel(self.x, self.y);
709             let p = (self.x, self.y, pixel);
710 
711             self.x += 1;
712 
713             Some(p)
714         }
715     }
716 }
717 
718 impl<I: ?Sized> Clone for Pixels<'_, I> {
clone(&self) -> Self719     fn clone(&self) -> Self {
720         Pixels { ..*self }
721     }
722 }
723 
724 /// Trait to inspect an image.
725 pub trait GenericImageView {
726     /// The type of pixel.
727     type Pixel: Pixel;
728 
729     /// Underlying image type. This is mainly used by SubImages in order to
730     /// always have a reference to the original image. This allows for less
731     /// indirections and it eases the use of nested SubImages.
732     type InnerImageView: GenericImageView<Pixel = Self::Pixel>;
733 
734     /// The width and height of this image.
dimensions(&self) -> (u32, u32)735     fn dimensions(&self) -> (u32, u32);
736 
737     /// The width of this image.
width(&self) -> u32738     fn width(&self) -> u32 {
739         let (w, _) = self.dimensions();
740         w
741     }
742 
743     /// The height of this image.
height(&self) -> u32744     fn height(&self) -> u32 {
745         let (_, h) = self.dimensions();
746         h
747     }
748 
749     /// The bounding rectangle of this image.
bounds(&self) -> (u32, u32, u32, u32)750     fn bounds(&self) -> (u32, u32, u32, u32);
751 
752     /// Returns true if this x, y coordinate is contained inside the image.
in_bounds(&self, x: u32, y: u32) -> bool753     fn in_bounds(&self, x: u32, y: u32) -> bool {
754         let (ix, iy, iw, ih) = self.bounds();
755         x >= ix && x < ix + iw && y >= iy && y < iy + ih
756     }
757 
758     /// Returns the pixel located at (x, y). Indexed from top left.
759     ///
760     /// # Panics
761     ///
762     /// Panics if `(x, y)` is out of bounds.
763     ///
764     /// TODO: change this signature to &P
get_pixel(&self, x: u32, y: u32) -> Self::Pixel765     fn get_pixel(&self, x: u32, y: u32) -> Self::Pixel;
766 
767     /// Returns the pixel located at (x, y). Indexed from top left.
768     ///
769     /// This function can be implemented in a way that ignores bounds checking.
770     /// # Safety
771     ///
772     /// The coordinates must be [`in_bounds`] of the image.
773     ///
774     /// [`in_bounds`]: #method.in_bounds
unsafe_get_pixel(&self, x: u32, y: u32) -> Self::Pixel775     unsafe fn unsafe_get_pixel(&self, x: u32, y: u32) -> Self::Pixel {
776         self.get_pixel(x, y)
777     }
778 
779     /// Returns an Iterator over the pixels of this image.
780     /// The iterator yields the coordinates of each pixel
781     /// along with their value
pixels(&self) -> Pixels<Self>782     fn pixels(&self) -> Pixels<Self> {
783         let (width, height) = self.dimensions();
784 
785         Pixels {
786             image: self,
787             x: 0,
788             y: 0,
789             width,
790             height,
791         }
792     }
793 
794     /// Returns a reference to the underlying image.
inner(&self) -> &Self::InnerImageView795     fn inner(&self) -> &Self::InnerImageView;
796 
797     /// Returns an subimage that is an immutable view into this image.
798     /// You can use [`GenericImage::sub_image`] if you need a mutable view instead.
799     /// The coordinates set the position of the top left corner of the view.
view(&self, x: u32, y: u32, width: u32, height: u32) -> SubImage<&Self::InnerImageView>800     fn view(&self, x: u32, y: u32, width: u32, height: u32) -> SubImage<&Self::InnerImageView> {
801         SubImage::new(self.inner(), x, y, width, height)
802     }
803 }
804 
805 /// A trait for manipulating images.
806 pub trait GenericImage: GenericImageView {
807     /// Underlying image type. This is mainly used by SubImages in order to
808     /// always have a reference to the original image. This allows for less
809     /// indirections and it eases the use of nested SubImages.
810     type InnerImage: GenericImage<Pixel = Self::Pixel>;
811 
812     /// Gets a reference to the mutable pixel at location `(x, y)`. Indexed from top left.
813     ///
814     /// # Panics
815     ///
816     /// Panics if `(x, y)` is out of bounds.
get_pixel_mut(&mut self, x: u32, y: u32) -> &mut Self::Pixel817     fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut Self::Pixel;
818 
819     /// Put a pixel at location (x, y). Indexed from top left.
820     ///
821     /// # Panics
822     ///
823     /// Panics if `(x, y)` is out of bounds.
put_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel)824     fn put_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel);
825 
826     /// Puts a pixel at location (x, y). Indexed from top left.
827     ///
828     /// This function can be implemented in a way that ignores bounds checking.
829     /// # Safety
830     ///
831     /// The coordinates must be [`in_bounds`] of the image.
832     ///
833     /// [`in_bounds`]: traits.GenericImageView.html#method.in_bounds
unsafe_put_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel)834     unsafe fn unsafe_put_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel) {
835         self.put_pixel(x, y, pixel);
836     }
837 
838     /// Put a pixel at location (x, y), taking into account alpha channels
839     ///
840     /// DEPRECATED: This method will be removed. Blend the pixel directly instead.
blend_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel)841     fn blend_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel);
842 
843     /// Copies all of the pixels from another image into this image.
844     ///
845     /// The other image is copied with the top-left corner of the
846     /// other image placed at (x, y).
847     ///
848     /// In order to copy only a piece of the other image, use [`GenericImageView::view`].
849     ///
850     /// You can use [`FlatSamples`] to source pixels from an arbitrary regular raster of channel
851     /// values, for example from a foreign interface or a fixed image.
852     ///
853     /// # Returns
854     /// Returns an error if the image is too large to be copied at the given position
855     ///
856     /// [`GenericImageView::view`]: trait.GenericImageView.html#method.view
857     /// [`FlatSamples`]: flat/struct.FlatSamples.html
copy_from<O>(&mut self, other: &O, x: u32, y: u32) -> ImageResult<()> where O: GenericImageView<Pixel = Self::Pixel>,858     fn copy_from<O>(&mut self, other: &O, x: u32, y: u32) -> ImageResult<()>
859     where
860         O: GenericImageView<Pixel = Self::Pixel>,
861     {
862         // Do bounds checking here so we can use the non-bounds-checking
863         // functions to copy pixels.
864         if self.width() < other.width() + x || self.height() < other.height() + y {
865             return Err(ImageError::Parameter(ParameterError::from_kind(
866                 ParameterErrorKind::DimensionMismatch,
867             )));
868         }
869 
870         for k in 0..other.height() {
871             for i in 0..other.width() {
872                 let p = other.get_pixel(i, k);
873                 self.put_pixel(i + x, k + y, p);
874             }
875         }
876         Ok(())
877     }
878 
879     /// Copies all of the pixels from one part of this image to another part of this image.
880     ///
881     /// The destination rectangle of the copy is specified with the top-left corner placed at (x, y).
882     ///
883     /// # Returns
884     /// `true` if the copy was successful, `false` if the image could not
885     /// be copied due to size constraints.
copy_within(&mut self, source: Rect, x: u32, y: u32) -> bool886     fn copy_within(&mut self, source: Rect, x: u32, y: u32) -> bool {
887         let Rect { x: sx, y: sy, width, height } = source;
888         let dx = x;
889         let dy = y;
890         assert!(sx < self.width() && dx < self.width());
891         assert!(sy < self.height() && dy < self.height());
892         if self.width() - dx.max(sx) < width || self.height() - dy.max(sy) < height {
893             return false;
894         }
895         // since `.rev()` creates a new dype we would either have to go with dynamic dispatch for the ranges
896         // or have quite a lot of code bloat. A macro gives us static dispatch with less visible bloat.
897         macro_rules! copy_within_impl_ {
898             ($xiter:expr, $yiter:expr) => {
899                 for y in $yiter {
900                     let sy = sy + y;
901                     let dy = dy + y;
902                     for x in $xiter {
903                         let sx = sx + x;
904                         let dx = dx + x;
905                         let pixel = self.get_pixel(sx, sy);
906                         self.put_pixel(dx, dy, pixel);
907                     }
908                 }
909             };
910         }
911         // check how target and source rectangles relate to each other so we dont overwrite data before we copied it.
912         match (sx < dx, sy < dy) {
913             (true, true) => copy_within_impl_!((0..width).rev(), (0..height).rev()),
914             (true, false) => copy_within_impl_!((0..width).rev(), 0..height),
915             (false, true) => copy_within_impl_!(0..width, (0..height).rev()),
916             (false, false) => copy_within_impl_!(0..width, 0..height),
917         }
918         true
919     }
920 
921     /// Returns a mutable reference to the underlying image.
inner_mut(&mut self) -> &mut Self::InnerImage922     fn inner_mut(&mut self) -> &mut Self::InnerImage;
923 
924     /// Returns a mutable subimage that is a view into this image.
925     /// If you want an immutable subimage instead, use [`GenericImageView::view`]
926     /// The coordinates set the position of the top left corner of the SubImage.
sub_image( &mut self, x: u32, y: u32, width: u32, height: u32, ) -> SubImage<&mut Self::InnerImage>927     fn sub_image(
928         &mut self,
929         x: u32,
930         y: u32,
931         width: u32,
932         height: u32,
933     ) -> SubImage<&mut Self::InnerImage> {
934         SubImage::new(self.inner_mut(), x, y, width, height)
935     }
936 }
937 
938 /// A View into another image
939 ///
940 /// Instances of this struct can be created using:
941 ///   - [`GenericImage::sub_image`] to create a mutable view,
942 ///   - [`GenericImageView::view`] to create an immutable view,
943 ///   - [`SubImage::new`] to instantiate the struct directly.
944 pub struct SubImage<I> {
945     image: I,
946     xoffset: u32,
947     yoffset: u32,
948     xstride: u32,
949     ystride: u32,
950 }
951 
952 /// Alias to access Pixel behind a reference
953 type DerefPixel<I> = <<I as Deref>::Target as GenericImageView>::Pixel;
954 
955 /// Alias to access Subpixel behind a reference
956 type DerefSubpixel<I> = <DerefPixel<I> as Pixel>::Subpixel;
957 
958 impl<I> SubImage<I> {
959     /// Construct a new subimage
960     /// The coordinates set the position of the top left corner of the SubImage.
new(image: I, x: u32, y: u32, width: u32, height: u32) -> SubImage<I>961     pub fn new(image: I, x: u32, y: u32, width: u32, height: u32) -> SubImage<I> {
962         SubImage {
963             image,
964             xoffset: x,
965             yoffset: y,
966             xstride: width,
967             ystride: height,
968         }
969     }
970 
971     /// Change the coordinates of this subimage.
change_bounds(&mut self, x: u32, y: u32, width: u32, height: u32)972     pub fn change_bounds(&mut self, x: u32, y: u32, width: u32, height: u32) {
973         self.xoffset = x;
974         self.yoffset = y;
975         self.xstride = width;
976         self.ystride = height;
977     }
978 
979     /// Convert this subimage to an ImageBuffer
to_image(&self) -> ImageBuffer<DerefPixel<I>, Vec<DerefSubpixel<I>>> where I: Deref, I::Target: GenericImage + 'static,980     pub fn to_image(&self) -> ImageBuffer<DerefPixel<I>, Vec<DerefSubpixel<I>>>
981     where
982         I: Deref,
983         I::Target: GenericImage + 'static,
984     {
985         let mut out = ImageBuffer::new(self.xstride, self.ystride);
986         let borrowed = self.image.deref();
987 
988         for y in 0..self.ystride {
989             for x in 0..self.xstride {
990                 let p = borrowed.get_pixel(x + self.xoffset, y + self.yoffset);
991                 out.put_pixel(x, y, p);
992             }
993         }
994 
995         out
996     }
997 }
998 
999 #[allow(deprecated)]
1000 impl<I> GenericImageView for SubImage<I>
1001 where
1002     I: Deref,
1003     I::Target: GenericImageView + Sized,
1004 {
1005     type Pixel = DerefPixel<I>;
1006     type InnerImageView = I::Target;
1007 
dimensions(&self) -> (u32, u32)1008     fn dimensions(&self) -> (u32, u32) {
1009         (self.xstride, self.ystride)
1010     }
1011 
bounds(&self) -> (u32, u32, u32, u32)1012     fn bounds(&self) -> (u32, u32, u32, u32) {
1013         (self.xoffset, self.yoffset, self.xstride, self.ystride)
1014     }
1015 
get_pixel(&self, x: u32, y: u32) -> Self::Pixel1016     fn get_pixel(&self, x: u32, y: u32) -> Self::Pixel {
1017         self.image.get_pixel(x + self.xoffset, y + self.yoffset)
1018     }
1019 
view(&self, x: u32, y: u32, width: u32, height: u32) -> SubImage<&Self::InnerImageView>1020     fn view(&self, x: u32, y: u32, width: u32, height: u32) -> SubImage<&Self::InnerImageView> {
1021         let x = self.xoffset + x;
1022         let y = self.yoffset + y;
1023         SubImage::new(self.inner(), x, y, width, height)
1024     }
1025 
inner(&self) -> &Self::InnerImageView1026     fn inner(&self) -> &Self::InnerImageView {
1027         &self.image
1028     }
1029 }
1030 
1031 #[allow(deprecated)]
1032 impl<I> GenericImage for SubImage<I>
1033 where
1034     I: DerefMut,
1035     I::Target: GenericImage + Sized,
1036 {
1037     type InnerImage = I::Target;
1038 
get_pixel_mut(&mut self, x: u32, y: u32) -> &mut Self::Pixel1039     fn get_pixel_mut(&mut self, x: u32, y: u32) -> &mut Self::Pixel {
1040         self.image.get_pixel_mut(x + self.xoffset, y + self.yoffset)
1041     }
1042 
put_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel)1043     fn put_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel) {
1044         self.image
1045             .put_pixel(x + self.xoffset, y + self.yoffset, pixel)
1046     }
1047 
1048     /// DEPRECATED: This method will be removed. Blend the pixel directly instead.
blend_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel)1049     fn blend_pixel(&mut self, x: u32, y: u32, pixel: Self::Pixel) {
1050         self.image
1051             .blend_pixel(x + self.xoffset, y + self.yoffset, pixel)
1052     }
1053 
sub_image( &mut self, x: u32, y: u32, width: u32, height: u32, ) -> SubImage<&mut Self::InnerImage>1054     fn sub_image(
1055         &mut self,
1056         x: u32,
1057         y: u32,
1058         width: u32,
1059         height: u32,
1060     ) -> SubImage<&mut Self::InnerImage> {
1061         let x = self.xoffset + x;
1062         let y = self.yoffset + y;
1063         SubImage::new(self.inner_mut(), x, y, width, height)
1064     }
1065 
inner_mut(&mut self) -> &mut Self::InnerImage1066     fn inner_mut(&mut self) -> &mut Self::InnerImage {
1067         &mut self.image
1068     }
1069 }
1070 
1071 #[cfg(test)]
1072 mod tests {
1073     use std::io;
1074     use std::path::Path;
1075 
1076     use super::{ColorType, ImageDecoder, ImageResult, GenericImage, GenericImageView, load_rect, ImageFormat};
1077     use crate::{GrayImage, ImageBuffer};
1078     use crate::color::Rgba;
1079     use crate::math::Rect;
1080 
1081     #[test]
1082     /// Test that alpha blending works as expected
test_image_alpha_blending()1083     fn test_image_alpha_blending() {
1084         let mut target = ImageBuffer::new(1, 1);
1085         target.put_pixel(0, 0, Rgba([255u8, 0, 0, 255]));
1086         assert!(*target.get_pixel(0, 0) == Rgba([255, 0, 0, 255]));
1087         target.blend_pixel(0, 0, Rgba([0, 255, 0, 255]));
1088         assert!(*target.get_pixel(0, 0) == Rgba([0, 255, 0, 255]));
1089 
1090         // Blending an alpha channel onto a solid background
1091         target.blend_pixel(0, 0, Rgba([255, 0, 0, 127]));
1092         assert!(*target.get_pixel(0, 0) == Rgba([127, 127, 0, 255]));
1093 
1094         // Blending two alpha channels
1095         target.put_pixel(0, 0, Rgba([0, 255, 0, 127]));
1096         target.blend_pixel(0, 0, Rgba([255, 0, 0, 127]));
1097         assert!(*target.get_pixel(0, 0) == Rgba([169, 85, 0, 190]));
1098     }
1099 
1100     #[test]
test_in_bounds()1101     fn test_in_bounds() {
1102         let mut target = ImageBuffer::new(2, 2);
1103         target.put_pixel(0, 0, Rgba([255u8, 0, 0, 255]));
1104 
1105         assert!(target.in_bounds(0, 0));
1106         assert!(target.in_bounds(1, 0));
1107         assert!(target.in_bounds(0, 1));
1108         assert!(target.in_bounds(1, 1));
1109 
1110         assert!(!target.in_bounds(2, 0));
1111         assert!(!target.in_bounds(0, 2));
1112         assert!(!target.in_bounds(2, 2));
1113     }
1114 
1115     #[test]
test_can_subimage_clone_nonmut()1116     fn test_can_subimage_clone_nonmut() {
1117         let mut source = ImageBuffer::new(3, 3);
1118         source.put_pixel(1, 1, Rgba([255u8, 0, 0, 255]));
1119 
1120         // A non-mutable copy of the source image
1121         let source = source.clone();
1122 
1123         // Clone a view into non-mutable to a separate buffer
1124         let cloned = source.view(1, 1, 1, 1).to_image();
1125 
1126         assert!(cloned.get_pixel(0, 0) == source.get_pixel(1, 1));
1127     }
1128 
1129     #[test]
test_can_nest_views()1130     fn test_can_nest_views() {
1131         let mut source = ImageBuffer::from_pixel(3, 3, Rgba([255u8, 0, 0, 255]));
1132 
1133         {
1134             let mut sub1 = source.sub_image(0, 0, 2, 2);
1135             let mut sub2 = sub1.sub_image(1, 1, 1, 1);
1136             sub2.put_pixel(0, 0, Rgba([0, 0, 0, 0]));
1137         }
1138 
1139         assert_eq!(*source.get_pixel(1, 1), Rgba([0, 0, 0, 0]));
1140 
1141         let view1 = source.view(0, 0, 2, 2);
1142         assert_eq!(*source.get_pixel(1, 1), view1.get_pixel(1, 1));
1143 
1144         let view2 = view1.view(1, 1, 1, 1);
1145         assert_eq!(*source.get_pixel(1, 1), view2.get_pixel(0, 0));
1146     }
1147 
1148     #[test]
test_load_rect()1149     fn test_load_rect() {
1150         struct MockDecoder {scanline_number: u64, scanline_bytes: u64}
1151         impl<'a> ImageDecoder<'a> for MockDecoder {
1152             type Reader = Box<dyn io::Read>;
1153             fn dimensions(&self) -> (u32, u32) {(5, 5)}
1154             fn color_type(&self) -> ColorType {  ColorType::L8 }
1155             fn into_reader(self) -> ImageResult<Self::Reader> {unimplemented!()}
1156             fn scanline_bytes(&self) -> u64 { self.scanline_bytes }
1157         }
1158 
1159         const DATA: [u8; 25] = [0,  1,  2,  3,  4,
1160                                 5,  6,  7,  8,  9,
1161                                 10, 11, 12, 13, 14,
1162                                 15, 16, 17, 18, 19,
1163                                 20, 21, 22, 23, 24];
1164 
1165         fn seek_scanline(m: &mut MockDecoder, n: u64) -> io::Result<()> {
1166             m.scanline_number = n;
1167             Ok(())
1168         }
1169         fn read_scanline(m: &mut MockDecoder, buf: &mut [u8]) -> io::Result<()> {
1170             let bytes_read = m.scanline_number * m.scanline_bytes;
1171             if bytes_read >= 25 {
1172                 return Ok(());
1173             }
1174 
1175             let len = m.scanline_bytes.min(25 - bytes_read);
1176             buf[..(len as usize)].copy_from_slice(&DATA[(bytes_read as usize)..][..(len as usize)]);
1177             m.scanline_number += 1;
1178             Ok(())
1179         }
1180 
1181         for scanline_bytes in 1..30 {
1182             let mut output = [0u8; 26];
1183 
1184             load_rect(0, 0, 5, 5, &mut output, |_|{},
1185                       &mut MockDecoder{scanline_number:0, scanline_bytes},
1186                       seek_scanline, read_scanline).unwrap();
1187             assert_eq!(output[0..25], DATA);
1188             assert_eq!(output[25], 0);
1189 
1190             output = [0u8; 26];
1191             load_rect(3, 2, 1, 1, &mut output, |_|{},
1192                       &mut MockDecoder{scanline_number:0, scanline_bytes},
1193                       seek_scanline, read_scanline).unwrap();
1194             assert_eq!(output[0..2], [13, 0]);
1195 
1196             output = [0u8; 26];
1197             load_rect(3, 2, 2, 2, &mut output, |_|{},
1198                       &mut MockDecoder{scanline_number:0, scanline_bytes},
1199                       seek_scanline, read_scanline).unwrap();
1200             assert_eq!(output[0..5], [13, 14, 18, 19, 0]);
1201 
1202 
1203             output = [0u8; 26];
1204             load_rect(1, 1, 2, 4, &mut output, |_|{},
1205                       &mut MockDecoder{scanline_number:0, scanline_bytes},
1206                       seek_scanline, read_scanline).unwrap();
1207             assert_eq!(output[0..9], [6, 7, 11, 12, 16, 17, 21, 22, 0]);
1208 
1209         }
1210     }
1211 
1212     #[test]
test_load_rect_single_scanline()1213     fn test_load_rect_single_scanline() {
1214         const DATA: [u8; 25] = [0,  1,  2,  3,  4,
1215                                 5,  6,  7,  8,  9,
1216                                 10, 11, 12, 13, 14,
1217                                 15, 16, 17, 18, 19,
1218                                 20, 21, 22, 23, 24];
1219 
1220         struct MockDecoder;
1221         impl<'a> ImageDecoder<'a> for MockDecoder {
1222             type Reader = Box<dyn io::Read>;
1223             fn dimensions(&self) -> (u32, u32) {(5, 5)}
1224             fn color_type(&self) -> ColorType {  ColorType::L8 }
1225             fn into_reader(self) -> ImageResult<Self::Reader> {unimplemented!()}
1226             fn scanline_bytes(&self) -> u64 { 25 }
1227         }
1228 
1229         // Ensure that seek scanline is called only once.
1230         let mut seeks = 0;
1231         let seek_scanline = |_d: &mut MockDecoder, n: u64| -> io::Result<()> {
1232             seeks += 1;
1233             assert_eq!(n, 0);
1234             assert_eq!(seeks, 1);
1235             Ok(())
1236         };
1237 
1238         fn read_scanline(_m: &mut MockDecoder, buf: &mut [u8]) -> io::Result<()> {
1239             buf.copy_from_slice(&DATA);
1240             Ok(())
1241         }
1242 
1243         let mut output = [0; 26];
1244         load_rect(1, 1, 2, 4, &mut output, |_|{},
1245                     &mut MockDecoder,
1246                     seek_scanline, read_scanline).unwrap();
1247         assert_eq!(output[0..9], [6, 7, 11, 12, 16, 17, 21, 22, 0]);
1248     }
1249 
1250 
1251     #[test]
test_image_format_from_path()1252     fn test_image_format_from_path() {
1253         fn from_path(s: &str) -> ImageResult<ImageFormat> {
1254             ImageFormat::from_path(Path::new(s))
1255         }
1256         assert_eq!(from_path("./a.jpg").unwrap(), ImageFormat::Jpeg);
1257         assert_eq!(from_path("./a.jpeg").unwrap(), ImageFormat::Jpeg);
1258         assert_eq!(from_path("./a.JPEG").unwrap(), ImageFormat::Jpeg);
1259         assert_eq!(from_path("./a.pNg").unwrap(), ImageFormat::Png);
1260         assert_eq!(from_path("./a.gif").unwrap(), ImageFormat::Gif);
1261         assert_eq!(from_path("./a.webp").unwrap(), ImageFormat::WebP);
1262         assert_eq!(from_path("./a.tiFF").unwrap(), ImageFormat::Tiff);
1263         assert_eq!(from_path("./a.tif").unwrap(), ImageFormat::Tiff);
1264         assert_eq!(from_path("./a.tga").unwrap(), ImageFormat::Tga);
1265         assert_eq!(from_path("./a.dds").unwrap(), ImageFormat::Dds);
1266         assert_eq!(from_path("./a.bmp").unwrap(), ImageFormat::Bmp);
1267         assert_eq!(from_path("./a.Ico").unwrap(), ImageFormat::Ico);
1268         assert_eq!(from_path("./a.hdr").unwrap(), ImageFormat::Hdr);
1269         assert_eq!(from_path("./a.pbm").unwrap(), ImageFormat::Pnm);
1270         assert_eq!(from_path("./a.pAM").unwrap(), ImageFormat::Pnm);
1271         assert_eq!(from_path("./a.Ppm").unwrap(), ImageFormat::Pnm);
1272         assert_eq!(from_path("./a.pgm").unwrap(), ImageFormat::Pnm);
1273         assert_eq!(from_path("./a.AViF").unwrap(), ImageFormat::Avif);
1274         assert!(from_path("./a.txt").is_err());
1275         assert!(from_path("./a").is_err());
1276     }
1277 
1278     #[test]
test_generic_image_copy_within_oob()1279     fn test_generic_image_copy_within_oob() {
1280         let mut image: GrayImage = ImageBuffer::from_raw(4, 4, vec![0u8; 16]).unwrap();
1281         assert!(!image.sub_image(0, 0, 4, 4).copy_within(Rect { x: 0, y: 0, width: 5, height: 4 }, 0, 0));
1282         assert!(!image.sub_image(0, 0, 4, 4).copy_within(Rect { x: 0, y: 0, width: 4, height: 5 }, 0, 0));
1283         assert!(!image.sub_image(0, 0, 4, 4).copy_within(Rect { x: 1, y: 0, width: 4, height: 4 }, 0, 0));
1284         assert!(!image.sub_image(0, 0, 4, 4).copy_within(Rect { x: 0, y: 0, width: 4, height: 4 }, 1, 0));
1285         assert!(!image.sub_image(0, 0, 4, 4).copy_within(Rect { x: 0, y: 1, width: 4, height: 4 }, 0, 0));
1286         assert!(!image.sub_image(0, 0, 4, 4).copy_within(Rect { x: 0, y: 0, width: 4, height: 4 }, 0, 1));
1287         assert!(!image.sub_image(0, 0, 4, 4).copy_within(Rect { x: 1, y: 1, width: 4, height: 4 }, 0, 0));
1288     }
1289 
1290     #[test]
test_generic_image_copy_within_tl()1291     fn test_generic_image_copy_within_tl() {
1292         let data = &[
1293             00, 01, 02, 03,
1294             04, 05, 06, 07,
1295             08, 09, 10, 11,
1296             12, 13, 14, 15
1297         ];
1298         let expected = [
1299             00, 01, 02, 03,
1300             04, 00, 01, 02,
1301             08, 04, 05, 06,
1302             12, 08, 09, 10,
1303         ];
1304         let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap();
1305         assert!(image.sub_image(0, 0, 4, 4).copy_within(Rect { x: 0, y: 0, width: 3, height: 3 }, 1, 1));
1306         assert_eq!(&image.into_raw(), &expected);
1307     }
1308 
1309     #[test]
test_generic_image_copy_within_tr()1310     fn test_generic_image_copy_within_tr() {
1311         let data = &[
1312             00, 01, 02, 03,
1313             04, 05, 06, 07,
1314             08, 09, 10, 11,
1315             12, 13, 14, 15
1316         ];
1317         let expected = [
1318             00, 01, 02, 03,
1319             01, 02, 03, 07,
1320             05, 06, 07, 11,
1321             09, 10, 11, 15
1322         ];
1323         let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap();
1324         assert!(image.sub_image(0, 0, 4, 4).copy_within(Rect { x: 1, y: 0, width: 3, height: 3 }, 0, 1));
1325         assert_eq!(&image.into_raw(), &expected);
1326     }
1327 
1328     #[test]
test_generic_image_copy_within_bl()1329     fn test_generic_image_copy_within_bl() {
1330         let data = &[
1331             00, 01, 02, 03,
1332             04, 05, 06, 07,
1333             08, 09, 10, 11,
1334             12, 13, 14, 15
1335         ];
1336         let expected = [
1337             00, 04, 05, 06,
1338             04, 08, 09, 10,
1339             08, 12, 13, 14,
1340             12, 13, 14, 15
1341         ];
1342         let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap();
1343         assert!(image.sub_image(0, 0, 4, 4).copy_within(Rect { x: 0, y: 1, width: 3, height: 3 }, 1, 0));
1344         assert_eq!(&image.into_raw(), &expected);
1345     }
1346 
1347     #[test]
test_generic_image_copy_within_br()1348     fn test_generic_image_copy_within_br() {
1349         let data = &[
1350             00, 01, 02, 03,
1351             04, 05, 06, 07,
1352             08, 09, 10, 11,
1353             12, 13, 14, 15
1354         ];
1355         let expected = [
1356             05, 06, 07, 03,
1357             09, 10, 11, 07,
1358             13, 14, 15, 11,
1359             12, 13, 14, 15
1360         ];
1361         let mut image: GrayImage = ImageBuffer::from_raw(4, 4, Vec::from(&data[..])).unwrap();
1362         assert!(image.sub_image(0, 0, 4, 4).copy_within(Rect { x: 1, y: 1, width: 3, height: 3 }, 0, 0));
1363         assert_eq!(&image.into_raw(), &expected);
1364     }
1365 
1366     #[test]
image_formats_are_recognized()1367     fn image_formats_are_recognized() {
1368         use ImageFormat::*;
1369         const ALL_FORMATS: &'static [ImageFormat] = &[Avif, Png, Jpeg, Gif, WebP, Pnm, Tiff, Tga, Dds, Bmp, Ico, Hdr, Farbfeld];
1370         for &format in ALL_FORMATS {
1371             let mut file = Path::new("file.nothing").to_owned();
1372             for ext in format.extensions_str() {
1373                 assert!(file.set_extension(ext));
1374                 match ImageFormat::from_path(&file) {
1375                     Err(_) => panic!("Path {} not recognized as {:?}", file.display(), format),
1376                     Ok(result) => assert_eq!(format, result),
1377                 }
1378             }
1379         }
1380     }
1381 }
1382