1use std::collections::HashMap;
2use std::io::Read;
3use std::ops::Range;
4
5use bytes::Bytes;
6use num_enum::TryFromPrimitive;
7
8use crate::error::{AsyncTiffError, AsyncTiffResult};
9use crate::geo::{GeoKeyDirectory, GeoKeyTag};
10use crate::reader::{AsyncCursor, AsyncFileReader};
11use crate::tiff::tags::{
12 CompressionMethod, PhotometricInterpretation, PlanarConfiguration, Predictor, ResolutionUnit,
13 SampleFormat, Tag, Type,
14};
15use crate::tiff::{TiffError, Value};
16use crate::tile::Tile;
17
18const DOCUMENT_NAME: u16 = 269;
19
20#[derive(Debug, Clone)]
24pub struct ImageFileDirectories {
25 ifds: Vec<ImageFileDirectory>,
27 }
31
32impl AsRef<[ImageFileDirectory]> for ImageFileDirectories {
33 fn as_ref(&self) -> &[ImageFileDirectory] {
34 &self.ifds
35 }
36}
37
38impl ImageFileDirectories {
39 pub(crate) async fn open(
40 cursor: &mut AsyncCursor,
41 ifd_offset: u64,
42 bigtiff: bool,
43 ) -> AsyncTiffResult<Self> {
44 let mut next_ifd_offset = Some(ifd_offset);
45
46 let mut ifds = vec![];
47 while let Some(offset) = next_ifd_offset {
48 let ifd = ImageFileDirectory::read(cursor, offset, bigtiff).await?;
49 next_ifd_offset = ifd.next_ifd_offset();
50 ifds.push(ifd);
51 }
52
53 Ok(Self { ifds })
54 }
55}
56
57#[allow(dead_code)]
60#[derive(Debug, Clone)]
61pub struct ImageFileDirectory {
62 pub(crate) new_subfile_type: Option<u32>,
63
64 pub(crate) image_width: u32,
66
67 pub(crate) image_height: u32,
69
70 pub(crate) bits_per_sample: Vec<u16>,
71
72 pub(crate) compression: CompressionMethod,
73
74 pub(crate) photometric_interpretation: PhotometricInterpretation,
75
76 pub(crate) document_name: Option<String>,
77
78 pub(crate) image_description: Option<String>,
79
80 pub(crate) strip_offsets: Option<Vec<u64>>,
81
82 pub(crate) orientation: Option<u16>,
83
84 pub(crate) samples_per_pixel: u16,
90
91 pub(crate) rows_per_strip: Option<u32>,
92
93 pub(crate) strip_byte_counts: Option<Vec<u64>>,
94
95 pub(crate) min_sample_value: Option<Vec<u16>>,
96 pub(crate) max_sample_value: Option<Vec<u16>>,
97
98 pub(crate) x_resolution: Option<f64>,
100
101 pub(crate) y_resolution: Option<f64>,
103
104 pub(crate) planar_configuration: PlanarConfiguration,
119
120 pub(crate) resolution_unit: Option<ResolutionUnit>,
121
122 pub(crate) software: Option<String>,
124
125 pub(crate) date_time: Option<String>,
131 pub(crate) artist: Option<String>,
132 pub(crate) host_computer: Option<String>,
133
134 pub(crate) predictor: Option<Predictor>,
135
136 pub(crate) color_map: Option<Vec<u16>>,
156
157 pub(crate) tile_width: Option<u32>,
158 pub(crate) tile_height: Option<u32>,
159
160 pub(crate) tile_offsets: Option<Vec<u64>>,
161 pub(crate) tile_byte_counts: Option<Vec<u64>>,
162
163 pub(crate) extra_samples: Option<Vec<u16>>,
164
165 pub(crate) sample_format: Vec<SampleFormat>,
166
167 pub(crate) jpeg_tables: Option<Bytes>,
168
169 pub(crate) copyright: Option<String>,
170
171 pub(crate) geo_key_directory: Option<GeoKeyDirectory>,
173 pub(crate) model_pixel_scale: Option<Vec<f64>>,
174 pub(crate) model_tiepoint: Option<Vec<f64>>,
175
176 pub(crate) other_tags: HashMap<Tag, Value>,
180
181 pub(crate) next_ifd_offset: Option<u64>,
182}
183
184impl ImageFileDirectory {
185 async fn read(
187 cursor: &mut AsyncCursor,
188 ifd_start: u64,
189 bigtiff: bool,
190 ) -> AsyncTiffResult<Self> {
191 cursor.seek(ifd_start);
192
193 let tag_count = if bigtiff {
194 cursor.read_u64().await?
195 } else {
196 cursor.read_u16().await?.into()
197 };
198 let mut tags = HashMap::with_capacity(tag_count as usize);
199 for _ in 0..tag_count {
200 let (tag_name, tag_value) = read_tag(cursor, bigtiff).await?;
201 tags.insert(tag_name, tag_value);
202 }
203
204 let ifd_entry_byte_size = if bigtiff { 20 } else { 12 };
213 let tag_count_byte_size = if bigtiff { 8 } else { 2 };
215
216 cursor.seek(ifd_start + (ifd_entry_byte_size * tag_count) + tag_count_byte_size);
218
219 let next_ifd_offset = if bigtiff {
220 cursor.read_u64().await?
221 } else {
222 cursor.read_u32().await?.into()
223 };
224
225 let next_ifd_offset = if next_ifd_offset == 0 {
227 None
228 } else {
229 Some(next_ifd_offset)
230 };
231
232 Self::from_tags(tags, next_ifd_offset)
233 }
234
235 fn next_ifd_offset(&self) -> Option<u64> {
236 self.next_ifd_offset
237 }
238
239 fn from_tags(
240 mut tag_data: HashMap<Tag, Value>,
241 next_ifd_offset: Option<u64>,
242 ) -> AsyncTiffResult<Self> {
243 let mut new_subfile_type = None;
244 let mut image_width = None;
245 let mut image_height = None;
246 let mut bits_per_sample = None;
247 let mut compression = None;
248 let mut photometric_interpretation = None;
249 let mut document_name = None;
250 let mut image_description = None;
251 let mut strip_offsets = None;
252 let mut orientation = None;
253 let mut samples_per_pixel = None;
254 let mut rows_per_strip = None;
255 let mut strip_byte_counts = None;
256 let mut min_sample_value = None;
257 let mut max_sample_value = None;
258 let mut x_resolution = None;
259 let mut y_resolution = None;
260 let mut planar_configuration = None;
261 let mut resolution_unit = None;
262 let mut software = None;
263 let mut date_time = None;
264 let mut artist = None;
265 let mut host_computer = None;
266 let mut predictor = None;
267 let mut color_map = None;
268 let mut tile_width = None;
269 let mut tile_height = None;
270 let mut tile_offsets = None;
271 let mut tile_byte_counts = None;
272 let mut extra_samples = None;
273 let mut sample_format = None;
274 let mut jpeg_tables = None;
275 let mut copyright = None;
276 let mut geo_key_directory_data = None;
277 let mut model_pixel_scale = None;
278 let mut model_tiepoint = None;
279 let mut geo_ascii_params: Option<String> = None;
280 let mut geo_double_params: Option<Vec<f64>> = None;
281
282 let mut other_tags = HashMap::new();
283
284 tag_data.drain().try_for_each(|(tag, value)| {
285 match tag {
286 Tag::NewSubfileType => new_subfile_type = Some(value.into_u32()?),
287 Tag::ImageWidth => image_width = Some(value.into_u32()?),
288 Tag::ImageLength => image_height = Some(value.into_u32()?),
289 Tag::BitsPerSample => bits_per_sample = Some(value.into_u16_vec()?),
290 Tag::Compression => {
291 compression = Some(CompressionMethod::from_u16_exhaustive(value.into_u16()?))
292 }
293 Tag::PhotometricInterpretation => {
294 photometric_interpretation =
295 PhotometricInterpretation::from_u16(value.into_u16()?)
296 }
297 Tag::ImageDescription => image_description = Some(value.into_string()?),
298 Tag::StripOffsets => strip_offsets = Some(value.into_u64_vec()?),
299 Tag::Orientation => orientation = Some(value.into_u16()?),
300 Tag::SamplesPerPixel => samples_per_pixel = Some(value.into_u16()?),
301 Tag::RowsPerStrip => rows_per_strip = Some(value.into_u32()?),
302 Tag::StripByteCounts => strip_byte_counts = Some(value.into_u64_vec()?),
303 Tag::MinSampleValue => min_sample_value = Some(value.into_u16_vec()?),
304 Tag::MaxSampleValue => max_sample_value = Some(value.into_u16_vec()?),
305 Tag::XResolution => match value {
306 Value::Rational(n, d) => x_resolution = Some(n as f64 / d as f64),
307 _ => unreachable!("Expected rational type for XResolution."),
308 },
309 Tag::YResolution => match value {
310 Value::Rational(n, d) => y_resolution = Some(n as f64 / d as f64),
311 _ => unreachable!("Expected rational type for YResolution."),
312 },
313 Tag::PlanarConfiguration => {
314 planar_configuration = PlanarConfiguration::from_u16(value.into_u16()?)
315 }
316 Tag::ResolutionUnit => {
317 resolution_unit = ResolutionUnit::from_u16(value.into_u16()?)
318 }
319 Tag::Software => software = Some(value.into_string()?),
320 Tag::DateTime => date_time = Some(value.into_string()?),
321 Tag::Artist => artist = Some(value.into_string()?),
322 Tag::HostComputer => host_computer = Some(value.into_string()?),
323 Tag::Predictor => predictor = Predictor::from_u16(value.into_u16()?),
324 Tag::ColorMap => color_map = Some(value.into_u16_vec()?),
325 Tag::TileWidth => tile_width = Some(value.into_u32()?),
326 Tag::TileLength => tile_height = Some(value.into_u32()?),
327 Tag::TileOffsets => tile_offsets = Some(value.into_u64_vec()?),
328 Tag::TileByteCounts => tile_byte_counts = Some(value.into_u64_vec()?),
329 Tag::ExtraSamples => extra_samples = Some(value.into_u16_vec()?),
330 Tag::SampleFormat => {
331 let values = value.into_u16_vec()?;
332 sample_format = Some(
333 values
334 .into_iter()
335 .map(SampleFormat::from_u16_exhaustive)
336 .collect(),
337 );
338 }
339 Tag::JPEGTables => jpeg_tables = Some(value.into_u8_vec()?.into()),
340 Tag::Copyright => copyright = Some(value.into_string()?),
341
342 Tag::GeoKeyDirectoryTag => geo_key_directory_data = Some(value.into_u16_vec()?),
345 Tag::ModelPixelScaleTag => model_pixel_scale = Some(value.into_f64_vec()?),
346 Tag::ModelTiepointTag => model_tiepoint = Some(value.into_f64_vec()?),
347 Tag::GeoAsciiParamsTag => geo_ascii_params = Some(value.into_string()?),
348 Tag::GeoDoubleParamsTag => geo_double_params = Some(value.into_f64_vec()?),
349 Tag::Unknown(DOCUMENT_NAME) => document_name = Some(value.into_string()?),
352 _ => {
353 other_tags.insert(tag, value);
354 }
355 };
356 Ok::<_, TiffError>(())
357 })?;
358
359 let mut geo_key_directory = None;
360
361 if let Some(data) = geo_key_directory_data {
364 let mut chunks = data.chunks(4);
365
366 let header = chunks
367 .next()
368 .expect("If the geo key directory exists, a header should exist.");
369 let key_directory_version = header[0];
370 assert_eq!(key_directory_version, 1);
371
372 let key_revision = header[1];
373 assert_eq!(key_revision, 1);
374
375 let _key_minor_revision = header[2];
376 let number_of_keys = header[3];
377
378 let mut tags = HashMap::with_capacity(number_of_keys as usize);
379 for _ in 0..number_of_keys {
380 let chunk = chunks
381 .next()
382 .expect("There should be a chunk for each key.");
383
384 let key_id = chunk[0];
385 let tag_name =
386 GeoKeyTag::try_from_primitive(key_id).expect("Unknown GeoKeyTag id: {key_id}");
387
388 let tag_location = chunk[1];
389 let count = chunk[2];
390 let value_offset = chunk[3];
391
392 if tag_location == 0 {
393 tags.insert(tag_name, Value::Short(value_offset));
394 } else if Tag::from_u16_exhaustive(tag_location) == Tag::GeoAsciiParamsTag {
395 let geo_ascii_params = geo_ascii_params
399 .as_ref()
400 .expect("GeoAsciiParamsTag exists but geo_ascii_params does not.");
401 let value_offset = value_offset as usize;
402 let mut s = &geo_ascii_params[value_offset..value_offset + count as usize];
403
404 if s.ends_with('|') {
407 s = &s[0..s.len() - 1];
408 }
409
410 tags.insert(tag_name, Value::Ascii(s.to_string()));
411 } else if Tag::from_u16_exhaustive(tag_location) == Tag::GeoDoubleParamsTag {
412 let geo_double_params = geo_double_params
416 .as_ref()
417 .expect("GeoDoubleParamsTag exists but geo_double_params does not.");
418 let value_offset = value_offset as usize;
419 let value = if count == 1 {
420 Value::Double(geo_double_params[value_offset])
421 } else {
422 let x = geo_double_params[value_offset..value_offset + count as usize]
423 .iter()
424 .map(|val| Value::Double(*val))
425 .collect();
426 Value::List(x)
427 };
428 tags.insert(tag_name, value);
429 }
430 }
431 geo_key_directory = Some(GeoKeyDirectory::from_tags(tags)?);
432 }
433
434 let samples_per_pixel = samples_per_pixel.expect("samples_per_pixel not found");
435 let planar_configuration = if let Some(planar_configuration) = planar_configuration {
436 planar_configuration
437 } else if samples_per_pixel == 1 {
438 PlanarConfiguration::Chunky
441 } else {
442 PlanarConfiguration::Chunky
443 };
444 Ok(Self {
445 new_subfile_type,
446 image_width: image_width.expect("image_width not found"),
447 image_height: image_height.expect("image_height not found"),
448 bits_per_sample: bits_per_sample.expect("bits per sample not found"),
449 compression: compression.unwrap_or(CompressionMethod::None),
452 photometric_interpretation: photometric_interpretation
453 .expect("photometric interpretation not found"),
454 document_name,
455 image_description,
456 strip_offsets,
457 orientation,
458 samples_per_pixel,
459 rows_per_strip,
460 strip_byte_counts,
461 min_sample_value,
462 max_sample_value,
463 x_resolution,
464 y_resolution,
465 planar_configuration,
466 resolution_unit,
467 software,
468 date_time,
469 artist,
470 host_computer,
471 predictor,
472 color_map,
473 tile_width,
474 tile_height,
475 tile_offsets,
476 tile_byte_counts,
477 extra_samples,
478 sample_format: sample_format
481 .unwrap_or(vec![SampleFormat::Uint; samples_per_pixel as _]),
482 copyright,
483 jpeg_tables,
484 geo_key_directory,
485 model_pixel_scale,
486 model_tiepoint,
487 other_tags,
488 next_ifd_offset,
489 })
490 }
491
492 pub fn new_subfile_type(&self) -> Option<u32> {
495 self.new_subfile_type
496 }
497
498 pub fn image_width(&self) -> u32 {
501 self.image_width
502 }
503
504 pub fn image_height(&self) -> u32 {
507 self.image_height
508 }
509
510 pub fn bits_per_sample(&self) -> &[u16] {
513 &self.bits_per_sample
514 }
515
516 pub fn compression(&self) -> CompressionMethod {
519 self.compression
520 }
521
522 pub fn photometric_interpretation(&self) -> PhotometricInterpretation {
525 self.photometric_interpretation
526 }
527
528 pub fn document_name(&self) -> Option<&str> {
530 self.document_name.as_deref()
531 }
532
533 pub fn image_description(&self) -> Option<&str> {
536 self.image_description.as_deref()
537 }
538
539 pub fn strip_offsets(&self) -> Option<&[u64]> {
542 self.strip_offsets.as_deref()
543 }
544
545 pub fn orientation(&self) -> Option<u16> {
548 self.orientation
549 }
550
551 pub fn samples_per_pixel(&self) -> u16 {
557 self.samples_per_pixel
558 }
559
560 pub fn rows_per_strip(&self) -> Option<u32> {
563 self.rows_per_strip
564 }
565
566 pub fn strip_byte_counts(&self) -> Option<&[u64]> {
569 self.strip_byte_counts.as_deref()
570 }
571
572 pub fn min_sample_value(&self) -> Option<&[u16]> {
575 self.min_sample_value.as_deref()
576 }
577
578 pub fn max_sample_value(&self) -> Option<&[u16]> {
581 self.max_sample_value.as_deref()
582 }
583
584 pub fn x_resolution(&self) -> Option<f64> {
587 self.x_resolution
588 }
589
590 pub fn y_resolution(&self) -> Option<f64> {
593 self.y_resolution
594 }
595
596 pub fn planar_configuration(&self) -> PlanarConfiguration {
613 self.planar_configuration
614 }
615
616 pub fn resolution_unit(&self) -> Option<ResolutionUnit> {
619 self.resolution_unit
620 }
621
622 pub fn software(&self) -> Option<&str> {
625 self.software.as_deref()
626 }
627
628 pub fn date_time(&self) -> Option<&str> {
636 self.date_time.as_deref()
637 }
638
639 pub fn artist(&self) -> Option<&str> {
642 self.artist.as_deref()
643 }
644
645 pub fn host_computer(&self) -> Option<&str> {
648 self.host_computer.as_deref()
649 }
650
651 pub fn predictor(&self) -> Option<Predictor> {
655 self.predictor
656 }
657
658 pub fn tile_width(&self) -> Option<u32> {
661 self.tile_width
662 }
663
664 pub fn tile_height(&self) -> Option<u32> {
667 self.tile_height
668 }
669
670 pub fn tile_offsets(&self) -> Option<&[u64]> {
673 self.tile_offsets.as_deref()
674 }
675
676 pub fn tile_byte_counts(&self) -> Option<&[u64]> {
679 self.tile_byte_counts.as_deref()
680 }
681
682 pub fn extra_samples(&self) -> Option<&[u16]> {
685 self.extra_samples.as_deref()
686 }
687
688 pub fn sample_format(&self) -> &[SampleFormat] {
691 &self.sample_format
692 }
693
694 pub fn jpeg_tables(&self) -> Option<&[u8]> {
697 self.jpeg_tables.as_deref()
698 }
699
700 pub fn copyright(&self) -> Option<&str> {
703 self.copyright.as_deref()
704 }
705
706 pub fn geo_key_directory(&self) -> Option<&GeoKeyDirectory> {
709 self.geo_key_directory.as_ref()
710 }
711
712 pub fn model_pixel_scale(&self) -> Option<&[f64]> {
715 self.model_pixel_scale.as_deref()
716 }
717
718 pub fn model_tiepoint(&self) -> Option<&[f64]> {
721 self.model_tiepoint.as_deref()
722 }
723
724 pub fn colormap(&self) -> Option<HashMap<usize, [u8; 3]>> {
726 fn cmap_transform(val: u16) -> u8 {
727 let val = ((val as f64 / 65535.0) * 255.0).floor();
728 if val >= 255.0 {
729 255
730 } else if val < 0.0 {
731 0
732 } else {
733 val as u8
734 }
735 }
736
737 if let Some(cmap_data) = &self.color_map {
738 let bits_per_sample = self.bits_per_sample[0];
739 let count = 2_usize.pow(bits_per_sample as u32);
740 let mut result = HashMap::new();
741
742 for idx in 0..count {
744 let color: [u8; 3] =
745 std::array::from_fn(|i| cmap_transform(cmap_data[idx + i * count]));
746 result.insert(idx, color);
749 }
750
751 Some(result)
752 } else {
753 None
754 }
755 }
756
757 fn get_tile_byte_range(&self, x: usize, y: usize) -> Option<Range<u64>> {
758 let tile_offsets = self.tile_offsets.as_deref()?;
759 let tile_byte_counts = self.tile_byte_counts.as_deref()?;
760 let idx = (y * self.tile_count()?.0) + x;
761 let offset = tile_offsets[idx] as usize;
762 let byte_count = tile_byte_counts[idx] as usize;
764 Some(offset as _..(offset + byte_count) as _)
765 }
766
767 pub async fn fetch_tile(
769 &self,
770 x: usize,
771 y: usize,
772 reader: &dyn AsyncFileReader,
773 ) -> AsyncTiffResult<Tile> {
774 let range = self
775 .get_tile_byte_range(x, y)
776 .ok_or(AsyncTiffError::General("Not a tiled TIFF".to_string()))?;
777 let compressed_bytes = reader.get_bytes(range).await?;
778 Ok(Tile {
779 x,
780 y,
781 compressed_bytes,
782 compression_method: self.compression,
783 photometric_interpretation: self.photometric_interpretation,
784 jpeg_tables: self.jpeg_tables.clone(),
785 })
786 }
787
788 pub async fn fetch_tiles(
790 &self,
791 x: &[usize],
792 y: &[usize],
793 reader: &dyn AsyncFileReader,
794 ) -> AsyncTiffResult<Vec<Tile>> {
795 assert_eq!(x.len(), y.len(), "x and y should have same len");
796
797 let byte_ranges = x
799 .iter()
800 .zip(y)
801 .map(|(x, y)| {
802 self.get_tile_byte_range(*x, *y)
803 .ok_or(AsyncTiffError::General("Not a tiled TIFF".to_string()))
804 })
805 .collect::<AsyncTiffResult<Vec<_>>>()?;
806
807 let buffers = reader.get_byte_ranges(byte_ranges).await?;
809
810 let mut tiles = vec![];
812 for ((compressed_bytes, &x), &y) in buffers.into_iter().zip(x).zip(y) {
813 let tile = Tile {
814 x,
815 y,
816 compressed_bytes,
817 compression_method: self.compression,
818 photometric_interpretation: self.photometric_interpretation,
819 jpeg_tables: self.jpeg_tables.clone(),
820 };
821 tiles.push(tile);
822 }
823 Ok(tiles)
824 }
825
826 pub fn tile_count(&self) -> Option<(usize, usize)> {
829 let x_count = (self.image_width as f64 / self.tile_width? as f64).ceil();
830 let y_count = (self.image_height as f64 / self.tile_height? as f64).ceil();
831 Some((x_count as usize, y_count as usize))
832 }
833}
834
835async fn read_tag(cursor: &mut AsyncCursor, bigtiff: bool) -> AsyncTiffResult<(Tag, Value)> {
837 let start_cursor_position = cursor.position();
838
839 let tag_name = Tag::from_u16_exhaustive(cursor.read_u16().await?);
840
841 let tag_type_code = cursor.read_u16().await?;
842 let tag_type = Type::from_u16(tag_type_code).expect(
843 "Unknown tag type {tag_type_code}. TODO: we should skip entries with unknown tag types.",
844 );
845 let count = if bigtiff {
846 cursor.read_u64().await?
847 } else {
848 cursor.read_u32().await?.into()
849 };
850
851 let tag_value = read_tag_value(cursor, tag_type, count, bigtiff).await?;
852
853 let ifd_entry_size = if bigtiff { 20 } else { 12 };
855 cursor.seek(start_cursor_position + ifd_entry_size);
856
857 Ok((tag_name, tag_value))
858}
859
860async fn read_tag_value(
866 cursor: &mut AsyncCursor,
867 tag_type: Type,
868 count: u64,
869 bigtiff: bool,
870) -> AsyncTiffResult<Value> {
871 if count == 0 {
873 return Ok(Value::List(vec![]));
874 }
875
876 let tag_size = match tag_type {
877 Type::BYTE | Type::SBYTE | Type::ASCII | Type::UNDEFINED => 1,
878 Type::SHORT | Type::SSHORT => 2,
879 Type::LONG | Type::SLONG | Type::FLOAT | Type::IFD => 4,
880 Type::LONG8
881 | Type::SLONG8
882 | Type::DOUBLE
883 | Type::RATIONAL
884 | Type::SRATIONAL
885 | Type::IFD8 => 8,
886 };
887
888 let value_byte_length = count.checked_mul(tag_size).unwrap();
889
890 if count == 1 {
892 if bigtiff && value_byte_length > 4 && value_byte_length <= 8 {
894 let mut data = cursor.read(value_byte_length).await?;
895
896 return Ok(match tag_type {
897 Type::LONG8 => Value::UnsignedBig(data.read_u64()?),
898 Type::SLONG8 => Value::SignedBig(data.read_i64()?),
899 Type::DOUBLE => Value::Double(data.read_f64()?),
900 Type::RATIONAL => Value::Rational(data.read_u32()?, data.read_u32()?),
901 Type::SRATIONAL => Value::SRational(data.read_i32()?, data.read_i32()?),
902 Type::IFD8 => Value::IfdBig(data.read_u64()?),
903 Type::BYTE
904 | Type::SBYTE
905 | Type::ASCII
906 | Type::UNDEFINED
907 | Type::SHORT
908 | Type::SSHORT
909 | Type::LONG
910 | Type::SLONG
911 | Type::FLOAT
912 | Type::IFD => unreachable!(),
913 });
914 }
915
916 let mut data = cursor.read(value_byte_length).await?;
920
921 return Ok(match tag_type {
923 Type::BYTE | Type::UNDEFINED => Value::Byte(data.read_u8()?),
924 Type::SBYTE => Value::Signed(data.read_i8()? as i32),
925 Type::SHORT => Value::Short(data.read_u16()?),
926 Type::SSHORT => Value::Signed(data.read_i16()? as i32),
927 Type::LONG => Value::Unsigned(data.read_u32()?),
928 Type::SLONG => Value::Signed(data.read_i32()?),
929 Type::FLOAT => Value::Float(data.read_f32()?),
930 Type::ASCII => {
931 if data.as_ref()[0] == 0 {
932 Value::Ascii("".to_string())
933 } else {
934 panic!("Invalid tag");
935 }
937 }
938 Type::LONG8 => {
939 let offset = data.read_u32()?;
940 cursor.seek(offset as _);
941 Value::UnsignedBig(cursor.read_u64().await?)
942 }
943 Type::SLONG8 => {
944 let offset = data.read_u32()?;
945 cursor.seek(offset as _);
946 Value::SignedBig(cursor.read_i64().await?)
947 }
948 Type::DOUBLE => {
949 let offset = data.read_u32()?;
950 cursor.seek(offset as _);
951 Value::Double(cursor.read_f64().await?)
952 }
953 Type::RATIONAL => {
954 let offset = data.read_u32()?;
955 cursor.seek(offset as _);
956 let numerator = cursor.read_u32().await?;
957 let denominator = cursor.read_u32().await?;
958 Value::Rational(numerator, denominator)
959 }
960 Type::SRATIONAL => {
961 let offset = data.read_u32()?;
962 cursor.seek(offset as _);
963 let numerator = cursor.read_i32().await?;
964 let denominator = cursor.read_i32().await?;
965 Value::SRational(numerator, denominator)
966 }
967 Type::IFD => Value::Ifd(data.read_u32()?),
968 Type::IFD8 => {
969 let offset = data.read_u32()?;
970 cursor.seek(offset as _);
971 Value::IfdBig(cursor.read_u64().await?)
972 }
973 });
974 }
975
976 if value_byte_length <= 4 || bigtiff && value_byte_length <= 8 {
978 let mut data = cursor.read(value_byte_length).await?;
979 if bigtiff {
980 cursor.advance(8 - value_byte_length);
981 } else {
982 cursor.advance(4 - value_byte_length);
983 }
984
985 match tag_type {
986 Type::BYTE | Type::UNDEFINED => {
987 return {
988 Ok(Value::List(
989 (0..count)
990 .map(|_| Value::Byte(data.read_u8().unwrap()))
991 .collect(),
992 ))
993 };
994 }
995 Type::SBYTE => {
996 return {
997 Ok(Value::List(
998 (0..count)
999 .map(|_| Value::Signed(data.read_i8().unwrap() as i32))
1000 .collect(),
1001 ))
1002 }
1003 }
1004 Type::ASCII => {
1005 let mut buf = vec![0; count as usize];
1006 data.read_exact(&mut buf)?;
1007 if buf.is_ascii() && buf.ends_with(&[0]) {
1008 let v = std::str::from_utf8(&buf)
1009 .map_err(|err| AsyncTiffError::General(err.to_string()))?;
1010 let v = v.trim_matches(char::from(0));
1011 return Ok(Value::Ascii(v.into()));
1012 } else {
1013 panic!("Invalid tag");
1014 }
1016 }
1017 Type::SHORT => {
1018 let mut v = Vec::new();
1019 for _ in 0..count {
1020 v.push(Value::Short(data.read_u16()?));
1021 }
1022 return Ok(Value::List(v));
1023 }
1024 Type::SSHORT => {
1025 let mut v = Vec::new();
1026 for _ in 0..count {
1027 v.push(Value::Signed(i32::from(data.read_i16()?)));
1028 }
1029 return Ok(Value::List(v));
1030 }
1031 Type::LONG => {
1032 let mut v = Vec::new();
1033 for _ in 0..count {
1034 v.push(Value::Unsigned(data.read_u32()?));
1035 }
1036 return Ok(Value::List(v));
1037 }
1038 Type::SLONG => {
1039 let mut v = Vec::new();
1040 for _ in 0..count {
1041 v.push(Value::Signed(data.read_i32()?));
1042 }
1043 return Ok(Value::List(v));
1044 }
1045 Type::FLOAT => {
1046 let mut v = Vec::new();
1047 for _ in 0..count {
1048 v.push(Value::Float(data.read_f32()?));
1049 }
1050 return Ok(Value::List(v));
1051 }
1052 Type::IFD => {
1053 let mut v = Vec::new();
1054 for _ in 0..count {
1055 v.push(Value::Ifd(data.read_u32()?));
1056 }
1057 return Ok(Value::List(v));
1058 }
1059 Type::LONG8
1060 | Type::SLONG8
1061 | Type::RATIONAL
1062 | Type::SRATIONAL
1063 | Type::DOUBLE
1064 | Type::IFD8 => {
1065 unreachable!()
1066 }
1067 }
1068 }
1069
1070 let offset = if bigtiff {
1072 cursor.read_u64().await?
1073 } else {
1074 cursor.read_u32().await?.into()
1075 };
1076 cursor.seek(offset);
1077
1078 match tag_type {
1080 Type::BYTE | Type::UNDEFINED => {
1083 let mut v = Vec::with_capacity(count as _);
1084 for _ in 0..count {
1085 v.push(Value::Byte(cursor.read_u8().await?))
1086 }
1087 Ok(Value::List(v))
1088 }
1089 Type::SBYTE => {
1090 let mut v = Vec::with_capacity(count as _);
1091 for _ in 0..count {
1092 v.push(Value::Signed(cursor.read_i8().await? as i32))
1093 }
1094 Ok(Value::List(v))
1095 }
1096 Type::SHORT => {
1097 let mut v = Vec::with_capacity(count as _);
1098 for _ in 0..count {
1099 v.push(Value::Short(cursor.read_u16().await?))
1100 }
1101 Ok(Value::List(v))
1102 }
1103 Type::SSHORT => {
1104 let mut v = Vec::with_capacity(count as _);
1105 for _ in 0..count {
1106 v.push(Value::Signed(cursor.read_i16().await? as i32))
1107 }
1108 Ok(Value::List(v))
1109 }
1110 Type::LONG => {
1111 let mut v = Vec::with_capacity(count as _);
1112 for _ in 0..count {
1113 v.push(Value::Unsigned(cursor.read_u32().await?))
1114 }
1115 Ok(Value::List(v))
1116 }
1117 Type::SLONG => {
1118 let mut v = Vec::with_capacity(count as _);
1119 for _ in 0..count {
1120 v.push(Value::Signed(cursor.read_i32().await?))
1121 }
1122 Ok(Value::List(v))
1123 }
1124 Type::FLOAT => {
1125 let mut v = Vec::with_capacity(count as _);
1126 for _ in 0..count {
1127 v.push(Value::Float(cursor.read_f32().await?))
1128 }
1129 Ok(Value::List(v))
1130 }
1131 Type::DOUBLE => {
1132 let mut v = Vec::with_capacity(count as _);
1133 for _ in 0..count {
1134 v.push(Value::Double(cursor.read_f64().await?))
1135 }
1136 Ok(Value::List(v))
1137 }
1138 Type::RATIONAL => {
1139 let mut v = Vec::with_capacity(count as _);
1140 for _ in 0..count {
1141 v.push(Value::Rational(
1142 cursor.read_u32().await?,
1143 cursor.read_u32().await?,
1144 ))
1145 }
1146 Ok(Value::List(v))
1147 }
1148 Type::SRATIONAL => {
1149 let mut v = Vec::with_capacity(count as _);
1150 for _ in 0..count {
1151 v.push(Value::SRational(
1152 cursor.read_i32().await?,
1153 cursor.read_i32().await?,
1154 ))
1155 }
1156 Ok(Value::List(v))
1157 }
1158 Type::LONG8 => {
1159 let mut v = Vec::with_capacity(count as _);
1160 for _ in 0..count {
1161 v.push(Value::UnsignedBig(cursor.read_u64().await?))
1162 }
1163 Ok(Value::List(v))
1164 }
1165 Type::SLONG8 => {
1166 let mut v = Vec::with_capacity(count as _);
1167 for _ in 0..count {
1168 v.push(Value::SignedBig(cursor.read_i64().await?))
1169 }
1170 Ok(Value::List(v))
1171 }
1172 Type::IFD => {
1173 let mut v = Vec::with_capacity(count as _);
1174 for _ in 0..count {
1175 v.push(Value::Ifd(cursor.read_u32().await?))
1176 }
1177 Ok(Value::List(v))
1178 }
1179 Type::IFD8 => {
1180 let mut v = Vec::with_capacity(count as _);
1181 for _ in 0..count {
1182 v.push(Value::IfdBig(cursor.read_u64().await?))
1183 }
1184 Ok(Value::List(v))
1185 }
1186 Type::ASCII => {
1187 let mut out = vec![0; count as _];
1188 let mut buf = cursor.read(count).await?;
1189 buf.read_exact(&mut out)?;
1190
1191 if let Some(first) = out.iter().position(|&b| b == 0) {
1193 out.truncate(first);
1194 }
1195 Ok(Value::Ascii(
1196 String::from_utf8(out).map_err(|err| AsyncTiffError::General(err.to_string()))?,
1197 ))
1198 }
1199 }
1200}