From 3953bd31e14185cd5d7726eda2556623ee73cf0e Mon Sep 17 00:00:00 2001 From: ruffson Date: Sat, 17 Oct 2020 11:27:41 +0200 Subject: [PATCH 1/9] Read out short vecs and ascii from ifds --- src/decoder/ifd.rs | 42 ++++++++++++++++++++++++++++++++++++++++-- src/decoder/mod.rs | 9 +++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/src/decoder/ifd.rs b/src/decoder/ifd.rs index 2100833..edfa054 100644 --- a/src/decoder/ifd.rs +++ b/src/decoder/ifd.rs @@ -10,14 +10,15 @@ use crate::tags::{Tag, Type}; use crate::{TiffError, TiffFormatError, TiffResult, TiffUnsupportedError}; use self::Value::{ - Ascii, Byte, Double, Float, List, Rational, RationalBig, SRational, SRationalBig, Signed, - SignedBig, Unsigned, UnsignedBig, + Ascii, Byte, Double, Float, List, Rational, RationalBig, SRational, SRationalBig, Short, + Signed, SignedBig, Unsigned, UnsignedBig, }; #[allow(unused_qualifications)] #[derive(Debug, Clone, PartialEq)] pub enum Value { Byte(u8), + Short(u16), Signed(i32), SignedBig(i64), Unsigned(u32), @@ -42,6 +43,17 @@ impl Value { } } + pub fn into_u16(self) -> TiffResult { + match self { + Short(val) => Ok(val), + Unsigned(val) => Ok(u16::try_from(val)?), + UnsignedBig(val) => Ok(u16::try_from(val)?), + val => Err(TiffError::FormatError( + TiffFormatError::UnsignedIntegerExpected(val), + )), + } + } + pub fn into_u32(self) -> TiffResult { match self { Unsigned(val) => Ok(val), @@ -100,6 +112,15 @@ impl Value { } } + pub fn into_string(self) -> TiffResult { + match self { + Ascii(val) => Ok(val), + val => Err(TiffError::FormatError( + TiffFormatError::SignedIntegerExpected(val), + )), + } + } + pub fn into_u32_vec(self) -> TiffResult> { match self { List(vec) => { @@ -139,6 +160,22 @@ impl Value { } } + pub fn into_u16_vec(self) -> TiffResult> { + match self { + List(vec) => { + let mut new_vec = Vec::with_capacity(vec.len()); + for v in vec { + new_vec.push(v.into_u16()?) + } + Ok(new_vec) + } + Short(val) => Ok(vec![val]), + val => Err(TiffError::FormatError( + TiffFormatError::UnsignedIntegerExpected(val), + )), + } + } + pub fn into_i32_vec(self) -> TiffResult> { match self { List(vec) => { @@ -400,6 +437,7 @@ impl Entry { Signed(i32::from(r.read_i16()?)), ])) } + (Type::SHORT, 16) => Ok(Short(u16::from(decoder.read_short()?))), (Type::SHORT, n) => self.decode_offset(n, bo, limits, decoder, |decoder| { Ok(UnsignedBig(u64::from(decoder.read_short()?))) }), diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index 4105b89..5b99382 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -728,6 +728,10 @@ impl Decoder { pub fn get_tag_u32_vec(&mut self, tag: Tag) -> TiffResult> { self.get_tag(tag)?.into_u32_vec() } + + pub fn get_tag_u16_vec(&mut self, tag: Tag) -> TiffResult> { + self.get_tag(tag)?.into_u16_vec() + } pub fn get_tag_u64_vec(&mut self, tag: Tag) -> TiffResult> { self.get_tag(tag)?.into_u64_vec() } @@ -747,6 +751,11 @@ impl Decoder { self.get_tag(tag)?.into_u8_vec() } + /// Tries to retrieve a tag and convert it to a ascii vector. + pub fn get_tag_ascii_string(&mut self, tag: Tag) -> TiffResult { + self.get_tag(tag)?.into_string() + } + /// Decompresses the strip into the supplied buffer. /// Returns the number of bytes read. fn expand_strip<'a>( From 62a1a500a5f576a9efa45ab80c543f0466457a36 Mon Sep 17 00:00:00 2001 From: ruffson Date: Sat, 17 Oct 2020 11:35:05 +0200 Subject: [PATCH 2/9] Add support for GeoTiff geokey dir --- src/decoder/mod.rs | 11 +++ src/geo.rs | 195 +++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + src/tags.rs | 8 ++ 4 files changed, 215 insertions(+) create mode 100644 src/geo.rs diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index 5b99382..4888763 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -13,6 +13,7 @@ use crate::tags::{ use self::stream::{ ByteOrder, DeflateReader, EndianReader, JpegReader, LZWReader, PackBitsReader, SmartReader, }; +use geo; pub mod ifd; mod stream; @@ -472,6 +473,16 @@ impl Decoder { } _ => return Err(TiffUnsupportedError::UnsupportedSampleDepth(self.samples).into()), } + + match self.get_tag_u16_vec(Tag::GeoKeyDirectoryTag) { + Ok(geodir) => { + let ascii_params = Result::ok(self.get_tag_ascii_string(Tag::GeoAsciiParamsTag)); + let double_params = Result::ok(self.get_tag_f64_vec(Tag::GeoDoubleParamsTag)); + geo::parse_geo_keys(geodir, ascii_params, double_params); + } + Err(_) => {} + } + Ok(()) } diff --git a/src/geo.rs b/src/geo.rs new file mode 100644 index 0000000..1ac9907 --- /dev/null +++ b/src/geo.rs @@ -0,0 +1,195 @@ +use std::{collections::HashMap, convert::TryFrom}; +// use tags::Tag; + +macro_rules! enum_try_from { + {#[$enum_attr:meta] $vis:vis enum $tyname:ident { $($name:ident = $value:expr),* $(,)* }} => { + #[$enum_attr] + $vis enum $tyname { + $($name = $value,)* + } + + impl ::std::convert::TryFrom for $tyname { + type Error = (); + /// Get enum key for value + fn try_from(num: usize) -> Result { + $( + if num == $value { + Ok($tyname::$name) + } else + )* { + Err(()) + } + } + } + }; +} + +// More info about geotiff keys can be found +// [here](http://geotiff.maptools.org/spec/geotiff2.7.html) +enum_try_from! { + #[derive(Debug, PartialEq, Eq, Hash)] + pub enum GeoKey { + // GeoTIFF Configuration GeoKeys + GTModelTypeGeoKey = 1024, + GTRasterTypeGeoKey = 1025, + GTCitationGeoKey = 1026, + // Geographic CS Parameter GeoKeys + GeographicTypeGeoKey = 2048, + GeogCitationGeoKey = 2049, + GeogGeodeticDatumGeoKey = 2050, + GeogPrimeMeridianGeoKey = 2051, + GeogLinearUnitsGeoKey = 2052, + GeogLinearUnitSizeGeoKey = 2053, + GeogAngularUnitsGeoKey = 2054, + GeogAngularUnitSizeGeoKey = 2055, + GeogEllipsoidGeoKey = 2056, + GeogSemiMajorAxisGeoKey = 2057, + GeogSemiMinorAxisGeoKey = 2058, + GeogInvFlatteningGeoKey = 2059, + GeogAzimuthUnitsGeoKey = 2060, + GeogPrimeMeridianLongGeoKey = 2061, + // Projected CS Parameter GeoKeys + ProjectedCSTypeGeoKey = 3072, + PCSCitationGeoKey = 3073, + // Projection Definition GeoKeys + ProjectionGeoKey = 3074, + ProjCoordTransGeoKey = 3075, + ProjLinearUnitsGeoKey = 3076, + ProjLinearUnitSizeGeoKey = 3077, + ProjStdParallel1GeoKey = 3078, + ProjStdParallel2GeoKey = 3079, + ProjNatOriginLongGeoKey = 3080, + ProjNatOriginLatGeoKey = 3081, + ProjFalseEastingGeoKey = 3082, + ProjFalseNorthingGeoKey = 3083, + ProjFalseOriginLongGeoKey = 3084, + ProjFalseOriginLatGeoKey = 3085, + ProjFalseOriginEastingGeoKey = 3086, + ProjFalseOriginNorthingGeoKey = 3087, + ProjCenterLongGeoKey = 3088, + ProjCenterLatGeoKey = 3089, + ProjCenterEastingGeoKey = 3090, + ProjCenterNorthingGeoKey = 3091, + ProjScaleAtNatOriginGeoKey = 3092, + ProjScaleAtCenterGeoKey = 3093, + ProjAzimuthAngleGeoKey = 3094, + ProjStraightVertPoleLongGeoKey = 3095, + // Vertical CS Parameter Keys + VerticalCSTypeGeoKey = 4096, + VerticalCitationGeoKey = 4097, + VerticalDatumGeoKey = 4098, + VerticalUnitsGeoKey = 4099, +} +} +#[derive(Clone, Debug)] +pub enum GeoKeyType { + Short(u16), + Double(Vec), + Ascii(String), + ShortVec(Vec), +} + +pub fn get_geo_key(geodir: HashMap, key: &GeoKey) -> Option { + let res = geodir.get(key); + + return match res { + Some(val) => Some(val.clone()), + None => None, + }; +} + +pub fn parse_geo_keys( + geokey_dir: Vec, + ascii_params: Option, + double_params: Option>, +) -> HashMap { + let mut geodir: HashMap = HashMap::new(); + if geokey_dir.len() < 4 { + // TODO: or return a error in a result + return geodir; + } + println!( + "Directory Version: {}, {}.{}, dir length: {}", + geokey_dir[0], geokey_dir[1], geokey_dir[2], geokey_dir[3], + ); + + let num_keys = geokey_dir[3] as usize; + if geokey_dir.len() > 4 * num_keys + 4 { + println!("There are some aditional keys!!!"); + } + + for i in 0..num_keys { + let idx = 4 + i * 4; + // Each keyEntry is made up of SHORTS: KeyID, TIFFTagLocation, Count, Value_Offset + let key_id = match GeoKey::try_from(geokey_dir[idx] as usize) { + Ok(value) => value, + Err(_) => { + println!("Unknown tag found with geokey: {}", geokey_dir[idx]); + continue; + } + }; + let tiff_tag_location = geokey_dir[idx + 1]; + let count = geokey_dir[idx + 2]; + let value_offset = geokey_dir[idx + 3]; + + println!( + "KeyID: {:?}, TiffTag: {:?}, Count {:?}, ValueOffset {:?}", + key_id, tiff_tag_location, count, value_offset + ); + + if tiff_tag_location == 0 { + geodir.insert(key_id, GeoKeyType::Short(value_offset as u16)); + } else if tiff_tag_location == 34736 { + // should be accessed rather by Tag::GeoDoubleParamsTag + match &double_params { + Some(double_params) => { + let start = value_offset as usize; + let stop = (value_offset + count) as usize; + + if start > double_params.len() || stop > double_params.len() { + continue; + } + let mut value = vec![0.; count as usize]; + value.copy_from_slice(&double_params[start..stop]); + geodir.insert(key_id, GeoKeyType::Double(value)); + } + None => continue, + } + } else if tiff_tag_location == 34737 { + // should be accessed rather by Tag::GeoAsciiParamsTag + match &ascii_params { + Some(ascii_params) => { + let start = value_offset as usize; + let stop = (value_offset + count) as usize; + + if start > ascii_params.len() || stop > ascii_params.len() { + continue; + } + let value = String::from(&ascii_params[start..stop]); + geodir.insert(key_id, GeoKeyType::Ascii(value)); + } + None => continue, + } + } else if tiff_tag_location == 34735 { + println!("\n===========================================\n\nTHE CASE IS HERE\n\n\n---------------------------------\n"); + // should be accessed rather by Tag::GeoKeyDirectoryTag + // If the tag is the same as the GeoKeyDirectoryTag, the value_offset represents + // SHORT values at the end of the `geokey_dir` itself. + let start = value_offset as usize; + let stop = (value_offset + count) as usize; + + if start > geokey_dir.len() || stop > geokey_dir.len() { + continue; + } + + let mut value = vec![0; count as usize]; + value.copy_from_slice(&geokey_dir[start..stop]); + geodir.insert(key_id, GeoKeyType::ShortVec(value)); + } else { + // undefined + continue; + } + } + println!("{:#?}", geodir); + geodir +} diff --git a/src/lib.rs b/src/lib.rs index 7de0f5e..cb8816d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,7 @@ mod bytecast; pub mod decoder; pub mod encoder; mod error; +pub mod geo; pub mod tags; pub use self::error::{InflateError, TiffError, TiffFormatError, TiffResult, TiffUnsupportedError}; diff --git a/src/tags.rs b/src/tags.rs index 2741725..1b17cdd 100644 --- a/src/tags.rs +++ b/src/tags.rs @@ -120,6 +120,14 @@ pub enum Tag(u16) unknown("A private or extension tag") { TileOffsets = 324, TileByteCounts = 325, SampleFormat = 339, + // GeoTIFF + ModelPixelScaleTag = 33550, // (SoftDesk) + ModelTransformationTag = 34264, // (JPL Carto Group) + ModelTiepointTag = 33922, // (Intergraph) + GeoKeyDirectoryTag = 34735, // (SPOT) + GeoDoubleParamsTag = 34736, // (SPOT) + GeoAsciiParamsTag = 34737, // (SPOT) + // GdalNodata = 42113, } } From 96d6d52830b7d957c1f9b5dc1ef0b90cb15d694f Mon Sep 17 00:00:00 2001 From: ruffson Date: Mon, 19 Oct 2020 09:44:35 +0200 Subject: [PATCH 3/9] Move geo code in its own dir --- src/decoder/mod.rs | 3 ++- src/{geo.rs => geo/geo_key.rs} | 0 src/geo/mod.rs | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) rename src/{geo.rs => geo/geo_key.rs} (100%) create mode 100644 src/geo/mod.rs diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index 4888763..95f84d1 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -478,7 +478,8 @@ impl Decoder { Ok(geodir) => { let ascii_params = Result::ok(self.get_tag_ascii_string(Tag::GeoAsciiParamsTag)); let double_params = Result::ok(self.get_tag_f64_vec(Tag::GeoDoubleParamsTag)); - geo::parse_geo_keys(geodir, ascii_params, double_params); + geo::geo_key::parse_geo_keys(geodir, ascii_params, double_params); + // TODO: save the hashmap somewhere in this module/decoder } Err(_) => {} } diff --git a/src/geo.rs b/src/geo/geo_key.rs similarity index 100% rename from src/geo.rs rename to src/geo/geo_key.rs diff --git a/src/geo/mod.rs b/src/geo/mod.rs new file mode 100644 index 0000000..30e8165 --- /dev/null +++ b/src/geo/mod.rs @@ -0,0 +1 @@ +pub mod geo_key; From 0a4b51055e6d9357eedee1c62abdfece7fcee69d Mon Sep 17 00:00:00 2001 From: ruffson Date: Mon, 19 Oct 2020 09:44:53 +0200 Subject: [PATCH 4/9] Add gdal_nodata tag --- src/tags.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tags.rs b/src/tags.rs index 1b17cdd..5da23f4 100644 --- a/src/tags.rs +++ b/src/tags.rs @@ -127,7 +127,7 @@ pub enum Tag(u16) unknown("A private or extension tag") { GeoKeyDirectoryTag = 34735, // (SPOT) GeoDoubleParamsTag = 34736, // (SPOT) GeoAsciiParamsTag = 34737, // (SPOT) - // GdalNodata = 42113, + GdalNodata = 42113, // Contains areas with missing data } } From 9a0041286e41fd4a8883b7057257a4d55cb39104 Mon Sep 17 00:00:00 2001 From: ruffson Date: Mon, 19 Oct 2020 09:46:51 +0200 Subject: [PATCH 5/9] Remove print outs --- src/geo/geo_key.rs | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/src/geo/geo_key.rs b/src/geo/geo_key.rs index 1ac9907..86f270d 100644 --- a/src/geo/geo_key.rs +++ b/src/geo/geo_key.rs @@ -105,18 +105,11 @@ pub fn parse_geo_keys( ) -> HashMap { let mut geodir: HashMap = HashMap::new(); if geokey_dir.len() < 4 { - // TODO: or return a error in a result + // TODO: or return an error in a result return geodir; } - println!( - "Directory Version: {}, {}.{}, dir length: {}", - geokey_dir[0], geokey_dir[1], geokey_dir[2], geokey_dir[3], - ); let num_keys = geokey_dir[3] as usize; - if geokey_dir.len() > 4 * num_keys + 4 { - println!("There are some aditional keys!!!"); - } for i in 0..num_keys { let idx = 4 + i * 4; @@ -124,7 +117,6 @@ pub fn parse_geo_keys( let key_id = match GeoKey::try_from(geokey_dir[idx] as usize) { Ok(value) => value, Err(_) => { - println!("Unknown tag found with geokey: {}", geokey_dir[idx]); continue; } }; @@ -132,11 +124,6 @@ pub fn parse_geo_keys( let count = geokey_dir[idx + 2]; let value_offset = geokey_dir[idx + 3]; - println!( - "KeyID: {:?}, TiffTag: {:?}, Count {:?}, ValueOffset {:?}", - key_id, tiff_tag_location, count, value_offset - ); - if tiff_tag_location == 0 { geodir.insert(key_id, GeoKeyType::Short(value_offset as u16)); } else if tiff_tag_location == 34736 { @@ -171,7 +158,6 @@ pub fn parse_geo_keys( None => continue, } } else if tiff_tag_location == 34735 { - println!("\n===========================================\n\nTHE CASE IS HERE\n\n\n---------------------------------\n"); // should be accessed rather by Tag::GeoKeyDirectoryTag // If the tag is the same as the GeoKeyDirectoryTag, the value_offset represents // SHORT values at the end of the `geokey_dir` itself. @@ -190,6 +176,5 @@ pub fn parse_geo_keys( continue; } } - println!("{:#?}", geodir); geodir } From 4b218be4ac26a161f5f0cfd8633bd84e4231cc4d Mon Sep 17 00:00:00 2001 From: ruffson Date: Mon, 19 Oct 2020 09:52:44 +0200 Subject: [PATCH 6/9] Add geodir hashmap to decoder --- src/decoder/mod.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index 95f84d1..ccd62bf 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -210,6 +210,7 @@ where photometric_interpretation: PhotometricInterpretation, compression_method: CompressionMethod, strip_decoder: Option, + geokey_dir: Option>, } trait Wrapping { @@ -325,6 +326,7 @@ impl Decoder { photometric_interpretation: PhotometricInterpretation::BlackIsZero, compression_method: CompressionMethod::None, strip_decoder: None, + geokey_dir: None, } .init() } @@ -478,7 +480,11 @@ impl Decoder { Ok(geodir) => { let ascii_params = Result::ok(self.get_tag_ascii_string(Tag::GeoAsciiParamsTag)); let double_params = Result::ok(self.get_tag_f64_vec(Tag::GeoDoubleParamsTag)); - geo::geo_key::parse_geo_keys(geodir, ascii_params, double_params); + self.geokey_dir = Some(geo::geo_key::parse_geo_keys( + geodir, + ascii_params, + double_params, + )); // TODO: save the hashmap somewhere in this module/decoder } Err(_) => {} From 9f4799912fbd92e9c2812100ddea9d83334a9fde Mon Sep 17 00:00:00 2001 From: ruffson Date: Mon, 2 Nov 2020 18:41:59 +0100 Subject: [PATCH 7/9] Remove geokey parsing --- src/decoder/mod.rs | 16 ---- src/geo/geo_key.rs | 180 --------------------------------------------- src/geo/mod.rs | 1 - src/lib.rs | 1 - 4 files changed, 198 deletions(-) delete mode 100644 src/geo/geo_key.rs delete mode 100644 src/geo/mod.rs diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index ccd62bf..0b65113 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -210,7 +210,6 @@ where photometric_interpretation: PhotometricInterpretation, compression_method: CompressionMethod, strip_decoder: Option, - geokey_dir: Option>, } trait Wrapping { @@ -326,7 +325,6 @@ impl Decoder { photometric_interpretation: PhotometricInterpretation::BlackIsZero, compression_method: CompressionMethod::None, strip_decoder: None, - geokey_dir: None, } .init() } @@ -476,20 +474,6 @@ impl Decoder { _ => return Err(TiffUnsupportedError::UnsupportedSampleDepth(self.samples).into()), } - match self.get_tag_u16_vec(Tag::GeoKeyDirectoryTag) { - Ok(geodir) => { - let ascii_params = Result::ok(self.get_tag_ascii_string(Tag::GeoAsciiParamsTag)); - let double_params = Result::ok(self.get_tag_f64_vec(Tag::GeoDoubleParamsTag)); - self.geokey_dir = Some(geo::geo_key::parse_geo_keys( - geodir, - ascii_params, - double_params, - )); - // TODO: save the hashmap somewhere in this module/decoder - } - Err(_) => {} - } - Ok(()) } diff --git a/src/geo/geo_key.rs b/src/geo/geo_key.rs deleted file mode 100644 index 86f270d..0000000 --- a/src/geo/geo_key.rs +++ /dev/null @@ -1,180 +0,0 @@ -use std::{collections::HashMap, convert::TryFrom}; -// use tags::Tag; - -macro_rules! enum_try_from { - {#[$enum_attr:meta] $vis:vis enum $tyname:ident { $($name:ident = $value:expr),* $(,)* }} => { - #[$enum_attr] - $vis enum $tyname { - $($name = $value,)* - } - - impl ::std::convert::TryFrom for $tyname { - type Error = (); - /// Get enum key for value - fn try_from(num: usize) -> Result { - $( - if num == $value { - Ok($tyname::$name) - } else - )* { - Err(()) - } - } - } - }; -} - -// More info about geotiff keys can be found -// [here](http://geotiff.maptools.org/spec/geotiff2.7.html) -enum_try_from! { - #[derive(Debug, PartialEq, Eq, Hash)] - pub enum GeoKey { - // GeoTIFF Configuration GeoKeys - GTModelTypeGeoKey = 1024, - GTRasterTypeGeoKey = 1025, - GTCitationGeoKey = 1026, - // Geographic CS Parameter GeoKeys - GeographicTypeGeoKey = 2048, - GeogCitationGeoKey = 2049, - GeogGeodeticDatumGeoKey = 2050, - GeogPrimeMeridianGeoKey = 2051, - GeogLinearUnitsGeoKey = 2052, - GeogLinearUnitSizeGeoKey = 2053, - GeogAngularUnitsGeoKey = 2054, - GeogAngularUnitSizeGeoKey = 2055, - GeogEllipsoidGeoKey = 2056, - GeogSemiMajorAxisGeoKey = 2057, - GeogSemiMinorAxisGeoKey = 2058, - GeogInvFlatteningGeoKey = 2059, - GeogAzimuthUnitsGeoKey = 2060, - GeogPrimeMeridianLongGeoKey = 2061, - // Projected CS Parameter GeoKeys - ProjectedCSTypeGeoKey = 3072, - PCSCitationGeoKey = 3073, - // Projection Definition GeoKeys - ProjectionGeoKey = 3074, - ProjCoordTransGeoKey = 3075, - ProjLinearUnitsGeoKey = 3076, - ProjLinearUnitSizeGeoKey = 3077, - ProjStdParallel1GeoKey = 3078, - ProjStdParallel2GeoKey = 3079, - ProjNatOriginLongGeoKey = 3080, - ProjNatOriginLatGeoKey = 3081, - ProjFalseEastingGeoKey = 3082, - ProjFalseNorthingGeoKey = 3083, - ProjFalseOriginLongGeoKey = 3084, - ProjFalseOriginLatGeoKey = 3085, - ProjFalseOriginEastingGeoKey = 3086, - ProjFalseOriginNorthingGeoKey = 3087, - ProjCenterLongGeoKey = 3088, - ProjCenterLatGeoKey = 3089, - ProjCenterEastingGeoKey = 3090, - ProjCenterNorthingGeoKey = 3091, - ProjScaleAtNatOriginGeoKey = 3092, - ProjScaleAtCenterGeoKey = 3093, - ProjAzimuthAngleGeoKey = 3094, - ProjStraightVertPoleLongGeoKey = 3095, - // Vertical CS Parameter Keys - VerticalCSTypeGeoKey = 4096, - VerticalCitationGeoKey = 4097, - VerticalDatumGeoKey = 4098, - VerticalUnitsGeoKey = 4099, -} -} -#[derive(Clone, Debug)] -pub enum GeoKeyType { - Short(u16), - Double(Vec), - Ascii(String), - ShortVec(Vec), -} - -pub fn get_geo_key(geodir: HashMap, key: &GeoKey) -> Option { - let res = geodir.get(key); - - return match res { - Some(val) => Some(val.clone()), - None => None, - }; -} - -pub fn parse_geo_keys( - geokey_dir: Vec, - ascii_params: Option, - double_params: Option>, -) -> HashMap { - let mut geodir: HashMap = HashMap::new(); - if geokey_dir.len() < 4 { - // TODO: or return an error in a result - return geodir; - } - - let num_keys = geokey_dir[3] as usize; - - for i in 0..num_keys { - let idx = 4 + i * 4; - // Each keyEntry is made up of SHORTS: KeyID, TIFFTagLocation, Count, Value_Offset - let key_id = match GeoKey::try_from(geokey_dir[idx] as usize) { - Ok(value) => value, - Err(_) => { - continue; - } - }; - let tiff_tag_location = geokey_dir[idx + 1]; - let count = geokey_dir[idx + 2]; - let value_offset = geokey_dir[idx + 3]; - - if tiff_tag_location == 0 { - geodir.insert(key_id, GeoKeyType::Short(value_offset as u16)); - } else if tiff_tag_location == 34736 { - // should be accessed rather by Tag::GeoDoubleParamsTag - match &double_params { - Some(double_params) => { - let start = value_offset as usize; - let stop = (value_offset + count) as usize; - - if start > double_params.len() || stop > double_params.len() { - continue; - } - let mut value = vec![0.; count as usize]; - value.copy_from_slice(&double_params[start..stop]); - geodir.insert(key_id, GeoKeyType::Double(value)); - } - None => continue, - } - } else if tiff_tag_location == 34737 { - // should be accessed rather by Tag::GeoAsciiParamsTag - match &ascii_params { - Some(ascii_params) => { - let start = value_offset as usize; - let stop = (value_offset + count) as usize; - - if start > ascii_params.len() || stop > ascii_params.len() { - continue; - } - let value = String::from(&ascii_params[start..stop]); - geodir.insert(key_id, GeoKeyType::Ascii(value)); - } - None => continue, - } - } else if tiff_tag_location == 34735 { - // should be accessed rather by Tag::GeoKeyDirectoryTag - // If the tag is the same as the GeoKeyDirectoryTag, the value_offset represents - // SHORT values at the end of the `geokey_dir` itself. - let start = value_offset as usize; - let stop = (value_offset + count) as usize; - - if start > geokey_dir.len() || stop > geokey_dir.len() { - continue; - } - - let mut value = vec![0; count as usize]; - value.copy_from_slice(&geokey_dir[start..stop]); - geodir.insert(key_id, GeoKeyType::ShortVec(value)); - } else { - // undefined - continue; - } - } - geodir -} diff --git a/src/geo/mod.rs b/src/geo/mod.rs deleted file mode 100644 index 30e8165..0000000 --- a/src/geo/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod geo_key; diff --git a/src/lib.rs b/src/lib.rs index cb8816d..7de0f5e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,7 +14,6 @@ mod bytecast; pub mod decoder; pub mod encoder; mod error; -pub mod geo; pub mod tags; pub use self::error::{InflateError, TiffError, TiffFormatError, TiffResult, TiffUnsupportedError}; From 923b37d64735f38d8967a88b3eb52d5b2cc9083b Mon Sep 17 00:00:00 2001 From: ruffson Date: Mon, 2 Nov 2020 18:49:20 +0100 Subject: [PATCH 8/9] Remove unnecessary line --- src/decoder/ifd.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/decoder/ifd.rs b/src/decoder/ifd.rs index edfa054..cbcce61 100644 --- a/src/decoder/ifd.rs +++ b/src/decoder/ifd.rs @@ -437,7 +437,6 @@ impl Entry { Signed(i32::from(r.read_i16()?)), ])) } - (Type::SHORT, 16) => Ok(Short(u16::from(decoder.read_short()?))), (Type::SHORT, n) => self.decode_offset(n, bo, limits, decoder, |decoder| { Ok(UnsignedBig(u64::from(decoder.read_short()?))) }), From e2caf86f6a3e422a7a4211c9870ff969257a2c64 Mon Sep 17 00:00:00 2001 From: ruffson Date: Mon, 2 Nov 2020 19:49:18 +0100 Subject: [PATCH 9/9] Add intos for Short --- src/decoder/ifd.rs | 2 ++ src/decoder/mod.rs | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/decoder/ifd.rs b/src/decoder/ifd.rs index cbcce61..c033c84 100644 --- a/src/decoder/ifd.rs +++ b/src/decoder/ifd.rs @@ -56,6 +56,7 @@ impl Value { pub fn into_u32(self) -> TiffResult { match self { + Short(val) => Ok(val.into()), Unsigned(val) => Ok(val), UnsignedBig(val) => Ok(u32::try_from(val)?), val => Err(TiffError::FormatError( @@ -76,6 +77,7 @@ impl Value { pub fn into_u64(self) -> TiffResult { match self { + Short(val) => Ok(val.into()), Unsigned(val) => Ok(val.into()), UnsignedBig(val) => Ok(val), val => Err(TiffError::FormatError( diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index 0b65113..af05a78 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -13,7 +13,6 @@ use crate::tags::{ use self::stream::{ ByteOrder, DeflateReader, EndianReader, JpegReader, LZWReader, PackBitsReader, SmartReader, }; -use geo; pub mod ifd; mod stream;