Merge branch 'master' of github.com:Farkal/image-tiff into features/32-bit-float-samples
This commit is contained in:
commit
5f48444fa0
11 files changed
+77
-29
No files matched your search
@@ -1,3 +1,12 @@
|
||||
# Version 0.5.0
|
||||
|
||||
* Added support for 32-bit and 64-bit decoded values.
|
||||
* Added CMYK(16|32|64) color type support.
|
||||
* Check many internal integer conversions to increase stability. This should
|
||||
only lead to images being reported as faulty that would previously silently
|
||||
break platform limits. If there are any false positives, please report them.
|
||||
* Remove an erroneous check of decoded length in lzw compressed images.
|
||||
|
||||
# Version 0.4.0
|
||||
|
||||
* Several enumerations are now non_exhaustive for future extensions.
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tiff"
|
||||
version = "0.4.0"
|
||||
version = "0.5.0"
|
||||
authors = [
|
||||
"ccgn",
|
||||
"bvssvni <bvssvni@gmail.com>",
|
||||
|
||||
@@ -198,10 +198,18 @@ impl Entry {
|
||||
if n > limits.decoding_buffer_size {
|
||||
return Err(TiffError::LimitsExceeded);
|
||||
}
|
||||
if n <= 4 {
|
||||
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 {
|
||||
decoder.goto_offset(self.r(bo).read_u32()?)?;
|
||||
let string = decoder.read_string(n)?;
|
||||
Ok(Ascii(string))
|
||||
}
|
||||
}
|
||||
_ => Err(TiffError::UnsupportedError(
|
||||
TiffUnsupportedError::UnsupportedDataType,
|
||||
)),
|
||||
|
||||
+8
-6
@@ -486,11 +486,13 @@ impl<R: Read + Seek> Decoder<R> {
|
||||
/// Reads a string
|
||||
#[inline]
|
||||
pub fn read_string(&mut self, length: usize) -> TiffResult<String> {
|
||||
let mut out = String::with_capacity(length);
|
||||
self.reader.read_to_string(&mut out)?;
|
||||
let mut out = vec![0; length];
|
||||
self.reader.read_exact(&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>>();
|
||||
Ok(String::from_utf8(trimmed)?)
|
||||
if let Some(first) = out.iter().position(|&b| b == 0) {
|
||||
out.truncate(first);
|
||||
}
|
||||
Ok(String::from_utf8(out)?)
|
||||
}
|
||||
|
||||
/// Reads a TIFF IFA offset/value field
|
||||
@@ -646,7 +648,7 @@ impl<R: Read + Seek> Decoder<R> {
|
||||
let (bytes, reader) = LZWReader::new(
|
||||
&mut self.reader,
|
||||
usize::try_from(length)?,
|
||||
max_uncompressed_length
|
||||
max_uncompressed_length * buffer.byte_len()
|
||||
)?;
|
||||
(bytes, Box::new(reader))
|
||||
}
|
||||
@@ -838,7 +840,7 @@ impl<R: Read + Seek> Decoder<R> {
|
||||
|
||||
let buffer_size = usize::try_from(self.width)? * strip_height * self.bits_per_sample.len();
|
||||
|
||||
if buffer.len() < buffer_size || usize::try_from(byte_count)? / buffer.byte_len() > buffer_size {
|
||||
if buffer.len() < buffer_size {
|
||||
return Err(TiffError::FormatError(
|
||||
TiffFormatError::InconsistentSizesEncountered,
|
||||
));
|
||||
|
||||
+33
-19
@@ -469,26 +469,9 @@ impl<W: Write + Seek> TiffEncoder<W> {
|
||||
where
|
||||
[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 mut image: ImageEncoder<W, C> = ImageEncoder::new(encoder, width, height)?;
|
||||
|
||||
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()
|
||||
let image: ImageEncoder<W, C> = ImageEncoder::new(encoder, width, height)?;
|
||||
image.write_data(data)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -610,10 +593,14 @@ impl<'a, W: Write + Seek> Drop for DirectoryEncoder<'a, W> {
|
||||
/// # let mut file = std::io::Cursor::new(Vec::new());
|
||||
/// # let image_data = vec![0; 100*100*3];
|
||||
/// use tiff::encoder::*;
|
||||
/// use tiff::tags::Tag;
|
||||
///
|
||||
/// let mut tiff = TiffEncoder::new(&mut file).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;
|
||||
/// while image.next_strip_sample_count() > 0 {
|
||||
/// let sample_count = image.next_strip_sample_count() as usize;
|
||||
@@ -623,11 +610,13 @@ impl<'a, W: Write + Seek> Drop for DirectoryEncoder<'a, W> {
|
||||
/// 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> {
|
||||
encoder: DirectoryEncoder<'a, W>,
|
||||
strip_idx: u64,
|
||||
strip_count: u64,
|
||||
row_samples: u64,
|
||||
width: u32,
|
||||
height: u32,
|
||||
rows_per_strip: u64,
|
||||
strip_offsets: Vec<u32>,
|
||||
@@ -672,6 +661,7 @@ impl<'a, W: 'a + Write + Seek, T: ColorType> ImageEncoder<'a, W, T> {
|
||||
strip_idx: 0,
|
||||
row_samples,
|
||||
rows_per_strip,
|
||||
width,
|
||||
height,
|
||||
strip_offsets: Vec::new(),
|
||||
strip_byte_count: Vec::new(),
|
||||
@@ -716,6 +706,30 @@ impl<'a, W: 'a + Write + Seek, T: ColorType> ImageEncoder<'a, W, T> {
|
||||
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
|
||||
pub fn resolution(&mut self, unit: ResolutionUnit, value: Rational) {
|
||||
self.encoder.write_tag(Tag::ResolutionUnit, unit.to_u16()).unwrap();
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@
|
||||
//! lossless and lossy compression.
|
||||
//!
|
||||
//! # 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 lzw;
|
||||
|
||||
@@ -114,6 +114,11 @@ pub enum Tag(u16) unknown("A private or extension tag") {
|
||||
YResolution = 283,
|
||||
// Advanced tags
|
||||
Predictor = 317,
|
||||
TileWidth = 322,
|
||||
TileLength = 323,
|
||||
TileOffsets = 324,
|
||||
TileByteCounts = 325,
|
||||
SampleFormat = 339,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -171,6 +171,12 @@ fn test_decode_data() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_69() {
|
||||
test_image_sum_u16("issue_69_lzw.tiff", ColorType::Gray(16), 1015486);
|
||||
test_image_sum_u16("issue_69_packbits.tiff", ColorType::Gray(16), 1015486);
|
||||
}
|
||||
|
||||
// TODO: GrayA support
|
||||
//#[test]
|
||||
//fn test_gray_alpha_u8()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
extern crate tiff;
|
||||
|
||||
use tiff::decoder::{Decoder, DecodingResult};
|
||||
use tiff::decoder::{Decoder, DecodingResult, ifd};
|
||||
use tiff::encoder::{colortype, TiffEncoder, SRational};
|
||||
use tiff::ColorType;
|
||||
use tiff::tags::Tag;
|
||||
@@ -24,14 +24,18 @@ fn encode_decode() {
|
||||
{
|
||||
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();
|
||||
image.encoder().write_tag(Tag::Artist, "Image-tiff").unwrap();
|
||||
image.write_data(&image_data).unwrap();
|
||||
|
||||
}
|
||||
{
|
||||
file.seek(SeekFrom::Start(0)).unwrap();
|
||||
let mut decoder = Decoder::new(&mut file).unwrap();
|
||||
assert_eq!(decoder.colortype().unwrap(), ColorType::RGB(8));
|
||||
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() {
|
||||
assert_eq!(image_data, img_res);
|
||||
} else {
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Reference in new issue
Block a user