diff --git a/Cargo.lock b/Cargo.lock index 0962eef..14cff1c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,105 +1,169 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "byteorder" version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "crc32fast" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +dependencies = [ + "cfg-if", +] [[package]] name = "enum_primitive" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" +dependencies = [ + "num-traits 0.1.43", +] + +[[package]] +name = "flate2" +version = "1.0.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" dependencies = [ - "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "crc32fast", + "miniz_oxide", ] [[package]] name = "geotiff" version = "0.0.1" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "enum_primitive", + "num", + "tiff", +] + +[[package]] +name = "jpeg-decoder" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", ] [[package]] name = "num" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db" dependencies = [ - "num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "num-complex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits 0.2.6", ] [[package]] name = "num-bigint" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57450397855d951f1a41305e54851b1a7b8f5d2e349543a02a2effe25459f718" dependencies = [ - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer", + "num-traits 0.2.6", ] [[package]] name = "num-complex" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "107b9be86cd2481930688277b675b0114578227f034674726605b8a482d8baf8" dependencies = [ - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6", ] [[package]] name = "num-integer" version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" dependencies = [ - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6", ] [[package]] name = "num-iter" version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124" dependencies = [ - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer", + "num-traits 0.2.6", ] [[package]] name = "num-rational" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e96f040177bb3da242b5b1ecf3f54b5d5af3efbbfb18608977a5d2767b22f10" dependencies = [ - "num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-bigint", + "num-integer", + "num-traits 0.2.6", ] [[package]] name = "num-traits" version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" dependencies = [ - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6", ] [[package]] name = "num-traits" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" + +[[package]] +name = "tiff" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" +dependencies = [ + "flate2", + "jpeg-decoder", + "weezl", +] -[metadata] -"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" -"checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" -"checksum num 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cf4825417e1e1406b3782a8ce92f4d53f26ec055e3622e1881ca8e9f5f9e08db" -"checksum num-bigint 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "57450397855d951f1a41305e54851b1a7b8f5d2e349543a02a2effe25459f718" -"checksum num-complex 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "107b9be86cd2481930688277b675b0114578227f034674726605b8a482d8baf8" -"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" -"checksum num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124" -"checksum num-rational 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e96f040177bb3da242b5b1ecf3f54b5d5af3efbbfb18608977a5d2767b22f10" -"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" -"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" +[[package]] +name = "weezl" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" diff --git a/Cargo.toml b/Cargo.toml index b665901..ed2b642 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,3 +9,4 @@ repository = "https://github.com/georust/geotiff" byteorder = "*" enum_primitive = "*" num = "*" +tiff = "0.9" diff --git a/README.md b/README.md index 3b0fa41..98f9b44 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,14 @@ # A TIFF Library for Rust -![Version](https://img.shields.io/badge/version-v0.0.1-red.svg) +![Version](https://img.shields.io/badge/version-v0.0.2-red.svg) + +> [!IMPORTANT] +> This crate is currently undergoing a significant refactoring process to be built on +> top of the [`tiff`](https://crates.io/crates/tiff) crate, so expect breaking changes +> as we work towards a v0.1.0 release sometime in 2024 (contributions are welcome!). See +> the thread at https://github.com/georust/geotiff/issues/7 for more details. + +## Motivation (pre-2020) I needed this library to import elevation models for a routing library. As elevation models usually come in GeoTIFF format, but no such library was available for Rust, I created this library, taking other libraries as inspiration: @@ -46,4 +54,3 @@ Several documents describe the structure of a (Geo)TIFF: * The official TIFF specification: http://download.osgeo.org/geotiff/spec/tiff6.pdf. * The official GeoTIFF specitication: http://download.osgeo.org/geotiff/spec/geotiff.rtf * The article "GeoTIFF – A standard image file format for GIS applications" by Mahammad and Ramakrishnan: https://www.geospatialworld.net/article/geotiff-a-standard-image-file-format-for-gis-applications/ - diff --git a/src/tiff.rs b/src/geotiff.rs similarity index 92% rename from src/tiff.rs rename to src/geotiff.rs index 1e0085c..a513000 100644 --- a/src/tiff.rs +++ b/src/geotiff.rs @@ -1,6 +1,7 @@ use std::collections::HashSet; use enum_primitive::FromPrimitive; +use tiff::tags::Type; use crate::lowlevel::*; @@ -35,11 +36,11 @@ pub struct IFD { /// tag values. #[derive(Debug)] pub struct IFDEntry { - pub tag: TIFFTag, - pub tpe: TagType, - pub count: LONG, + pub tag: TIFFTag, + pub tpe: Type, + pub count: LONG, pub value_offset: LONG, - pub value: Vec, + pub value: Vec, } /// Implementations for the IFD struct. @@ -62,11 +63,6 @@ pub fn decode_tag(value: u16) -> Option { TIFFTag::from_u16(value) } -/// Decodes an u16 value into a TagType. -pub fn decode_tag_type(tpe: u16) -> Option { - TagType::from_u16(tpe) -} - /// Validation functions to make sure all the required tags are existing for a certain GeoTiff /// image type (e.g., grayscale or RGB image). pub fn validate_required_tags_for(typ: &ImageType) -> Option> { diff --git a/src/lib.rs b/src/lib.rs index 414a54e..f9a9061 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,12 +6,12 @@ extern crate num; use std::fmt; use std::io::Result; +pub mod geotiff; mod lowlevel; mod reader; -pub mod tiff; +pub use geotiff::TIFF; use reader::*; -pub use tiff::TIFF; /// The GeoTIFF library reads `.tiff` files. /// diff --git a/src/lowlevel.rs b/src/lowlevel.rs index 42fd5ca..2a91064 100644 --- a/src/lowlevel.rs +++ b/src/lowlevel.rs @@ -1,4 +1,4 @@ -#![allow(dead_code)] +use tiff::tags::Type; // Base types of the TIFF format. pub type BYTE = u8; @@ -23,40 +23,26 @@ enum_from_primitive! { } } -enum_from_primitive! { - #[repr(u16)] - #[derive(Debug,PartialEq)] - pub enum TagType { - ByteTag = 1, - ASCIITag = 2, - ShortTag = 3, - LongTag = 4, - RationalTag = 5, - SignedByteTag = 6, - UndefinedTag = 7, - SignedShortTag = 8, - SignedLongTag = 9, - SignedRationalTag = 10, - FloatTag = 11, - DoubleTag = 12, - } -} - /// Helper function that returns the size of a certain tag. -pub fn tag_size(t: &TagType) -> u32 { +pub fn tag_size(t: &Type) -> u32 { match *t { - TagType::ByteTag => 1, - TagType::ASCIITag => 1, - TagType::ShortTag => 2, - TagType::LongTag => 4, - TagType::RationalTag => 8, - TagType::SignedByteTag => 1, - TagType::UndefinedTag => 1, - TagType::SignedShortTag => 2, - TagType::SignedLongTag => 2, - TagType::SignedRationalTag => 8, - TagType::FloatTag => 4, - TagType::DoubleTag => 8, + Type::BYTE => 1, + Type::ASCII => 1, + Type::SHORT => 2, + Type::LONG => 4, + Type::RATIONAL => 8, + Type::SBYTE => 1, + Type::UNDEFINED => 1, + Type::SSHORT => 2, + Type::SLONG => 2, + Type::SRATIONAL => 8, + Type::FLOAT => 4, + Type::DOUBLE => 8, + Type::IFD => 4, + Type::LONG8 => 8, + Type::SLONG8 => 8, + Type::IFD8 => 8, + _ => unimplemented!(), } } diff --git a/src/reader.rs b/src/reader.rs index f89e129..4a49f0c 100644 --- a/src/reader.rs +++ b/src/reader.rs @@ -4,9 +4,10 @@ use std::path::Path; use byteorder::{BigEndian, ByteOrder, LittleEndian, ReadBytesExt}; use num::FromPrimitive; +use tiff::tags::Type; -use crate::lowlevel::{tag_size, TIFFByteOrder, TIFFTag, TagType, TagValue}; -use crate::tiff::{decode_tag, decode_tag_type, IFDEntry, IFD, TIFF}; +use crate::geotiff::{decode_tag, IFDEntry, IFD, TIFF}; +use crate::lowlevel::{tag_size, TIFFByteOrder, TIFFTag, TagValue}; /// A helper trait to indicate that something needs to be seekable and readable. pub trait SeekableReader: Seek + Read {} @@ -119,23 +120,32 @@ impl TIFFReader { /// Converts a Vec into a TagValue, depending on the type of the tag. In the TIFF file /// format, each tag type indicates which value it stores (e.g., a byte, ascii, or long value). /// This means that the tag values have to be read taking the tag type into consideration. - fn vec_to_tag_value(&self, vec: Vec, tpe: &TagType) -> TagValue { + fn vec_to_tag_value(&self, vec: Vec, tpe: &Type) -> TagValue { let len = vec.len(); match tpe { - &TagType::ByteTag => TagValue::ByteValue(vec[0]), - &TagType::ASCIITag => TagValue::AsciiValue(String::from_utf8_lossy(&vec).to_string()), - &TagType::ShortTag => TagValue::ShortValue(Endian::read_u16(&vec[..])), - &TagType::LongTag => TagValue::LongValue(Endian::read_u32(&vec[..])), - &TagType::RationalTag => TagValue::RationalValue((Endian::read_u32(&vec[..(len / 2)]), - Endian::read_u32(&vec[(len / 2)..]))), - &TagType::SignedByteTag => TagValue::SignedByteValue(vec[0] as i8), - &TagType::SignedShortTag => TagValue::SignedShortValue(Endian::read_i16(&vec[..])), - &TagType::SignedLongTag => TagValue::SignedLongValue(Endian::read_i32(&vec[..])), - &TagType::SignedRationalTag => TagValue::SignedRationalValue((Endian::read_i32(&vec[..(len / 2)]), - Endian::read_i32(&vec[(len / 2)..]))), - &TagType::FloatTag => TagValue::FloatValue(Endian::read_f32(&vec[..])), - &TagType::DoubleTag => TagValue::DoubleValue(Endian::read_f64(&vec[..])), - &TagType::UndefinedTag => TagValue::ByteValue(0), + Type::BYTE => TagValue::ByteValue(vec[0]), + Type::ASCII => TagValue::AsciiValue(String::from_utf8_lossy(&vec).to_string()), + Type::SHORT => TagValue::ShortValue(Endian::read_u16(&vec[..])), + Type::LONG => TagValue::LongValue(Endian::read_u32(&vec[..])), + Type::RATIONAL => TagValue::RationalValue(( + Endian::read_u32(&vec[..(len / 2)]), + Endian::read_u32(&vec[(len / 2)..]), + )), + Type::SBYTE => TagValue::SignedByteValue(vec[0] as i8), + Type::UNDEFINED => TagValue::ByteValue(0), + Type::SSHORT => TagValue::SignedShortValue(Endian::read_i16(&vec[..])), + Type::SLONG => TagValue::SignedLongValue(Endian::read_i32(&vec[..])), + Type::SRATIONAL => TagValue::SignedRationalValue(( + Endian::read_i32(&vec[..(len / 2)]), + Endian::read_i32(&vec[(len / 2)..]), + )), + Type::FLOAT => TagValue::FloatValue(Endian::read_f32(&vec[..])), + Type::DOUBLE => TagValue::DoubleValue(Endian::read_f64(&vec[..])), + Type::IFD => unimplemented!(), + Type::LONG8 => unimplemented!(), + Type::SLONG8 => unimplemented!(), + Type::IFD8 => unimplemented!(), + _ => unimplemented!(), } } @@ -185,7 +195,7 @@ impl TIFFReader { // Decode the type. let tpe_msg = format!("Invalid tag type {:04X}", tpe_value); - let tpe = decode_tag_type(tpe_value).expect(&tpe_msg); + let tpe = Type::from_u16(tpe_value).expect(&tpe_msg); let value_size = tag_size(&tpe); // Let's get the value(s) of this tag.