Add ColorType::Multiband enum variant to support samples>1 per pixel (#224)

Co-authored-by: tromper <scott@hopkinsunderground.com>
This commit is contained in:
Wei Jiandtromper authored and GitHub committed 2024-03-24 15:04:52 -07:00
1 parent 90ae5b8e54
commit 0c54a18e21
4 files changed
+94 -10

No files matched your search

+28 -10
View File
@@ -346,14 +346,19 @@ impl Image {
), ),
)), )),
}, },
PhotometricInterpretation::BlackIsZero | PhotometricInterpretation::WhiteIsZero PhotometricInterpretation::BlackIsZero | PhotometricInterpretation::WhiteIsZero => {
if self.samples == 1 => match self.samples {
{ 1 => Ok(ColorType::Gray(self.bits_per_sample)),
Ok(ColorType::Gray(self.bits_per_sample)) _ => Ok(ColorType::Multiband {
bit_depth: self.bits_per_sample,
num_samples: self.samples,
}),
}
} }
// TODO: this is bad we should not fail at this point // TODO: this is bad we should not fail at this point
_ => Err(TiffError::UnsupportedError( PhotometricInterpretation::RGBPalette
| PhotometricInterpretation::TransparencyMask
| PhotometricInterpretation::CIELab => Err(TiffError::UnsupportedError(
TiffUnsupportedError::InterpretationWithBits( TiffUnsupportedError::InterpretationWithBits(
self.photometric_interpretation, self.photometric_interpretation,
vec![self.bits_per_sample; self.samples as usize], vec![self.bits_per_sample; self.samples as usize],
@@ -555,13 +560,26 @@ impl Image {
| (ColorType::CMYK(n), _) | (ColorType::CMYK(n), _)
| (ColorType::YCbCr(n), _) | (ColorType::YCbCr(n), _)
| (ColorType::Gray(n), _) | (ColorType::Gray(n), _)
if usize::from(n) == buffer.byte_len() * 8 => {} | (
(ColorType::Gray(n), DecodingBuffer::U8(_)) if n < 8 => match self.predictor { ColorType::Multiband {
bit_depth: n,
num_samples: _,
},
_,
) if usize::from(n) == buffer.byte_len() * 8 => {}
(
ColorType::Gray(n)
| ColorType::Multiband {
bit_depth: n,
num_samples: _,
},
DecodingBuffer::U8(_),
) if n < 8 => match self.predictor {
Predictor::None => {} Predictor::None => {}
Predictor::Horizontal => { Predictor::Horizontal => {
return Err(TiffError::UnsupportedError( return Err(TiffError::UnsupportedError(
TiffUnsupportedError::HorizontalPredictor(color_type), TiffUnsupportedError::HorizontalPredictor(color_type),
)) ));
} }
Predictor::FloatingPoint => { Predictor::FloatingPoint => {
return Err(TiffError::UnsupportedError( return Err(TiffError::UnsupportedError(
@@ -572,7 +590,7 @@ impl Image {
(type_, _) => { (type_, _) => {
return Err(TiffError::UnsupportedError( return Err(TiffError::UnsupportedError(
TiffUnsupportedError::UnsupportedColorType(type_), TiffUnsupportedError::UnsupportedColorType(type_),
)) ));
} }
} }
+3
View File
@@ -40,4 +40,7 @@ pub enum ColorType {
/// Pixel is YCbCr /// Pixel is YCbCr
YCbCr(u8), YCbCr(u8),
/// Pixel has multiple bands/channels
Multiband { bit_depth: u8, num_samples: u16 },
} }
+63
View File
@@ -0,0 +1,63 @@
extern crate tiff;
use tiff::decoder::{Decoder, DecodingResult};
use tiff::tags::Tag;
use tiff::ColorType;
use std::fs::File;
use std::path::PathBuf;
const TEST_IMAGE_DIR: &str = "./tests/images";
#[test]
fn test_geo_tiff() {
let filenames = ["geo-5b.tif"];
for filename in filenames.iter() {
let path = PathBuf::from(TEST_IMAGE_DIR).join(filename);
let img_file = File::open(path).expect("Cannot find test image!");
let mut decoder = Decoder::new(img_file).expect("Cannot create decoder");
decoder = decoder.with_limits(tiff::decoder::Limits::unlimited());
assert_eq!(
decoder.dimensions().expect("Cannot get dimensions"),
(10, 10)
);
assert_eq!(
decoder.colortype().expect("Cannot get colortype"),
ColorType::Multiband {
bit_depth: 16,
num_samples: 5
}
);
assert_eq!(
decoder
.get_tag_u64(Tag::StripOffsets)
.expect("Cannot get StripOffsets"),
418
);
assert_eq!(
decoder
.get_tag_u64(Tag::RowsPerStrip)
.expect("Cannot get RowsPerStrip"),
10
);
assert_eq!(
decoder
.get_tag_u64(Tag::StripByteCounts)
.expect("Cannot get StripByteCounts"),
1000
);
assert_eq!(
decoder
.get_tag(Tag::ModelPixelScaleTag)
.expect("Cannot get pixel scale")
.into_f64_vec()
.expect("Cannot get pixel scale"),
vec![60.0, 60.0, 0.0]
);
let DecodingResult::I16(data) = decoder.read_image().unwrap() else {
panic!("Cannot read band data")
};
assert_eq!(data.len(), 500);
}
}
Binary file not shown.