icns/
image.rs

1use std;
2use std::io;
3
4/// A decoded icon image.
5///
6/// An `Image` struct consists of a width, a height, a
7/// [`PixelFormat`](enum.PixelFormat.html), and a data array encoding the image
8/// pixels in that format.
9///
10/// Regardless of format, pixel data for an image is always stored one complete
11/// pixel at a time, in row-major order (that is, the top-left pixel comes
12/// first, followed by the rest of the top row from left to right; then comes
13/// the second row down, again from left to right, and so on until finally the
14/// bottom-right pixel comes last).
15#[derive(Clone)]
16pub struct Image {
17    pub(crate) format: PixelFormat,
18    pub(crate) width: u32,
19    pub(crate) height: u32,
20    pub(crate) data: Box<[u8]>,
21}
22
23impl Image {
24    /// Creates a new image with all pixel data set to zero.
25    pub fn new(format: PixelFormat, width: u32, height: u32) -> Image {
26        let data_bits = format.bits_per_pixel() * width * height;
27        let data_bytes = ((data_bits + 7) / 8) as usize;
28        Image {
29            format: format,
30            width: width,
31            height: height,
32            data: vec![0u8; data_bytes].into_boxed_slice(),
33        }
34    }
35
36    /// Creates a new image using the given pixel data.  Returns an error if
37    /// the data array is not the correct length.
38    pub fn from_data(format: PixelFormat,
39                     width: u32,
40                     height: u32,
41                     data: Vec<u8>)
42                     -> io::Result<Image> {
43        let data_bits = format.bits_per_pixel() * width * height;
44        let data_bytes = ((data_bits + 7) / 8) as usize;
45        if data.len() == data_bytes {
46            Ok(Image {
47                format: format,
48                width: width,
49                height: height,
50                data: data.into_boxed_slice(),
51            })
52        } else {
53            let msg = format!("incorrect pixel data array length for \
54                               speicifed format and dimensions ({} instead \
55                               of {})",
56                              data.len(),
57                              data_bytes);
58            Err(io::Error::new(io::ErrorKind::InvalidInput, msg))
59        }
60    }
61
62    /// Returns the format in which this image's pixel data is stored.
63    pub fn pixel_format(&self) -> PixelFormat {
64        self.format
65    }
66
67    /// Returns the width of the image, in pixels.
68    pub fn width(&self) -> u32 {
69        self.width
70    }
71
72    /// Returns the height of the image, in pixels.
73    pub fn height(&self) -> u32 {
74        self.height
75    }
76
77    /// Returns a reference to the image's pixel data.
78    pub fn data(&self) -> &[u8] {
79        &self.data
80    }
81
82    /// Returns a mutable reference to the image's pixel data.
83    pub fn data_mut(&mut self) -> &mut [u8] {
84        &mut self.data
85    }
86
87    /// Consumes the image, returning the pixel data without cloning it.
88    pub fn into_data(self) -> Box<[u8]> {
89        self.data
90    }
91
92    /// Creates a copy of this image by converting to the specified pixel
93    /// format.  This operation always succeeds, but may lose information (e.g.
94    /// converting from RGBA to RGB will silently drop the alpha channel).  If
95    /// the source image is already in the requested format, this is equivalant
96    /// to simply calling `clone()`.
97    pub fn convert_to(&self, format: PixelFormat) -> Image {
98        let new_data = match self.format {
99            PixelFormat::RGBA => {
100                match format {
101                    PixelFormat::RGBA => self.data.clone(),
102                    PixelFormat::RGB => rgba_to_rgb(&self.data),
103                    PixelFormat::GrayAlpha => rgba_to_grayalpha(&self.data),
104                    PixelFormat::Gray => rgba_to_gray(&self.data),
105                    PixelFormat::Alpha => rgba_to_alpha(&self.data),
106                }
107            }
108            PixelFormat::RGB => {
109                match format {
110                    PixelFormat::RGBA => rgb_to_rgba(&self.data),
111                    PixelFormat::RGB => self.data.clone(),
112                    PixelFormat::GrayAlpha => rgb_to_grayalpha(&self.data),
113                    PixelFormat::Gray => rgb_to_gray(&self.data),
114                    PixelFormat::Alpha => rgb_to_alpha(&self.data),
115                }
116            }
117            PixelFormat::GrayAlpha => {
118                match format {
119                    PixelFormat::RGBA => grayalpha_to_rgba(&self.data),
120                    PixelFormat::RGB => grayalpha_to_rgb(&self.data),
121                    PixelFormat::GrayAlpha => self.data.clone(),
122                    PixelFormat::Gray => grayalpha_to_gray(&self.data),
123                    PixelFormat::Alpha => grayalpha_to_alpha(&self.data),
124                }
125            }
126            PixelFormat::Gray => {
127                match format {
128                    PixelFormat::RGBA => gray_to_rgba(&self.data),
129                    PixelFormat::RGB => gray_to_rgb(&self.data),
130                    PixelFormat::GrayAlpha => gray_to_grayalpha(&self.data),
131                    PixelFormat::Gray => self.data.clone(),
132                    PixelFormat::Alpha => gray_to_alpha(&self.data),
133                }
134            }
135            PixelFormat::Alpha => {
136                match format {
137                    PixelFormat::RGBA => alpha_to_rgba(&self.data),
138                    PixelFormat::RGB => alpha_to_rgb(&self.data),
139                    PixelFormat::GrayAlpha => alpha_to_grayalpha(&self.data),
140                    PixelFormat::Gray => alpha_to_gray(&self.data),
141                    PixelFormat::Alpha => self.data.clone(),
142                }
143            }
144        };
145        Image {
146            format: format,
147            width: self.width,
148            height: self.height,
149            data: new_data,
150        }
151    }
152}
153
154/// Formats for storing pixel data in an image.
155///
156/// This type determines how the raw data array of an
157/// [`Image`](struct.Image.html) is to be interpreted.
158///
159/// Regardless of format, pixel data for an image is always stored one complete
160/// pixel at a time, in row-major order (that is, the top-left pixel comes
161/// first, followed by the rest of the top row from left to right; then comes
162/// the second row down, again from left to right, and so on until finally the
163/// bottom-right pixel comes last).
164#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
165pub enum PixelFormat {
166    /// 32-bit color with alpha channel.  Each pixel is four bytes, with red
167    /// first and alpha last.
168    RGBA,
169    /// 24-bit color with no alpha.  Each pixel is three bytes, with red
170    /// first and blue last.
171    RGB,
172    /// 16-bit grayscale-with-alpha.  Each pixel is two bytes, with the
173    /// grayscale value first and alpha second.
174    GrayAlpha,
175    /// 8-bit grayscale with no alpha.  Each pixel is one byte (0=black,
176    /// 255=white).
177    Gray,
178    /// 8-bit alpha mask with no color.  Each pixel is one byte (0=transparent,
179    /// 255=opaque).
180    Alpha,
181}
182
183impl PixelFormat {
184    /// Returns the number of bits needed to store a single pixel in this
185    /// format.
186    pub fn bits_per_pixel(self) -> u32 {
187        match self {
188            PixelFormat::RGBA => 32,
189            PixelFormat::RGB => 24,
190            PixelFormat::GrayAlpha => 16,
191            PixelFormat::Gray => 8,
192            PixelFormat::Alpha => 8,
193        }
194    }
195}
196
197/// Converts RGBA image data into RGB.
198fn rgba_to_rgb(rgba: &[u8]) -> Box<[u8]> {
199    assert_eq!(rgba.len() % 4, 0);
200    let num_pixels = rgba.len() / 4;
201    let mut rgb = Vec::with_capacity(num_pixels * 3);
202    for i in 0..num_pixels {
203        rgb.extend_from_slice(&rgba[(4 * i)..(4 * i + 3)]);
204    }
205    rgb.into_boxed_slice()
206}
207
208/// Converts RGB image data into RGBA.
209fn rgb_to_rgba(rgb: &[u8]) -> Box<[u8]> {
210    assert_eq!(rgb.len() % 3, 0);
211    let num_pixels = rgb.len() / 3;
212    let mut rgba = Vec::with_capacity(num_pixels * 4);
213    for i in 0..num_pixels {
214        rgba.extend_from_slice(&rgb[(3 * i)..(3 * i + 3)]);
215        rgba.push(std::u8::MAX);
216    }
217    rgba.into_boxed_slice()
218}
219
220/// Converts RGBA image data into grayscale.
221fn rgba_to_gray(rgba: &[u8]) -> Box<[u8]> {
222    assert_eq!(rgba.len() % 4, 0);
223    let num_pixels = rgba.len() / 4;
224    let mut gray = Vec::with_capacity(num_pixels);
225    for i in 0..num_pixels {
226        let red = u32::from(rgba[4 * i]);
227        let green = u32::from(rgba[4 * i + 1]);
228        let blue = u32::from(rgba[4 * i + 2]);
229        gray.push(((red + green + blue) / 3) as u8);
230    }
231    gray.into_boxed_slice()
232}
233
234/// Converts RGB image data into grayscale.
235fn rgb_to_gray(rgb: &[u8]) -> Box<[u8]> {
236    assert_eq!(rgb.len() % 3, 0);
237    let num_pixels = rgb.len() / 3;
238    let mut gray = Vec::with_capacity(num_pixels);
239    for i in 0..num_pixels {
240        let red = u32::from(rgb[3 * i]);
241        let green = u32::from(rgb[3 * i + 1]);
242        let blue = u32::from(rgb[3 * i + 2]);
243        gray.push(((red + green + blue) / 3) as u8);
244    }
245    gray.into_boxed_slice()
246}
247
248/// Converts RGBA image data into grayscale-with-alpha.
249fn rgba_to_grayalpha(rgba: &[u8]) -> Box<[u8]> {
250    assert_eq!(rgba.len() % 4, 0);
251    let num_pixels = rgba.len() / 4;
252    let mut grayalpha = Vec::with_capacity(num_pixels * 2);
253    for i in 0..num_pixels {
254        let red = u32::from(rgba[4 * i]);
255        let green = u32::from(rgba[4 * i + 1]);
256        let blue = u32::from(rgba[4 * i + 2]);
257        let alpha = rgba[4 * i + 3];
258        grayalpha.push(((red + green + blue) / 3) as u8);
259        grayalpha.push(alpha);
260    }
261    grayalpha.into_boxed_slice()
262}
263
264/// Converts RGB image data into grayscale-with-alpha.
265fn rgb_to_grayalpha(rgb: &[u8]) -> Box<[u8]> {
266    assert_eq!(rgb.len() % 3, 0);
267    let num_pixels = rgb.len() / 3;
268    let mut gray = Vec::with_capacity(num_pixels);
269    for i in 0..num_pixels {
270        let red = u32::from(rgb[3 * i]);
271        let green = u32::from(rgb[3 * i + 1]);
272        let blue = u32::from(rgb[3 * i + 2]);
273        gray.push(((red + green + blue) / 3) as u8);
274        gray.push(std::u8::MAX);
275    }
276    gray.into_boxed_slice()
277}
278
279/// Converts RGBA image data into an alpha mask.
280fn rgba_to_alpha(rgba: &[u8]) -> Box<[u8]> {
281    assert_eq!(rgba.len() % 4, 0);
282    let num_pixels = rgba.len() / 4;
283    let mut alpha = Vec::with_capacity(num_pixels);
284    for i in 0..num_pixels {
285        alpha.push(rgba[4 * i + 3]);
286    }
287    alpha.into_boxed_slice()
288}
289
290/// Converts RGB image data into an alpha mask.
291fn rgb_to_alpha(rgb: &[u8]) -> Box<[u8]> {
292    assert_eq!(rgb.len() % 3, 0);
293    let num_pixels = rgb.len() / 3;
294    vec![std::u8::MAX; num_pixels].into_boxed_slice()
295}
296
297/// Converts grayscale-with-alpha image data into RGBA.
298fn grayalpha_to_rgba(grayalpha: &[u8]) -> Box<[u8]> {
299    assert_eq!(grayalpha.len() % 2, 0);
300    let num_pixels = grayalpha.len() / 2;
301    let mut rgba = Vec::with_capacity(num_pixels * 4);
302    for i in 0..num_pixels {
303        let gray = grayalpha[2 * i];
304        let alpha = grayalpha[2 * i + 1];
305        rgba.push(gray);
306        rgba.push(gray);
307        rgba.push(gray);
308        rgba.push(alpha);
309    }
310    rgba.into_boxed_slice()
311}
312
313/// Converts grayscale-with-alpha image data into RGB.
314fn grayalpha_to_rgb(grayalpha: &[u8]) -> Box<[u8]> {
315    assert_eq!(grayalpha.len() % 2, 0);
316    let num_pixels = grayalpha.len() / 2;
317    let mut rgb = Vec::with_capacity(num_pixels * 3);
318    for i in 0..num_pixels {
319        let gray = grayalpha[2 * i];
320        rgb.push(gray);
321        rgb.push(gray);
322        rgb.push(gray);
323    }
324    rgb.into_boxed_slice()
325}
326
327/// Converts grayscale-with-alpha image data into grayscale-without-alpha.
328fn grayalpha_to_gray(grayalpha: &[u8]) -> Box<[u8]> {
329    assert_eq!(grayalpha.len() % 2, 0);
330    let num_pixels = grayalpha.len() / 2;
331    let mut gray = Vec::with_capacity(num_pixels);
332    for i in 0..num_pixels {
333        let value = grayalpha[2 * i];
334        gray.push(value);
335    }
336    gray.into_boxed_slice()
337}
338
339/// Converts grayscale-with-alpha image data into an alpha mask.
340fn grayalpha_to_alpha(grayalpha: &[u8]) -> Box<[u8]> {
341    assert_eq!(grayalpha.len() % 2, 0);
342    let num_pixels = grayalpha.len() / 2;
343    let mut alpha = Vec::with_capacity(num_pixels);
344    for i in 0..num_pixels {
345        let value = grayalpha[2 * i + 1];
346        alpha.push(value);
347    }
348    alpha.into_boxed_slice()
349}
350
351/// Converts grayscale image data into RGBA.
352fn gray_to_rgba(gray: &[u8]) -> Box<[u8]> {
353    let num_pixels = gray.len();
354    let mut rgba = Vec::with_capacity(num_pixels * 4);
355    for &value in gray {
356        rgba.push(value);
357        rgba.push(value);
358        rgba.push(value);
359        rgba.push(std::u8::MAX);
360    }
361    rgba.into_boxed_slice()
362}
363
364/// Converts grayscale image data into RGB.
365fn gray_to_rgb(gray: &[u8]) -> Box<[u8]> {
366    let num_pixels = gray.len();
367    let mut rgb = Vec::with_capacity(num_pixels * 3);
368    for &value in gray {
369        rgb.push(value);
370        rgb.push(value);
371        rgb.push(value);
372    }
373    rgb.into_boxed_slice()
374}
375
376/// Converts grayscale image data into grayscale-with-alpha.
377fn gray_to_grayalpha(gray: &[u8]) -> Box<[u8]> {
378    let num_pixels = gray.len();
379    let mut grayalpha = Vec::with_capacity(num_pixels * 2);
380    for &value in gray {
381        grayalpha.push(value);
382        grayalpha.push(std::u8::MAX);
383    }
384    grayalpha.into_boxed_slice()
385}
386
387/// Converts grayscale image data into an alpha mask.
388fn gray_to_alpha(gray: &[u8]) -> Box<[u8]> {
389    vec![std::u8::MAX; gray.len()].into_boxed_slice()
390}
391
392/// Converts alpha mask image data into RGBA.
393fn alpha_to_rgba(alpha: &[u8]) -> Box<[u8]> {
394    let num_pixels = alpha.len();
395    let mut rgba = Vec::with_capacity(num_pixels * 4);
396    for &value in alpha {
397        rgba.push(0);
398        rgba.push(0);
399        rgba.push(0);
400        rgba.push(value);
401    }
402    rgba.into_boxed_slice()
403}
404
405/// Converts alpha mask image data into RGB.
406fn alpha_to_rgb(alpha: &[u8]) -> Box<[u8]> {
407    vec![0u8; alpha.len() * 3].into_boxed_slice()
408}
409
410/// Converts alpha mask image data into grayscale-with-alpha.
411fn alpha_to_grayalpha(alpha: &[u8]) -> Box<[u8]> {
412    let num_pixels = alpha.len();
413    let mut grayalpha = Vec::with_capacity(num_pixels * 2);
414    for &value in alpha {
415        grayalpha.push(0);
416        grayalpha.push(value);
417    }
418    grayalpha.into_boxed_slice()
419}
420
421/// Converts alpha mask image data into grayscale.
422fn alpha_to_gray(alpha: &[u8]) -> Box<[u8]> {
423    vec![0u8; alpha.len()].into_boxed_slice()
424}
425
426#[cfg(test)]
427mod tests {
428    use super::*;
429    use std::io::Cursor;
430
431    #[test]
432    fn image_from_data() {
433        let data: Vec<u8> = vec![255, 0, 0, 0, 255, 0, 0, 0, 255, 95, 95, 95];
434        let image = Image::from_data(PixelFormat::RGB, 2, 2, data.clone())
435            .unwrap();
436        assert_eq!(image.data(), &data as &[u8]);
437    }
438
439    #[test]
440    fn image_from_data_wrong_size() {
441        let data: Vec<u8> = vec![1, 2, 3];
442        let result = Image::from_data(PixelFormat::Alpha, 2, 2, data);
443        assert!(result.is_err());
444    }
445
446    #[test]
447    fn alpha_to_gray() {
448        let alpha_data: Vec<u8> = vec![63, 127, 191, 255];
449        let mut alpha_image = Image::new(PixelFormat::Alpha, 2, 2);
450        alpha_image.data_mut().clone_from_slice(&alpha_data);
451        let gray_image = alpha_image.convert_to(PixelFormat::Gray);
452        let gray_data: Vec<u8> = vec![0, 0, 0, 0];
453        assert_eq!(gray_image.data(), &gray_data as &[u8]);
454    }
455
456    #[test]
457    fn alpha_to_grayalpha() {
458        let alpha_data: Vec<u8> = vec![63, 127, 191, 255];
459        let mut alpha_image = Image::new(PixelFormat::Alpha, 2, 2);
460        alpha_image.data_mut().clone_from_slice(&alpha_data);
461        let grayalpha_image = alpha_image.convert_to(PixelFormat::GrayAlpha);
462        let grayalpha_data: Vec<u8> = vec![0, 63, 0, 127, 0, 191, 0, 255];
463        assert_eq!(grayalpha_image.data(), &grayalpha_data as &[u8]);
464    }
465
466    #[test]
467    fn alpha_to_rgb() {
468        let alpha_data: Vec<u8> = vec![63, 127, 191, 255];
469        let mut alpha_image = Image::new(PixelFormat::Alpha, 2, 2);
470        alpha_image.data_mut().clone_from_slice(&alpha_data);
471        let rgb_image = alpha_image.convert_to(PixelFormat::RGB);
472        let rgb_data: Vec<u8> = vec![0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
473        assert_eq!(rgb_image.data(), &rgb_data as &[u8]);
474    }
475
476    #[test]
477    fn alpha_to_rgba() {
478        let alpha_data: Vec<u8> = vec![63, 127, 191, 255];
479        let mut alpha_image = Image::new(PixelFormat::Alpha, 2, 2);
480        alpha_image.data_mut().clone_from_slice(&alpha_data);
481        let rgba_image = alpha_image.convert_to(PixelFormat::RGBA);
482        let rgba_data: Vec<u8> = vec![0, 0, 0, 63, 0, 0, 0, 127, 0, 0, 0,
483                                      191, 0, 0, 0, 255];
484        assert_eq!(rgba_image.data(), &rgba_data as &[u8]);
485    }
486
487    #[test]
488    fn gray_to_alpha() {
489        let gray_data: Vec<u8> = vec![63, 127, 191, 255];
490        let mut gray_image = Image::new(PixelFormat::Gray, 2, 2);
491        gray_image.data_mut().clone_from_slice(&gray_data);
492        let alpha_image = gray_image.convert_to(PixelFormat::Alpha);
493        let alpha_data: Vec<u8> = vec![255, 255, 255, 255];
494        assert_eq!(alpha_image.data(), &alpha_data as &[u8]);
495    }
496
497    #[test]
498    fn gray_to_grayalpha() {
499        let gray_data: Vec<u8> = vec![63, 127, 191, 255];
500        let mut gray_image = Image::new(PixelFormat::Gray, 2, 2);
501        gray_image.data_mut().clone_from_slice(&gray_data);
502        let grayalpha_image = gray_image.convert_to(PixelFormat::GrayAlpha);
503        let grayalpha_data: Vec<u8> = vec![63, 255, 127, 255, 191, 255, 255,
504                                           255];
505        assert_eq!(grayalpha_image.data(), &grayalpha_data as &[u8]);
506    }
507
508    #[test]
509    fn gray_to_rgb() {
510        let gray_data: Vec<u8> = vec![63, 127, 191, 255];
511        let mut gray_image = Image::new(PixelFormat::Gray, 2, 2);
512        gray_image.data_mut().clone_from_slice(&gray_data);
513        let rgb_image = gray_image.convert_to(PixelFormat::RGB);
514        let rgb_data: Vec<u8> = vec![63, 63, 63, 127, 127, 127, 191, 191,
515                                     191, 255, 255, 255];
516        assert_eq!(rgb_image.data(), &rgb_data as &[u8]);
517    }
518
519    #[test]
520    fn gray_to_rgba() {
521        let gray_data: Vec<u8> = vec![63, 127, 191, 255];
522        let mut gray_image = Image::new(PixelFormat::Gray, 2, 2);
523        gray_image.data_mut().clone_from_slice(&gray_data);
524        let rgba_image = gray_image.convert_to(PixelFormat::RGBA);
525        assert_eq!(rgba_image.pixel_format(), PixelFormat::RGBA);
526        assert_eq!(rgba_image.width(), 2);
527        assert_eq!(rgba_image.height(), 2);
528        let rgba_data: Vec<u8> = vec![63, 63, 63, 255, 127, 127, 127, 255,
529                                      191, 191, 191, 255, 255, 255, 255, 255];
530        assert_eq!(rgba_image.data(), &rgba_data as &[u8]);
531    }
532
533    #[test]
534    fn grayalpha_to_alpha() {
535        let grayalpha_data: Vec<u8> = vec![1, 2, 3, 4, 5, 6, 7, 8];
536        let mut grayalpha_image = Image::new(PixelFormat::GrayAlpha, 2, 2);
537        grayalpha_image.data_mut().clone_from_slice(&grayalpha_data);
538        let alpha_image = grayalpha_image.convert_to(PixelFormat::Alpha);
539        let alpha_data: Vec<u8> = vec![2, 4, 6, 8];
540        assert_eq!(alpha_image.data(), &alpha_data as &[u8]);
541    }
542
543    #[test]
544    fn grayalpha_to_gray() {
545        let grayalpha_data: Vec<u8> = vec![1, 2, 3, 4, 5, 6, 7, 8];
546        let mut grayalpha_image = Image::new(PixelFormat::GrayAlpha, 2, 2);
547        grayalpha_image.data_mut().clone_from_slice(&grayalpha_data);
548        let gray_image = grayalpha_image.convert_to(PixelFormat::Gray);
549        let gray_data: Vec<u8> = vec![1, 3, 5, 7];
550        assert_eq!(gray_image.data(), &gray_data as &[u8]);
551    }
552
553    #[test]
554    fn grayalpha_to_rgb() {
555        let grayalpha_data: Vec<u8> = vec![1, 2, 3, 4, 5, 6, 7, 8];
556        let mut grayalpha_image = Image::new(PixelFormat::GrayAlpha, 2, 2);
557        grayalpha_image.data_mut().clone_from_slice(&grayalpha_data);
558        let rgb_image = grayalpha_image.convert_to(PixelFormat::RGB);
559        let rgb_data: Vec<u8> = vec![1, 1, 1, 3, 3, 3, 5, 5, 5, 7, 7, 7];
560        assert_eq!(rgb_image.data(), &rgb_data as &[u8]);
561    }
562
563    #[test]
564    fn grayalpha_to_rgba() {
565        let grayalpha_data: Vec<u8> = vec![1, 2, 3, 4, 5, 6, 7, 8];
566        let mut grayalpha_image = Image::new(PixelFormat::GrayAlpha, 2, 2);
567        grayalpha_image.data_mut().clone_from_slice(&grayalpha_data);
568        let rgba_image = grayalpha_image.convert_to(PixelFormat::RGBA);
569        let rgba_data: Vec<u8> = vec![1, 1, 1, 2, 3, 3, 3, 4, 5, 5, 5, 6, 7,
570                                      7, 7, 8];
571        assert_eq!(rgba_image.data(), &rgba_data as &[u8]);
572    }
573
574    #[test]
575    fn rgb_to_alpha() {
576        let rgb_data: Vec<u8> = vec![30, 0, 0, 0, 60, 0, 0, 0, 90, 40, 40, 40];
577        let mut rgb_image = Image::new(PixelFormat::RGB, 2, 2);
578        rgb_image.data_mut().clone_from_slice(&rgb_data);
579        let alpha_image = rgb_image.convert_to(PixelFormat::Alpha);
580        let alpha_data: Vec<u8> = vec![255, 255, 255, 255];
581        assert_eq!(alpha_image.data(), &alpha_data as &[u8]);
582    }
583
584    #[test]
585    fn rgb_to_gray() {
586        let rgb_data: Vec<u8> = vec![30, 0, 0, 0, 60, 0, 0, 0, 90, 40, 40, 40];
587        let mut rgb_image = Image::new(PixelFormat::RGB, 2, 2);
588        rgb_image.data_mut().clone_from_slice(&rgb_data);
589        let gray_image = rgb_image.convert_to(PixelFormat::Gray);
590        let gray_data: Vec<u8> = vec![10, 20, 30, 40];
591        assert_eq!(gray_image.data(), &gray_data as &[u8]);
592    }
593
594    #[test]
595    fn rgb_to_grayalpha() {
596        let rgb_data: Vec<u8> = vec![30, 0, 0, 0, 60, 0, 0, 0, 90, 40, 40, 40];
597        let mut rgb_image = Image::new(PixelFormat::RGB, 2, 2);
598        rgb_image.data_mut().clone_from_slice(&rgb_data);
599        let grayalpha_image = rgb_image.convert_to(PixelFormat::GrayAlpha);
600        let grayalpha_data: Vec<u8> = vec![10, 255, 20, 255, 30, 255, 40, 255];
601        assert_eq!(grayalpha_image.data(), &grayalpha_data as &[u8]);
602    }
603
604    #[test]
605    fn rgb_to_rgba() {
606        let rgb_data: Vec<u8> = vec![255, 0, 0, 0, 255, 0, 0, 0, 255, 127,
607                                     127, 127];
608        let mut rgb_image = Image::new(PixelFormat::RGB, 2, 2);
609        rgb_image.data_mut().clone_from_slice(&rgb_data);
610        let rgba_image = rgb_image.convert_to(PixelFormat::RGBA);
611        assert_eq!(rgba_image.pixel_format(), PixelFormat::RGBA);
612        assert_eq!(rgba_image.width(), 2);
613        assert_eq!(rgba_image.height(), 2);
614        let rgba_data: Vec<u8> = vec![255, 0, 0, 255, 0, 255, 0, 255, 0, 0,
615                                      255, 255, 127, 127, 127, 255];
616        assert_eq!(rgba_image.data(), &rgba_data as &[u8]);
617    }
618
619    #[test]
620    fn rgba_to_alpha() {
621        let rgba_data: Vec<u8> = vec![30, 0, 0, 200, 0, 60, 0, 150, 0, 0, 90,
622                                      100, 40, 40, 40, 50];
623        let mut rgba_image = Image::new(PixelFormat::RGBA, 2, 2);
624        rgba_image.data_mut().clone_from_slice(&rgba_data);
625        let alpha_image = rgba_image.convert_to(PixelFormat::Alpha);
626        let alpha_data: Vec<u8> = vec![200, 150, 100, 50];
627        assert_eq!(alpha_image.data(), &alpha_data as &[u8]);
628    }
629
630    #[test]
631    fn rgba_to_gray() {
632        let rgba_data: Vec<u8> = vec![30, 0, 0, 200, 0, 60, 0, 150, 0, 0, 90,
633                                      100, 40, 40, 40, 50];
634        let mut rgba_image = Image::new(PixelFormat::RGBA, 2, 2);
635        rgba_image.data_mut().clone_from_slice(&rgba_data);
636        let gray_image = rgba_image.convert_to(PixelFormat::Gray);
637        let gray_data: Vec<u8> = vec![10, 20, 30, 40];
638        assert_eq!(gray_image.data(), &gray_data as &[u8]);
639    }
640
641    #[test]
642    fn rgba_to_grayalpha() {
643        let rgba_data: Vec<u8> = vec![30, 0, 0, 200, 0, 60, 0, 150, 0, 0, 90,
644                                      100, 40, 40, 40, 50];
645        let mut rgba_image = Image::new(PixelFormat::RGBA, 2, 2);
646        rgba_image.data_mut().clone_from_slice(&rgba_data);
647        let grayalpha_image = rgba_image.convert_to(PixelFormat::GrayAlpha);
648        let grayalpha_data: Vec<u8> = vec![10, 200, 20, 150, 30, 100, 40, 50];
649        assert_eq!(grayalpha_image.data(), &grayalpha_data as &[u8]);
650    }
651
652    #[test]
653    fn rgba_to_rgb() {
654        let rgba_data: Vec<u8> = vec![30, 0, 0, 200, 0, 60, 0, 150, 0, 0, 90,
655                                      100, 40, 40, 40, 50];
656        let mut rgba_image = Image::new(PixelFormat::RGBA, 2, 2);
657        rgba_image.data_mut().clone_from_slice(&rgba_data);
658        let rgb_image = rgba_image.convert_to(PixelFormat::RGB);
659        let rgb_data: Vec<u8> = vec![30, 0, 0, 0, 60, 0, 0, 0, 90, 40, 40, 40];
660        assert_eq!(rgb_image.data(), &rgb_data as &[u8]);
661    }
662
663    #[test]
664    #[cfg(feature = "pngio")]
665    fn write_grayscale_png() {
666        let gray_data: Vec<u8> = vec![63, 127, 191, 255];
667        let mut image = Image::new(PixelFormat::Gray, 2, 2);
668        image.data_mut().clone_from_slice(&gray_data);
669        let mut output: Vec<u8> = Vec::new();
670        image.write_png(&mut output).expect("failed to write PNG");
671        let expected: Vec<u8> =
672            vec![137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68,
673                 82, 0, 0, 0, 2, 0, 0, 0, 2, 8, 0, 0, 0, 0, 87, 221, 82, 248,
674                 0, 0, 0, 14, 73, 68, 65, 84, 120, 156, 99, 180, 119, 96,
675                 220, 239, 0, 0, 4, 8, 1, 129, 134, 46, 201, 141, 0, 0, 0, 0,
676                 73, 69, 78, 68, 174, 66, 96, 130];
677        assert_eq!(output, expected);
678    }
679
680    #[test]
681    #[cfg(feature = "pngio")]
682    fn write_rgb_png() {
683        let rgb_data: Vec<u8> = vec![255, 0, 0, 0, 255, 0, 0, 0, 255, 127,
684                                     127, 127];
685        let mut image = Image::new(PixelFormat::RGB, 2, 2);
686        image.data_mut().clone_from_slice(&rgb_data);
687        let mut output: Vec<u8> = Vec::new();
688        image.write_png(&mut output).expect("failed to write PNG");
689        let expected: Vec<u8> =
690            vec![137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68,
691                 82, 0, 0, 0, 2, 0, 0, 0, 2, 8, 2, 0, 0, 0, 253, 212, 154,
692                 115, 0, 0, 0, 20, 73, 68, 65, 84, 120, 156, 99, 252, 207,
693                 192, 0, 196, 140, 12, 12, 255, 235, 235, 27, 0, 29, 14, 4,
694                 127, 253, 15, 140, 153, 0, 0, 0, 0, 73, 69, 78, 68, 174, 66,
695                 96, 130];
696        assert_eq!(output, expected);
697    }
698
699    #[test]
700    #[cfg(feature = "pngio")]
701    fn write_rgba_png() {
702        let rgba_data: Vec<u8> = vec![255, 0, 0, 63, 0, 255, 0, 127, 0, 0,
703                                      255, 191, 127, 127, 127, 255];
704        let mut image = Image::new(PixelFormat::RGBA, 2, 2);
705        image.data_mut().clone_from_slice(&rgba_data);
706        let mut output: Vec<u8> = Vec::new();
707        image.write_png(&mut output).expect("failed to write PNG");
708        let expected: Vec<u8> =
709            vec![137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68,
710                 82, 0, 0, 0, 2, 0, 0, 0, 2, 8, 6, 0, 0, 0, 114, 182, 13, 36,
711                 0, 0, 0, 25, 73, 68, 65, 84, 120, 156, 99, 252, 207, 192,
712                 96, 15, 36, 28, 24, 25, 24, 254, 239, 175, 175, 111, 112, 0,
713                 0, 49, 125, 5, 253, 88, 193, 178, 240, 0, 0, 0, 0, 73, 69,
714                 78, 68, 174, 66, 96, 130];
715        assert_eq!(output, expected);
716    }
717
718    #[test]
719    #[cfg(feature = "pngio")]
720    fn read_rgba_png() {
721        let png: Vec<u8> =
722            vec![137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68,
723                 82, 0, 0, 0, 2, 0, 0, 0, 2, 8, 6, 0, 0, 0, 114, 182, 13, 36,
724                 0, 0, 0, 29, 73, 68, 65, 84, 120, 1, 1, 18, 0, 237, 255, 1,
725                 255, 0, 0, 63, 1, 255, 0, 64, 1, 0, 0, 255, 191, 127, 127,
726                 128, 64, 49, 125, 5, 253, 198, 70, 247, 56, 0, 0, 0, 0, 73,
727                 69, 78, 68, 174, 66, 96, 130];
728        let image = Image::read_png(Cursor::new(&png))
729            .expect("failed to read PNG");
730        assert_eq!(image.pixel_format(), PixelFormat::RGBA);
731        assert_eq!(image.width(), 2);
732        assert_eq!(image.height(), 2);
733        let rgba_data: Vec<u8> = vec![255, 0, 0, 63, 0, 255, 0, 127, 0, 0,
734                                      255, 191, 127, 127, 127, 255];
735        assert_eq!(image.data(), &rgba_data as &[u8]);
736    }
737
738    #[test]
739    #[cfg(feature = "pngio")]
740    fn png_round_trip() {
741        let rgba_data: Vec<u8> = vec![127, 0, 0, 63, 0, 191, 0, 127, 0, 0,
742                                      255, 191, 127, 127, 127, 255];
743        let mut rgba_image = Image::new(PixelFormat::RGBA, 2, 2);
744        rgba_image.data_mut().clone_from_slice(&rgba_data);
745        let pixel_formats = [PixelFormat::RGBA,
746                             PixelFormat::RGB,
747                             PixelFormat::GrayAlpha,
748                             PixelFormat::Gray,
749                             PixelFormat::Alpha];
750        for &format in pixel_formats.iter() {
751            // For each pixel format, try writing a PNG from an image in that
752            // format.
753            let image_1 = rgba_image.convert_to(format);
754            let mut png_data = Vec::<u8>::new();
755            image_1.write_png(&mut png_data).expect("failed to write PNG");
756            // We should be able to read the PNG back in successfully.
757            let mut image_2 = Image::read_png(Cursor::new(&png_data))
758                .expect("failed to read PNG");
759            // We may get the image back in a different pixel format.  However,
760            // in such cases we should be able to convert back to the original
761            // pixel format and still get back exactly the same data.
762            if image_2.pixel_format() != image_1.pixel_format() {
763                image_2 = image_2.convert_to(image_1.pixel_format());
764            }
765            assert_eq!(image_1.data(), image_2.data());
766        }
767    }
768}