Add support for ASCII tags

This commit is contained in:
Jim Rybarski committed 2018-08-17 11:43:51 -05:00
1 parent daf23f34a0
commit ff1d31533b
4 files changed
+54 -12

No files matched your search

+17 -11
View File
@@ -6,7 +6,7 @@ use std::collections::{HashMap};
use super::stream::{ByteOrder, SmartReader, EndianReader}; use super::stream::{ByteOrder, SmartReader, EndianReader};
use ::{TiffError, TiffResult}; use ::{TiffError, TiffResult};
use self::Value::{Unsigned, List, Rational}; use self::Value::{Unsigned, List, Rational, Ascii};
macro_rules! tags { macro_rules! tags {
{$( {$(
@@ -33,7 +33,7 @@ macro_rules! tags {
// Note: These tags appear in the order they are mentioned in the TIFF reference // Note: These tags appear in the order they are mentioned in the TIFF reference
tags!{ tags!{
// Baseline tags: // Baseline tags:
Artist 315; // TODO add support Artist 315;
// grayscale images PhotometricInterpretation 1 or 3 // grayscale images PhotometricInterpretation 1 or 3
BitsPerSample 258; BitsPerSample 258;
CellLength 265; // TODO add support CellLength 265; // TODO add support
@@ -41,22 +41,22 @@ tags!{
// palette-color images (PhotometricInterpretation 3) // palette-color images (PhotometricInterpretation 3)
ColorMap 320; // TODO add support ColorMap 320; // TODO add support
Compression 259; // TODO add support for 2 and 32773 Compression 259; // TODO add support for 2 and 32773
Copyright 33_432; // TODO add support Copyright 33_432;
DateTime 306; // TODO add support DateTime 306;
ExtraSamples 338; // TODO add support ExtraSamples 338; // TODO add support
FillOrder 266; // TODO add support FillOrder 266; // TODO add support
FreeByteCounts 289; // TODO add support FreeByteCounts 289; // TODO add support
FreeOffsets 288; // TODO add support FreeOffsets 288; // TODO add support
GrayResponseCurve 291; // TODO add support GrayResponseCurve 291; // TODO add support
GrayResponseUnit 290; // TODO add support GrayResponseUnit 290; // TODO add support
HostComputer 316; // TODO add support HostComputer 316;
ImageDescription 270; // TODO add support ImageDescription 270;
ImageLength 257; ImageLength 257;
ImageWidth 256; ImageWidth 256;
Make 271; // TODO add support Make 271;
MaxSampleValue 281; // TODO add support MaxSampleValue 281; // TODO add support
MinSampleValue 280; // TODO add support MinSampleValue 280; // TODO add support
Model 272; // TODO add support Model 272;
NewSubfileType 254; // TODO add support NewSubfileType 254; // TODO add support
Orientation 274; // TODO add support Orientation 274; // TODO add support
PhotometricInterpretation 262; PhotometricInterpretation 262;
@@ -91,7 +91,8 @@ pub enum Value {
//Signed(i32), //Signed(i32),
Unsigned(u32), Unsigned(u32),
List(Vec<Value>), List(Vec<Value>),
Rational(u32, u32) Rational(u32, u32),
Ascii(String)
} }
impl Value { impl Value {
@@ -113,8 +114,8 @@ impl Value {
Ok(new_vec) Ok(new_vec)
}, },
Unsigned(val) => Ok(vec![val]), Unsigned(val) => Ok(vec![val]),
Rational(numerator, denominator) => Ok(vec![numerator, denominator]) Rational(numerator, denominator) => Ok(vec![numerator, denominator]),
//_ => Err(::image::FormatError("Tag data malformed.".to_string())) Ascii(val) => Ok(val.chars().map(|x| x as u32).collect())
} }
} }
} }
@@ -196,6 +197,11 @@ impl Entry {
} }
Ok(List(v)) Ok(List(v))
}, },
(Type::ASCII, n) => {
try!(decoder.goto_offset(try!(self.r(bo).read_u32())));
let string = try!(decoder.read_string(n as usize));
Ok(Ascii(string))
}
_ => Err(TiffError::UnsupportedError("Unsupported data type.".to_string())) _ => Err(TiffError::UnsupportedError("Unsupported data type.".to_string()))
} }
} }
+11
View File
@@ -2,6 +2,7 @@ use std::io::{self, Read, Seek};
use std::mem; use std::mem;
use num_traits::{FromPrimitive, Num}; use num_traits::{FromPrimitive, Num};
use std::collections::HashMap; use std::collections::HashMap;
use std::string::FromUtf8Error;
use ::{ColorType, TiffError, TiffResult}; use ::{ColorType, TiffError, TiffResult};
@@ -279,6 +280,16 @@ impl<R: Read + Seek> Decoder<R> {
self.reader.read_u32() self.reader.read_u32()
} }
/// Reads a string
#[inline]
pub fn read_string(&mut self, length: usize) -> Result<String, FromUtf8Error> {
let mut out = String::with_capacity(length);
self.reader.read_to_string(&mut out);
// Strings may be null-terminated, so we trim anything downstream of the null byte
let trimmed = out.bytes().take_while(|&n| n != 0).collect::<Vec<u8>>();
String::from_utf8(trimmed)
}
/// Reads a TIFF IFA offset/value field /// Reads a TIFF IFA offset/value field
#[inline] #[inline]
pub fn read_offset(&mut self) -> Result<[u8; 4], io::Error> { pub fn read_offset(&mut self) -> Result<[u8; 4], io::Error> {
+7
View File
@@ -1,6 +1,7 @@
use std::error::Error; use std::error::Error;
use std::fmt; use std::fmt;
use std::io; use std::io;
use std::string;
/// Tiff error kinds. /// Tiff error kinds.
#[derive(Debug)] #[derive(Debug)]
@@ -49,5 +50,11 @@ impl From<io::Error> for TiffError {
} }
} }
impl From<string::FromUtf8Error> for TiffError {
fn from(err: string::FromUtf8Error) -> TiffError {
TiffError::FormatError(String::from("Image contains invalid tag."))
}
}
/// Result of an image decoding/encoding process /// Result of an image decoding/encoding process
pub type TiffResult<T> = Result<T, TiffError>; pub type TiffResult<T> = Result<T, TiffError>;
+19 -1
View File
@@ -1,7 +1,7 @@
extern crate tiff; extern crate tiff;
use tiff::ColorType; use tiff::ColorType;
use tiff::decoder::{Decoder, DecodingResult}; use tiff::decoder::{Decoder, DecodingResult, ifd::Tag, ifd::Value};
use std::fs::File; use std::fs::File;
@@ -45,6 +45,24 @@ fn test_rgb_u16()
assert!(img_res.is_ok()); assert!(img_res.is_ok());
} }
#[test]
fn test_string_tags()
{
// these files have null-terminated strings for their Software tag. One has extra bytes after
// the null byte, so we check both to ensure that we're truncating properly
let filenames = vec!["minisblack-1c-16b.tiff", "rgb-3c-16b.tiff"];
for filename in filenames.iter() {
let path = format!("./tests/images/{}", filename);
let img_file = File::open(path).expect("can't open file");
let mut decoder = Decoder::new(img_file).expect("Cannot create decoder");
let software= decoder.get_tag(Tag::Software).unwrap();
match software {
Value::Ascii(s) => assert_eq!(s, String::from("GraphicsMagick 1.2 unreleased Q16 http://www.GraphicsMagick.org/")),
_ => assert!(false)
};
}
}
// TODO: GrayA support // TODO: GrayA support
//#[test] //#[test]
//fn test_gray_alpha_u8() //fn test_gray_alpha_u8()