1use std;
2use std::io;
3
4#[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 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 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 pub fn pixel_format(&self) -> PixelFormat {
64 self.format
65 }
66
67 pub fn width(&self) -> u32 {
69 self.width
70 }
71
72 pub fn height(&self) -> u32 {
74 self.height
75 }
76
77 pub fn data(&self) -> &[u8] {
79 &self.data
80 }
81
82 pub fn data_mut(&mut self) -> &mut [u8] {
84 &mut self.data
85 }
86
87 pub fn into_data(self) -> Box<[u8]> {
89 self.data
90 }
91
92 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#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
165pub enum PixelFormat {
166 RGBA,
169 RGB,
172 GrayAlpha,
175 Gray,
178 Alpha,
181}
182
183impl PixelFormat {
184 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
197fn 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
208fn 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
220fn 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
234fn 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
248fn 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
264fn 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
279fn 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
290fn 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
297fn 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
313fn 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
327fn 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
339fn 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
351fn 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
364fn 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
376fn 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
387fn gray_to_alpha(gray: &[u8]) -> Box<[u8]> {
389 vec![std::u8::MAX; gray.len()].into_boxed_slice()
390}
391
392fn 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
405fn alpha_to_rgb(alpha: &[u8]) -> Box<[u8]> {
407 vec![0u8; alpha.len() * 3].into_boxed_slice()
408}
409
410fn 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
421fn 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 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 let mut image_2 = Image::read_png(Cursor::new(&png_data))
758 .expect("failed to read PNG");
759 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}