Add support for ASCII tags
This commit is contained in:
1 parent
daf23f34a0
commit
ff1d31533b
4 files changed
+54
-12
No files matched your search
+17
-11
@@ -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()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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> {
|
||||||
|
|||||||
@@ -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
@@ -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()
|
||||||
|
|||||||
Reference in new issue
Block a user