Skip to content

Commit 2eef9ac

Browse files
committed
Encoding of extra samples, roundtrip test
1 parent 8517bb8 commit 2eef9ac

File tree

5 files changed

+59
-11
lines changed

5 files changed

+59
-11
lines changed

src/encoder/mod.rs

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -563,9 +563,6 @@ impl<'a, W: 'a + Write + Seek, T: ColorType, K: TiffKind> ImageEncoder<'a, W, T,
563563
encoder.write_tag(Tag::Compression, compression.tag().to_u16())?;
564564
encoder.write_tag(Tag::Predictor, predictor.to_u16())?;
565565

566-
encoder.write_tag(Tag::BitsPerSample, <T>::BITS_PER_SAMPLE)?;
567-
let sample_format: Vec<_> = <T>::SAMPLE_FORMAT.iter().map(|s| s.to_u16()).collect();
568-
encoder.write_tag(Tag::SampleFormat, &sample_format[..])?;
569566
encoder.write_tag(Tag::PhotometricInterpretation, <T>::TIFF_VALUE.to_u16())?;
570567

571568
encoder.write_tag(Tag::RowsPerStrip, u32::try_from(rows_per_strip)?)?;
@@ -754,6 +751,39 @@ impl<'a, W: 'a + Write + Seek, T: ColorType, K: TiffKind> ImageEncoder<'a, W, T,
754751
}
755752

756753
fn finish_internal(&mut self) -> TiffResult<DirectoryOffset<K>> {
754+
if self.extra_samples.is_empty() {
755+
self.encoder
756+
.write_tag(Tag::BitsPerSample, <T>::BITS_PER_SAMPLE)?;
757+
} else {
758+
let mut sample_format: Vec<_> = <T>::BITS_PER_SAMPLE.to_vec();
759+
let replicated =
760+
core::iter::repeat(<T>::BITS_PER_SAMPLE[0]).take(self.extra_samples.len());
761+
sample_format.extend(replicated);
762+
763+
self.encoder
764+
.write_tag(Tag::BitsPerSample, &sample_format[..])?;
765+
766+
self.encoder.write_tag(
767+
Tag::SamplesPerPixel,
768+
u16::try_from(<T>::BITS_PER_SAMPLE.len() + self.extra_samples.len())?,
769+
)?;
770+
}
771+
772+
let mut sample_format: Vec<_> = <T>::SAMPLE_FORMAT.iter().map(|s| s.to_u16()).collect();
773+
let extra_format = sample_format
774+
.first()
775+
.copied()
776+
// Frankly should not occur, we have no sample format without at least one entry. We
777+
// would need an interface upgrade to handle this however. Either decide to support
778+
// heterogeneous sample formats or a way to provide fallback that is used for purely
779+
// extra samples and not provided via a slice used for samples themselves.
780+
.unwrap_or(SampleFormat::Void.to_u16());
781+
782+
sample_format.extend(core::iter::repeat(extra_format).take(self.extra_samples.len()));
783+
784+
self.encoder
785+
.write_tag(Tag::SampleFormat, &sample_format[..])?;
786+
757787
self.encoder
758788
.write_tag(Tag::StripOffsets, K::convert_slice(&self.strip_offsets))?;
759789
self.encoder.write_tag(

tests/decode_images.rs

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -686,19 +686,37 @@ fn test_fax4_white_is_min() {
686686
}
687687

688688
#[test]
689-
fn extra_bits_image() {
689+
fn write_extra_bits_image() {
690690
use tiff::{encoder, tags::ExtraSamples};
691691

692-
let path = PathBuf::from(TEST_IMAGE_DIR).join("extra_bits_gray_4b.tiff");
692+
let path = PathBuf::from(TEST_IMAGE_DIR).join("extra_bits_rgb_8b.tiff");
693693
let img_file = File::create(path).expect("Cannot find test image!");
694694

695695
let mut encoder = encoder::TiffEncoder::new(img_file).expect("Cannot create encoder");
696-
let mut img = encoder
697-
.new_image::<encoder::colortype::Gray8>(8, 8)
698-
.unwrap();
696+
let mut img = encoder.new_image::<encoder::colortype::RGB8>(8, 8).unwrap();
699697

700698
img.extra_samples(&[ExtraSamples::Unspecified]).unwrap();
701699

702-
let data: [u8; 128] = core::array::from_fn(|i| i as u8 % 2);
703-
img.write_data(&data).expect("correct amount of data to write");
700+
// all pixels are supposed to be 0, the extra is 1
701+
let data: [u8; 256] = core::array::from_fn(|i| (i as u8 % 4).saturating_sub(2));
702+
703+
img.write_data(&data)
704+
.expect("correct amount of data to write");
705+
}
706+
707+
#[test]
708+
fn extra_bits_gray() {
709+
test_image_sum_u8(
710+
"extra_bits_gray_8b.tiff",
711+
ColorType::Multiband {
712+
bit_depth: 8,
713+
num_samples: 2,
714+
},
715+
64,
716+
);
717+
}
718+
719+
#[test]
720+
fn extra_bits_rgb() {
721+
test_image_sum_u8("extra_bits_rgb_8b.tiff", ColorType::RGB(8), 0);
704722
}

tests/encode_images.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ fn encode_decode() {
5757
),
5858
(Tag::Compression, ifd::Value::Short(1)),
5959
(Tag::PhotometricInterpretation, ifd::Value::Short(2)),
60-
(Tag::StripOffsets, ifd::Value::Unsigned(47)),
60+
(Tag::StripOffsets, ifd::Value::Unsigned(35)),
6161
(Tag::SamplesPerPixel, ifd::Value::Short(3)),
6262
(Tag::RowsPerStrip, ifd::Value::Unsigned(3334)),
6363
(Tag::StripByteCounts, ifd::Value::Unsigned(30000)),
338 Bytes
Binary file not shown.
482 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)