Merge branch 'master' of github.com:Farkal/image-tiff into big-tiff
This commit is contained in:
commit
b2da2f2333
6 files changed
+66
-32
No files matched your search
+14
-5
@@ -348,13 +348,22 @@ impl Entry {
|
|||||||
if n > limits.decoding_buffer_size {
|
if n > limits.decoding_buffer_size {
|
||||||
return Err(TiffError::LimitsExceeded);
|
return Err(TiffError::LimitsExceeded);
|
||||||
}
|
}
|
||||||
if decoder.bigtiff {
|
|
||||||
decoder.goto_offset_u64(self.r(bo).read_u64()?)?
|
if (n <= 4 && !decoder.bigtiff) || (n <= 8 && decoder.bigtiff) {
|
||||||
|
let mut buf = vec![0; n];
|
||||||
|
self.r(bo).read_exact(&mut buf )?;
|
||||||
|
let v = String::from_utf8(buf)?;
|
||||||
|
let v = v.trim_matches(char::from(0));
|
||||||
|
Ok(Ascii(v.into()))
|
||||||
} else {
|
} else {
|
||||||
decoder.goto_offset(self.r(bo).read_u32()?)?
|
if decoder.bigtiff {
|
||||||
|
decoder.goto_offset_u64(self.r(bo).read_u64()?)?
|
||||||
|
} else {
|
||||||
|
decoder.goto_offset(self.r(bo).read_u32()?)?
|
||||||
|
}
|
||||||
|
let string = decoder.read_string(n)?;
|
||||||
|
Ok(Ascii(string))
|
||||||
}
|
}
|
||||||
let string = decoder.read_string(n)?;
|
|
||||||
Ok(Ascii(string))
|
|
||||||
}
|
}
|
||||||
_ => Err(TiffError::UnsupportedError(
|
_ => Err(TiffError::UnsupportedError(
|
||||||
TiffUnsupportedError::UnsupportedDataType,
|
TiffUnsupportedError::UnsupportedDataType,
|
||||||
|
|||||||
+6
-4
@@ -457,11 +457,13 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
/// Reads a string
|
/// Reads a string
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn read_string(&mut self, length: usize) -> TiffResult<String> {
|
pub fn read_string(&mut self, length: usize) -> TiffResult<String> {
|
||||||
let mut out = String::with_capacity(length);
|
let mut out = vec![0; length];
|
||||||
self.reader.read_to_string(&mut out)?;
|
self.reader.read_exact(&mut out)?;
|
||||||
// Strings may be null-terminated, so we trim anything downstream of the null byte
|
// 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>>();
|
if let Some(first) = out.iter().position(|&b| b == 0) {
|
||||||
Ok(String::from_utf8(trimmed)?)
|
out.truncate(first);
|
||||||
|
}
|
||||||
|
Ok(String::from_utf8(out)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads a TIFF IFA offset/value field
|
/// Reads a TIFF IFA offset/value field
|
||||||
|
|||||||
+33
-19
@@ -407,26 +407,9 @@ impl<W: Write + Seek> TiffEncoder<W> {
|
|||||||
where
|
where
|
||||||
[C::Inner]: TiffValue,
|
[C::Inner]: TiffValue,
|
||||||
{
|
{
|
||||||
let num_pix = usize::try_from(width)?.checked_mul(usize::try_from(height)?)
|
|
||||||
.ok_or_else(|| ::std::io::Error::new(
|
|
||||||
::std::io::ErrorKind::InvalidInput,
|
|
||||||
"Image width * height exceeds usize"))?;
|
|
||||||
if data.len() < num_pix {
|
|
||||||
return Err(::std::io::Error::new(
|
|
||||||
::std::io::ErrorKind::InvalidData,
|
|
||||||
"Input data slice is undersized for provided dimensions").into());
|
|
||||||
}
|
|
||||||
|
|
||||||
let encoder = DirectoryEncoder::new(&mut self.writer)?;
|
let encoder = DirectoryEncoder::new(&mut self.writer)?;
|
||||||
let mut image: ImageEncoder<W, C> = ImageEncoder::new(encoder, width, height)?;
|
let image: ImageEncoder<W, C> = ImageEncoder::new(encoder, width, height)?;
|
||||||
|
image.write_data(data)
|
||||||
let mut idx = 0;
|
|
||||||
while image.next_strip_sample_count() > 0 {
|
|
||||||
let sample_count = usize::try_from(image.next_strip_sample_count())?;
|
|
||||||
image.write_strip(&data[idx..idx + sample_count])?;
|
|
||||||
idx += sample_count;
|
|
||||||
}
|
|
||||||
image.finish()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -548,10 +531,14 @@ impl<'a, W: Write + Seek> Drop for DirectoryEncoder<'a, W> {
|
|||||||
/// # let mut file = std::io::Cursor::new(Vec::new());
|
/// # let mut file = std::io::Cursor::new(Vec::new());
|
||||||
/// # let image_data = vec![0; 100*100*3];
|
/// # let image_data = vec![0; 100*100*3];
|
||||||
/// use tiff::encoder::*;
|
/// use tiff::encoder::*;
|
||||||
|
/// use tiff::tags::Tag;
|
||||||
///
|
///
|
||||||
/// let mut tiff = TiffEncoder::new(&mut file).unwrap();
|
/// let mut tiff = TiffEncoder::new(&mut file).unwrap();
|
||||||
/// let mut image = tiff.new_image::<colortype::RGB8>(100, 100).unwrap();
|
/// let mut image = tiff.new_image::<colortype::RGB8>(100, 100).unwrap();
|
||||||
///
|
///
|
||||||
|
/// // You can encode tags here
|
||||||
|
/// image.encoder().write_tag(Tag::Artist, "Image-tiff").unwrap();
|
||||||
|
///
|
||||||
/// let mut idx = 0;
|
/// let mut idx = 0;
|
||||||
/// while image.next_strip_sample_count() > 0 {
|
/// while image.next_strip_sample_count() > 0 {
|
||||||
/// let sample_count = image.next_strip_sample_count() as usize;
|
/// let sample_count = image.next_strip_sample_count() as usize;
|
||||||
@@ -561,11 +548,13 @@ impl<'a, W: Write + Seek> Drop for DirectoryEncoder<'a, W> {
|
|||||||
/// image.finish().unwrap();
|
/// image.finish().unwrap();
|
||||||
/// # }
|
/// # }
|
||||||
/// ```
|
/// ```
|
||||||
|
/// You can also call write_data function wich will encode by strip and finish
|
||||||
pub struct ImageEncoder<'a, W: 'a + Write + Seek, C: ColorType> {
|
pub struct ImageEncoder<'a, W: 'a + Write + Seek, C: ColorType> {
|
||||||
encoder: DirectoryEncoder<'a, W>,
|
encoder: DirectoryEncoder<'a, W>,
|
||||||
strip_idx: u64,
|
strip_idx: u64,
|
||||||
strip_count: u64,
|
strip_count: u64,
|
||||||
row_samples: u64,
|
row_samples: u64,
|
||||||
|
width: u32,
|
||||||
height: u32,
|
height: u32,
|
||||||
rows_per_strip: u64,
|
rows_per_strip: u64,
|
||||||
strip_offsets: Vec<u32>,
|
strip_offsets: Vec<u32>,
|
||||||
@@ -608,6 +597,7 @@ impl<'a, W: 'a + Write + Seek, T: ColorType> ImageEncoder<'a, W, T> {
|
|||||||
strip_idx: 0,
|
strip_idx: 0,
|
||||||
row_samples,
|
row_samples,
|
||||||
rows_per_strip,
|
rows_per_strip,
|
||||||
|
width,
|
||||||
height,
|
height,
|
||||||
strip_offsets: Vec::new(),
|
strip_offsets: Vec::new(),
|
||||||
strip_byte_count: Vec::new(),
|
strip_byte_count: Vec::new(),
|
||||||
@@ -652,6 +642,30 @@ impl<'a, W: 'a + Write + Seek, T: ColorType> ImageEncoder<'a, W, T> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Write strips from data
|
||||||
|
pub fn write_data(mut self, data: &[T::Inner]) -> TiffResult<()>
|
||||||
|
where
|
||||||
|
[T::Inner]: TiffValue,
|
||||||
|
{
|
||||||
|
let num_pix = usize::try_from(self.width)?.checked_mul(usize::try_from(self.height)?)
|
||||||
|
.ok_or_else(|| ::std::io::Error::new(
|
||||||
|
::std::io::ErrorKind::InvalidInput,
|
||||||
|
"Image width * height exceeds usize"))?;
|
||||||
|
if data.len() < num_pix {
|
||||||
|
return Err(::std::io::Error::new(
|
||||||
|
::std::io::ErrorKind::InvalidData,
|
||||||
|
"Input data slice is undersized for provided dimensions").into());
|
||||||
|
}
|
||||||
|
let mut idx = 0;
|
||||||
|
while self.next_strip_sample_count() > 0 {
|
||||||
|
let sample_count = usize::try_from(self.next_strip_sample_count())?;
|
||||||
|
self.write_strip(&data[idx..idx + sample_count])?;
|
||||||
|
idx += sample_count;
|
||||||
|
}
|
||||||
|
self.finish()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Set image resolution
|
/// Set image resolution
|
||||||
pub fn resolution(&mut self, unit: ResolutionUnit, value: Rational) {
|
pub fn resolution(&mut self, unit: ResolutionUnit, value: Rational) {
|
||||||
self.encoder.write_tag(Tag::ResolutionUnit, unit.to_u16()).unwrap();
|
self.encoder.write_tag(Tag::ResolutionUnit, unit.to_u16()).unwrap();
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@
|
|||||||
//! lossless and lossy compression.
|
//! lossless and lossy compression.
|
||||||
//!
|
//!
|
||||||
//! # Related Links
|
//! # Related Links
|
||||||
//! * <http://partners.adobe.com/public/developer/tiff/index.html> - The TIFF specification
|
//! * <https://www.adobe.io/open/standards/TIFF.html> - The TIFF specification
|
||||||
|
|
||||||
extern crate byteorder;
|
extern crate byteorder;
|
||||||
extern crate lzw;
|
extern crate lzw;
|
||||||
|
|||||||
@@ -105,6 +105,11 @@ pub enum Tag(u16) unknown("A private or extension tag") {
|
|||||||
YResolution = 283,
|
YResolution = 283,
|
||||||
// Advanced tags
|
// Advanced tags
|
||||||
Predictor = 317,
|
Predictor = 317,
|
||||||
|
TileWidth = 322,
|
||||||
|
TileLength = 323,
|
||||||
|
TileOffsets = 324,
|
||||||
|
TileByteCounts = 325,
|
||||||
|
SampleFormat = 339,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
extern crate tiff;
|
extern crate tiff;
|
||||||
|
|
||||||
use tiff::decoder::{Decoder, DecodingResult};
|
use tiff::decoder::{Decoder, DecodingResult, ifd};
|
||||||
use tiff::encoder::{colortype, TiffEncoder, SRational};
|
use tiff::encoder::{colortype, TiffEncoder, SRational};
|
||||||
use tiff::ColorType;
|
use tiff::ColorType;
|
||||||
use tiff::tags::Tag;
|
use tiff::tags::Tag;
|
||||||
@@ -24,14 +24,18 @@ fn encode_decode() {
|
|||||||
{
|
{
|
||||||
let mut tiff = TiffEncoder::new(&mut file).unwrap();
|
let mut tiff = TiffEncoder::new(&mut file).unwrap();
|
||||||
|
|
||||||
tiff.write_image::<colortype::RGB8>(100, 100, &image_data)
|
let mut image = tiff.new_image::<colortype::RGB8>(100, 100)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
image.encoder().write_tag(Tag::Artist, "Image-tiff").unwrap();
|
||||||
|
image.write_data(&image_data).unwrap();
|
||||||
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
file.seek(SeekFrom::Start(0)).unwrap();
|
file.seek(SeekFrom::Start(0)).unwrap();
|
||||||
let mut decoder = Decoder::new(&mut file).unwrap();
|
let mut decoder = Decoder::new(&mut file).unwrap();
|
||||||
assert_eq!(decoder.colortype().unwrap(), ColorType::RGB(8));
|
assert_eq!(decoder.colortype().unwrap(), ColorType::RGB(8));
|
||||||
assert_eq!(decoder.dimensions().unwrap(), (100, 100));
|
assert_eq!(decoder.dimensions().unwrap(), (100, 100));
|
||||||
|
assert_eq!(decoder.get_tag(Tag::Artist).unwrap(), ifd::Value::Ascii("Image-tiff".into()));
|
||||||
if let DecodingResult::U8(img_res) = decoder.read_image().unwrap() {
|
if let DecodingResult::U8(img_res) = decoder.read_image().unwrap() {
|
||||||
assert_eq!(image_data, img_res);
|
assert_eq!(image_data, img_res);
|
||||||
} else {
|
} else {
|
||||||
@@ -259,4 +263,4 @@ fn test_multipage_image() {
|
|||||||
// check the dimensions of the image in the second page
|
// check the dimensions of the image in the second page
|
||||||
assert_eq!(img_decoder.dimensions().unwrap(), (3, 3));
|
assert_eq!(img_decoder.dimensions().unwrap(), (3, 3));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user