extern crate tiff; use tiff::decoder::{Decoder, DecodingSampleBuffer}; use tiff::encoder::{colortype, Predictor, TiffEncoder}; use tiff::ColorType; use std::fs::File; use std::io::{Cursor, Seek, SeekFrom}; use std::path::PathBuf; const TEST_IMAGE_DIR: &str = "./tests/images/"; macro_rules! test_predict { ($name:ident, $buffer:ident, $buffer_ty:ty) => { fn $name>( file: &str, expected_type: ColorType, ) { let path = PathBuf::from(TEST_IMAGE_DIR).join(file); let file = File::open(path).expect("Cannot find test image!"); let mut decoder = Decoder::open(file).expect("Cannot create decoder!"); decoder.next_image().unwrap(); assert_eq!(decoder.colortype().unwrap(), expected_type); let image_data = match decoder.read_image().unwrap() { DecodingSampleBuffer::$buffer(res) => res, _ => panic!("Wrong data type"), }; let mut predicted = Vec::with_capacity(image_data.len()); C::horizontal_predict(&image_data, &mut predicted); let sample_size = C::SAMPLE_FORMAT.len(); (0..sample_size).for_each(|i| { assert_eq!(predicted[i], image_data[i]); }); (sample_size..image_data.len()).for_each(|i| { predicted[i] = predicted[i].wrapping_add(predicted[i - sample_size]); assert_eq!(predicted[i], image_data[i]); }); } }; } test_predict!(test_u8_predict, U8, u8); test_predict!(test_i8_predict, I8, i8); test_predict!(test_u16_predict, U16, u16); test_predict!(test_i16_predict, I16, i16); test_predict!(test_u32_predict, U32, u32); test_predict!(test_u64_predict, U64, u64); #[test] fn test_gray_u8_predict() { test_u8_predict::("minisblack-1c-8b.tiff", ColorType::Gray(8)); } #[test] fn test_gray_i8_predict() { test_i8_predict::("minisblack-1c-i8b.tiff", ColorType::Gray(8)); } #[test] fn test_rgb_u8_predict() { test_u8_predict::("rgb-3c-8b.tiff", ColorType::RGB(8)); } #[test] fn test_cmyk_u8_predict() { test_u8_predict::("cmyk-3c-8b.tiff", ColorType::CMYK(8)); } #[test] fn test_gray_u16_predict() { test_u16_predict::("minisblack-1c-16b.tiff", ColorType::Gray(16)); } #[test] fn test_gray_i16_predict() { test_i16_predict::("minisblack-1c-i16b.tiff", ColorType::Gray(16)); } #[test] fn test_rgb_u16_predict() { test_u16_predict::("rgb-3c-16b.tiff", ColorType::RGB(16)); } #[test] fn test_cmyk_u16_predict() { test_u16_predict::("cmyk-3c-16b.tiff", ColorType::CMYK(16)); } #[test] fn test_gray_u32_predict() { test_u32_predict::("gradient-1c-32b.tiff", ColorType::Gray(32)); } #[test] fn test_rgb_u32_predict() { test_u32_predict::("gradient-3c-32b.tiff", ColorType::RGB(32)); } #[test] fn test_gray_u64_predict() { test_u64_predict::("gradient-1c-64b.tiff", ColorType::Gray(64)); } #[test] fn test_rgb_u64_predict() { test_u64_predict::("gradient-3c-64b.tiff", ColorType::RGB(64)); } #[test] fn test_ycbcr_u8_predict() { test_u8_predict::("tiled-jpeg-ycbcr.tif", ColorType::YCbCr(8)); } macro_rules! test_predict_roundtrip { ($name:ident, $buffer:ident, $buffer_ty:ty) => { fn $name>( file: &str, expected_type: ColorType, ) { let path = PathBuf::from(TEST_IMAGE_DIR).join(file); let img_file = File::open(path).expect("Cannot find test image!"); let mut decoder = Decoder::open(img_file).expect("Cannot create decoder"); decoder.next_image().unwrap(); assert_eq!(decoder.colortype().unwrap(), expected_type); let image_data = match decoder.read_image().unwrap() { DecodingSampleBuffer::$buffer(res) => res, _ => panic!("Wrong data type"), }; let mut file = Cursor::new(Vec::new()); { let mut tiff = TiffEncoder::new(&mut file) .unwrap() .with_predictor(Predictor::Horizontal); let (width, height) = decoder.dimensions().unwrap(); tiff.write_image::(width, height, &image_data).unwrap(); } file.seek(SeekFrom::Start(0)).unwrap(); { let mut decoder = Decoder::open(&mut file).unwrap(); decoder.next_image().unwrap(); if let DecodingSampleBuffer::$buffer(img_res) = decoder.read_image().expect("Decoding image failed") { assert_eq!(image_data, img_res); } else { panic!("Wrong data type"); } } } }; } test_predict_roundtrip!(test_u8_predict_roundtrip, U8, u8); test_predict_roundtrip!(test_i8_predict_roundtrip, I8, i8); test_predict_roundtrip!(test_u16_predict_roundtrip, U16, u16); test_predict_roundtrip!(test_i16_predict_roundtrip, I16, i16); test_predict_roundtrip!(test_u32_predict_roundtrip, U32, u32); test_predict_roundtrip!(test_u64_predict_roundtrip, U64, u64); #[test] fn test_gray_u8_predict_roundtrip() { test_u8_predict_roundtrip::("minisblack-1c-8b.tiff", ColorType::Gray(8)); } #[test] fn test_gray_i8_predict_roundtrip() { test_i8_predict_roundtrip::("minisblack-1c-i8b.tiff", ColorType::Gray(8)); } #[test] fn test_rgb_u8_predict_roundtrip() { test_u8_predict_roundtrip::("rgb-3c-8b.tiff", ColorType::RGB(8)); } #[test] fn test_cmyk_u8_predict_roundtrip() { test_u8_predict_roundtrip::("cmyk-3c-8b.tiff", ColorType::CMYK(8)); } #[test] fn test_gray_u16_predict_roundtrip() { test_u16_predict_roundtrip::("minisblack-1c-16b.tiff", ColorType::Gray(16)); } #[test] fn test_gray_i16_predict_roundtrip() { test_i16_predict_roundtrip::( "minisblack-1c-i16b.tiff", ColorType::Gray(16), ); } #[test] fn test_rgb_u16_predict_roundtrip() { test_u16_predict_roundtrip::("rgb-3c-16b.tiff", ColorType::RGB(16)); } #[test] fn test_cmyk_u16_predict_roundtrip() { test_u16_predict_roundtrip::("cmyk-3c-16b.tiff", ColorType::CMYK(16)); } #[test] fn test_gray_u32_predict_roundtrip() { test_u32_predict_roundtrip::("gradient-1c-32b.tiff", ColorType::Gray(32)); } #[test] fn test_rgb_u32_predict_roundtrip() { test_u32_predict_roundtrip::("gradient-3c-32b.tiff", ColorType::RGB(32)); } #[test] fn test_gray_u64_predict_roundtrip() { test_u64_predict_roundtrip::("gradient-1c-64b.tiff", ColorType::Gray(64)); } #[test] fn test_rgb_u64_predict_roundtrip() { test_u64_predict_roundtrip::("gradient-3c-64b.tiff", ColorType::RGB(64)); } #[test] fn test_ycbcr_u8_predict_roundtrip() { test_u8_predict_roundtrip::("tiled-jpeg-ycbcr.tif", ColorType::YCbCr(8)); }