- implement clippy's recommendations
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "tiffwrite"
|
name = "tiffwrite"
|
||||||
version = "2024.12.1"
|
version = "2025.1.0"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
authors = ["Wim Pomp <w.pomp@nki.nl>"]
|
authors = ["Wim Pomp <w.pomp@nki.nl>"]
|
||||||
license = "GPL-3.0-or-later"
|
license = "GPL-3.0-or-later"
|
||||||
|
|||||||
231
src/lib.rs
231
src/lib.rs
@@ -24,6 +24,7 @@ const OFFSET: u64 = 16;
|
|||||||
const COMPRESSION: u16 = 50000;
|
const COMPRESSION: u16 = 50000;
|
||||||
|
|
||||||
/// Image File Directory
|
/// Image File Directory
|
||||||
|
#[allow(clippy::upper_case_acronyms)]
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
struct IFD {
|
struct IFD {
|
||||||
tags: HashSet<Tag>,
|
tags: HashSet<Tag>,
|
||||||
@@ -42,23 +43,25 @@ impl IFD {
|
|||||||
tags.sort();
|
tags.sort();
|
||||||
ijtifffile.file.seek(SeekFrom::End(0))?;
|
ijtifffile.file.seek(SeekFrom::End(0))?;
|
||||||
if ijtifffile.file.stream_position()? % 2 == 1 {
|
if ijtifffile.file.stream_position()? % 2 == 1 {
|
||||||
ijtifffile.file.write(&[0])?;
|
ijtifffile.file.write_all(&[0])?;
|
||||||
}
|
}
|
||||||
let offset = ijtifffile.file.stream_position()?;
|
let offset = ijtifffile.file.stream_position()?;
|
||||||
ijtifffile.file.write(&(tags.len() as u64).to_le_bytes())?;
|
ijtifffile
|
||||||
|
.file
|
||||||
|
.write_all(&(tags.len() as u64).to_le_bytes())?;
|
||||||
|
|
||||||
for tag in tags.iter_mut() {
|
for tag in tags.iter_mut() {
|
||||||
tag.write_tag(ijtifffile)?;
|
tag.write_tag(ijtifffile)?;
|
||||||
}
|
}
|
||||||
let where_to_write_next_ifd_offset = ijtifffile.file.stream_position()?;
|
let where_to_write_next_ifd_offset = ijtifffile.file.stream_position()?;
|
||||||
ijtifffile.file.write(&vec![0u8; OFFSET_SIZE])?;
|
ijtifffile.file.write_all(&[0; OFFSET_SIZE])?;
|
||||||
for tag in tags.iter() {
|
for tag in tags.iter() {
|
||||||
tag.write_data(ijtifffile)?;
|
tag.write_data(ijtifffile)?;
|
||||||
}
|
}
|
||||||
ijtifffile
|
ijtifffile
|
||||||
.file
|
.file
|
||||||
.seek(SeekFrom::Start(where_to_write_offset))?;
|
.seek(SeekFrom::Start(where_to_write_offset))?;
|
||||||
ijtifffile.file.write(&offset.to_le_bytes())?;
|
ijtifffile.file.write_all(&offset.to_le_bytes())?;
|
||||||
Ok(where_to_write_next_ifd_offset)
|
Ok(where_to_write_next_ifd_offset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -116,36 +119,28 @@ impl Tag {
|
|||||||
Tag::new(code, bytes, 2)
|
Tag::new(code, bytes, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn short(code: u16, value: &Vec<u16>) -> Self {
|
pub fn short(code: u16, value: &[u16]) -> Self {
|
||||||
Tag::new(
|
Tag::new(
|
||||||
code,
|
code,
|
||||||
value
|
value.iter().flat_map(|x| x.to_le_bytes()).collect(),
|
||||||
.into_iter()
|
|
||||||
.map(|x| x.to_le_bytes())
|
|
||||||
.flatten()
|
|
||||||
.collect(),
|
|
||||||
3,
|
3,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn long(code: u16, value: &Vec<u32>) -> Self {
|
pub fn long(code: u16, value: &[u32]) -> Self {
|
||||||
Tag::new(
|
Tag::new(
|
||||||
code,
|
code,
|
||||||
value
|
value.iter().flat_map(|x| x.to_le_bytes()).collect(),
|
||||||
.into_iter()
|
|
||||||
.map(|x| x.to_le_bytes())
|
|
||||||
.flatten()
|
|
||||||
.collect(),
|
|
||||||
4,
|
4,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rational(code: u16, value: &Vec<Rational32>) -> Self {
|
pub fn rational(code: u16, value: &[Rational32]) -> Self {
|
||||||
Tag::new(
|
Tag::new(
|
||||||
code,
|
code,
|
||||||
value
|
value
|
||||||
.into_iter()
|
.iter()
|
||||||
.map(|x| {
|
.flat_map(|x| {
|
||||||
u32::try_from(*x.denom())
|
u32::try_from(*x.denom())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_le_bytes()
|
.to_le_bytes()
|
||||||
@@ -153,168 +148,128 @@ impl Tag {
|
|||||||
.chain(u32::try_from(*x.numer()).unwrap().to_le_bytes())
|
.chain(u32::try_from(*x.numer()).unwrap().to_le_bytes())
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
})
|
})
|
||||||
.flatten()
|
|
||||||
.collect(),
|
.collect(),
|
||||||
5,
|
5,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sbyte(code: u16, value: &Vec<i8>) -> Self {
|
pub fn sbyte(code: u16, value: &[i8]) -> Self {
|
||||||
Tag::new(
|
Tag::new(
|
||||||
code,
|
code,
|
||||||
value.iter().map(|x| x.to_le_bytes()).flatten().collect(),
|
value.iter().flat_map(|x| x.to_le_bytes()).collect(),
|
||||||
6,
|
6,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sshort(code: u16, value: &Vec<i16>) -> Self {
|
pub fn sshort(code: u16, value: &[i16]) -> Self {
|
||||||
Tag::new(
|
Tag::new(
|
||||||
code,
|
code,
|
||||||
value
|
value.iter().flat_map(|x| x.to_le_bytes()).collect(),
|
||||||
.into_iter()
|
|
||||||
.map(|x| x.to_le_bytes())
|
|
||||||
.flatten()
|
|
||||||
.collect(),
|
|
||||||
8,
|
8,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn slong(code: u16, value: &Vec<i32>) -> Self {
|
pub fn slong(code: u16, value: &[i32]) -> Self {
|
||||||
Tag::new(
|
Tag::new(
|
||||||
code,
|
code,
|
||||||
value
|
value.iter().flat_map(|x| x.to_le_bytes()).collect(),
|
||||||
.into_iter()
|
|
||||||
.map(|x| x.to_le_bytes())
|
|
||||||
.flatten()
|
|
||||||
.collect(),
|
|
||||||
9,
|
9,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn srational(code: u16, value: &Vec<Rational32>) -> Self {
|
pub fn srational(code: u16, value: &[Rational32]) -> Self {
|
||||||
Tag::new(
|
Tag::new(
|
||||||
code,
|
code,
|
||||||
value
|
value
|
||||||
.into_iter()
|
.iter()
|
||||||
.map(|x| {
|
.flat_map(|x| {
|
||||||
i32::try_from(*x.denom())
|
x.denom()
|
||||||
.unwrap()
|
|
||||||
.to_le_bytes()
|
.to_le_bytes()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain(i32::try_from(*x.numer()).unwrap().to_le_bytes())
|
.chain(x.numer().to_le_bytes())
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
})
|
})
|
||||||
.flatten()
|
|
||||||
.collect(),
|
.collect(),
|
||||||
10,
|
10,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn float(code: u16, value: &Vec<f32>) -> Self {
|
pub fn float(code: u16, value: &[f32]) -> Self {
|
||||||
Tag::new(
|
Tag::new(
|
||||||
code,
|
code,
|
||||||
value
|
value.iter().flat_map(|x| x.to_le_bytes()).collect(),
|
||||||
.into_iter()
|
|
||||||
.map(|x| x.to_le_bytes())
|
|
||||||
.flatten()
|
|
||||||
.collect(),
|
|
||||||
11,
|
11,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn double(code: u16, value: &Vec<f64>) -> Self {
|
pub fn double(code: u16, value: &[f64]) -> Self {
|
||||||
Tag::new(
|
Tag::new(
|
||||||
code,
|
code,
|
||||||
value
|
value.iter().flat_map(|x| x.to_le_bytes()).collect(),
|
||||||
.into_iter()
|
|
||||||
.map(|x| x.to_le_bytes())
|
|
||||||
.flatten()
|
|
||||||
.collect(),
|
|
||||||
12,
|
12,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ifd(code: u16, value: &Vec<u32>) -> Self {
|
pub fn ifd(code: u16, value: &[u32]) -> Self {
|
||||||
Tag::new(
|
Tag::new(
|
||||||
code,
|
code,
|
||||||
value
|
value.iter().flat_map(|x| x.to_le_bytes()).collect(),
|
||||||
.into_iter()
|
|
||||||
.map(|x| x.to_le_bytes())
|
|
||||||
.flatten()
|
|
||||||
.collect(),
|
|
||||||
13,
|
13,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unicode(code: u16, value: &str) -> Self {
|
pub fn unicode(code: u16, value: &str) -> Self {
|
||||||
let mut bytes: Vec<u8> = value
|
let mut bytes: Vec<u8> = value.encode_utf16().flat_map(|x| x.to_le_bytes()).collect();
|
||||||
.encode_utf16()
|
|
||||||
.map(|x| x.to_le_bytes())
|
|
||||||
.flatten()
|
|
||||||
.collect();
|
|
||||||
bytes.push(0);
|
bytes.push(0);
|
||||||
Tag::new(code, bytes, 14)
|
Tag::new(code, bytes, 14)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn complex(code: u16, value: &Vec<Complex<f32>>) -> Self {
|
pub fn complex(code: u16, value: &[Complex<f32>]) -> Self {
|
||||||
Tag::new(
|
Tag::new(
|
||||||
code,
|
code,
|
||||||
value
|
value
|
||||||
.into_iter()
|
.iter()
|
||||||
.map(|x| {
|
.flat_map(|x| {
|
||||||
x.re.to_le_bytes()
|
x.re.to_le_bytes()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain(x.im.to_le_bytes())
|
.chain(x.im.to_le_bytes())
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
})
|
})
|
||||||
.flatten()
|
|
||||||
.collect(),
|
.collect(),
|
||||||
15,
|
15,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn long8(code: u16, value: &Vec<u64>) -> Self {
|
pub fn long8(code: u16, value: &[u64]) -> Self {
|
||||||
Tag::new(
|
Tag::new(
|
||||||
code,
|
code,
|
||||||
value
|
value.iter().flat_map(|x| x.to_le_bytes()).collect(),
|
||||||
.into_iter()
|
|
||||||
.map(|x| x.to_le_bytes())
|
|
||||||
.flatten()
|
|
||||||
.collect(),
|
|
||||||
16,
|
16,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn slong8(code: u16, value: &Vec<i64>) -> Self {
|
pub fn slong8(code: u16, value: &[i64]) -> Self {
|
||||||
Tag::new(
|
Tag::new(
|
||||||
code,
|
code,
|
||||||
value
|
value.iter().flat_map(|x| x.to_le_bytes()).collect(),
|
||||||
.into_iter()
|
|
||||||
.map(|x| x.to_le_bytes())
|
|
||||||
.flatten()
|
|
||||||
.collect(),
|
|
||||||
17,
|
17,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ifd8(code: u16, value: &Vec<u64>) -> Self {
|
pub fn ifd8(code: u16, value: &[u64]) -> Self {
|
||||||
Tag::new(
|
Tag::new(
|
||||||
code,
|
code,
|
||||||
value
|
value.iter().flat_map(|x| x.to_le_bytes()).collect(),
|
||||||
.into_iter()
|
|
||||||
.map(|x| x.to_le_bytes())
|
|
||||||
.flatten()
|
|
||||||
.collect(),
|
|
||||||
18,
|
18,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn short_long_or_long8(code: u16, value: &Vec<u64>) -> Self {
|
pub fn short_long_or_long8(code: u16, value: &[u64]) -> Self {
|
||||||
let m = *value.iter().max().unwrap();
|
let m = *value.iter().max().unwrap();
|
||||||
if m < 65536 {
|
if m < 65536 {
|
||||||
Tag::short(code, &value.into_iter().map(|x| *x as u16).collect())
|
Tag::short(code, &value.iter().map(|x| *x as u16).collect::<Vec<_>>())
|
||||||
} else if m < 4294967296 {
|
} else if m < 4294967296 {
|
||||||
Tag::long(code, &value.into_iter().map(|x| *x as u32).collect())
|
Tag::long(code, &value.iter().map(|x| *x as u32).collect::<Vec<_>>())
|
||||||
} else {
|
} else {
|
||||||
Tag::long8(code, value)
|
Tag::long8(code, value)
|
||||||
}
|
}
|
||||||
@@ -348,16 +303,16 @@ impl Tag {
|
|||||||
|
|
||||||
fn write_tag(&mut self, ijtifffile: &mut IJTiffFile) -> Result<()> {
|
fn write_tag(&mut self, ijtifffile: &mut IJTiffFile) -> Result<()> {
|
||||||
self.offset = ijtifffile.file.stream_position()?;
|
self.offset = ijtifffile.file.stream_position()?;
|
||||||
ijtifffile.file.write(&self.code.to_le_bytes())?;
|
ijtifffile.file.write_all(&self.code.to_le_bytes())?;
|
||||||
ijtifffile.file.write(&self.ttype.to_le_bytes())?;
|
ijtifffile.file.write_all(&self.ttype.to_le_bytes())?;
|
||||||
ijtifffile.file.write(&self.count().to_le_bytes())?;
|
ijtifffile.file.write_all(&self.count().to_le_bytes())?;
|
||||||
if self.bytes.len() <= OFFSET_SIZE {
|
if self.bytes.len() <= OFFSET_SIZE {
|
||||||
ijtifffile.file.write(&self.bytes)?;
|
ijtifffile.file.write_all(&self.bytes)?;
|
||||||
for _ in self.bytes.len()..OFFSET_SIZE {
|
ijtifffile
|
||||||
ijtifffile.file.write(&[0])?;
|
.file
|
||||||
}
|
.write_all(&vec![0; OFFSET_SIZE - self.bytes.len()])?;
|
||||||
} else {
|
} else {
|
||||||
ijtifffile.file.write(&vec![0u8; OFFSET_SIZE])?;
|
ijtifffile.file.write_all(&[0; OFFSET_SIZE])?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -369,9 +324,9 @@ impl Tag {
|
|||||||
ijtifffile.file.seek(SeekFrom::Start(
|
ijtifffile.file.seek(SeekFrom::Start(
|
||||||
self.offset + (TAG_SIZE - OFFSET_SIZE) as u64,
|
self.offset + (TAG_SIZE - OFFSET_SIZE) as u64,
|
||||||
))?;
|
))?;
|
||||||
ijtifffile.file.write(&offset.to_le_bytes())?;
|
ijtifffile.file.write_all(&offset.to_le_bytes())?;
|
||||||
if ijtifffile.file.stream_position()? % 2 == 1 {
|
if ijtifffile.file.stream_position()? % 2 == 1 {
|
||||||
ijtifffile.file.write(&[0u8])?;
|
ijtifffile.file.write_all(&[0])?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@@ -397,8 +352,7 @@ impl CompressedFrame {
|
|||||||
let shape = frame.shape();
|
let shape = frame.shape();
|
||||||
let tile_size = 2usize
|
let tile_size = 2usize
|
||||||
.pow(((shape[0] as f64 * shape[1] as f64 / 2f64).log2() / 2f64).round() as u32)
|
.pow(((shape[0] as f64 * shape[1] as f64 / 2f64).log2() / 2f64).round() as u32)
|
||||||
.max(16)
|
.clamp(16, 1024);
|
||||||
.min(1024);
|
|
||||||
|
|
||||||
let tile_width = tile_size;
|
let tile_width = tile_size;
|
||||||
let tile_length = tile_size;
|
let tile_length = tile_size;
|
||||||
@@ -482,16 +436,6 @@ impl CompressedFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// loop until all bytes are encoded
|
|
||||||
fn write(encoder: &mut Encoder<&mut Vec<u8>>, buf: &[u8]) -> Result<()> {
|
|
||||||
let b = buf.len();
|
|
||||||
let mut w = 0;
|
|
||||||
while w < b {
|
|
||||||
w += encoder.write(&buf[w..])?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn compress_tile<T>(
|
fn compress_tile<T>(
|
||||||
frame: ArcArray2<T>,
|
frame: ArcArray2<T>,
|
||||||
slice: (usize, usize, usize, usize),
|
slice: (usize, usize, usize, usize),
|
||||||
@@ -510,8 +454,7 @@ impl CompressedFrame {
|
|||||||
encoder.include_checksum(true)?;
|
encoder.include_checksum(true)?;
|
||||||
let shape = (slice.1 - slice.0, slice.3 - slice.2);
|
let shape = (slice.1 - slice.0, slice.3 - slice.2);
|
||||||
for i in 0..shape.0 {
|
for i in 0..shape.0 {
|
||||||
CompressedFrame::write(
|
encoder.write_all(
|
||||||
&mut encoder,
|
|
||||||
&frame
|
&frame
|
||||||
.slice(s![slice.0..slice.1, slice.2..slice.3])
|
.slice(s![slice.0..slice.1, slice.2..slice.3])
|
||||||
.slice(s![i, ..])
|
.slice(s![i, ..])
|
||||||
@@ -520,15 +463,12 @@ impl CompressedFrame {
|
|||||||
.flatten()
|
.flatten()
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>(),
|
||||||
)?;
|
)?;
|
||||||
CompressedFrame::write(
|
encoder.write_all(&vec![0; bytes_per_sample * (tile_width - shape.1)])?;
|
||||||
&mut encoder,
|
|
||||||
&vec![0u8; bytes_per_sample * (tile_width - shape.1)],
|
|
||||||
)?;
|
|
||||||
}
|
}
|
||||||
CompressedFrame::write(
|
encoder.write_all(&vec![
|
||||||
&mut encoder,
|
0;
|
||||||
&vec![0u8; bytes_per_sample * tile_width * (tile_length - shape.0)],
|
bytes_per_sample * tile_width * (tile_length - shape.0)
|
||||||
)?;
|
])?;
|
||||||
encoder.finish()?;
|
encoder.finish()?;
|
||||||
Ok(dest)
|
Ok(dest)
|
||||||
}
|
}
|
||||||
@@ -547,6 +487,7 @@ struct Frame {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Frame {
|
impl Frame {
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
fn new(
|
fn new(
|
||||||
offsets: Vec<u64>,
|
offsets: Vec<u64>,
|
||||||
bytecounts: Vec<u64>,
|
bytecounts: Vec<u64>,
|
||||||
@@ -663,11 +604,11 @@ impl IJTiffFile {
|
|||||||
.write(true)
|
.write(true)
|
||||||
.read(true)
|
.read(true)
|
||||||
.open(path)?;
|
.open(path)?;
|
||||||
file.write(b"II")?;
|
file.write_all(b"II")?;
|
||||||
file.write(&43u16.to_le_bytes())?;
|
file.write_all(&43u16.to_le_bytes())?;
|
||||||
file.write(&8u16.to_le_bytes())?;
|
file.write_all(&8u16.to_le_bytes())?;
|
||||||
file.write(&0u16.to_le_bytes())?;
|
file.write_all(&0u16.to_le_bytes())?;
|
||||||
file.write(&OFFSET.to_le_bytes())?;
|
file.write_all(&OFFSET.to_le_bytes())?;
|
||||||
Ok(IJTiffFile {
|
Ok(IJTiffFile {
|
||||||
file,
|
file,
|
||||||
frames: HashMap::new(),
|
frames: HashMap::new(),
|
||||||
@@ -753,7 +694,7 @@ impl IJTiffFile {
|
|||||||
fn hash_check(&mut self, bytes: &Vec<u8>, offset: u64) -> Result<bool> {
|
fn hash_check(&mut self, bytes: &Vec<u8>, offset: u64) -> Result<bool> {
|
||||||
let current_offset = self.file.stream_position()?;
|
let current_offset = self.file.stream_position()?;
|
||||||
self.file.seek(SeekFrom::Start(offset))?;
|
self.file.seek(SeekFrom::Start(offset))?;
|
||||||
let mut buffer = vec![0u8; bytes.len()];
|
let mut buffer = vec![0; bytes.len()];
|
||||||
self.file.read_exact(&mut buffer)?;
|
self.file.read_exact(&mut buffer)?;
|
||||||
let same = bytes == &buffer;
|
let same = bytes == &buffer;
|
||||||
self.file.seek(SeekFrom::Start(current_offset))?;
|
self.file.seek(SeekFrom::Start(current_offset))?;
|
||||||
@@ -763,16 +704,16 @@ impl IJTiffFile {
|
|||||||
fn write(&mut self, bytes: &Vec<u8>) -> Result<u64> {
|
fn write(&mut self, bytes: &Vec<u8>) -> Result<u64> {
|
||||||
let hash = IJTiffFile::hash(&bytes);
|
let hash = IJTiffFile::hash(&bytes);
|
||||||
if self.hashes.contains_key(&hash)
|
if self.hashes.contains_key(&hash)
|
||||||
&& self.hash_check(&bytes, *self.hashes.get(&hash).unwrap())?
|
&& self.hash_check(bytes, *self.hashes.get(&hash).unwrap())?
|
||||||
{
|
{
|
||||||
Ok(*self.hashes.get(&hash).unwrap())
|
Ok(*self.hashes.get(&hash).unwrap())
|
||||||
} else {
|
} else {
|
||||||
if self.file.stream_position()? % 2 == 1 {
|
if self.file.stream_position()? % 2 == 1 {
|
||||||
self.file.write(&[0])?;
|
self.file.write_all(&[0])?;
|
||||||
}
|
}
|
||||||
let offset = self.file.stream_position()?;
|
let offset = self.file.stream_position()?;
|
||||||
self.hashes.insert(hash, offset);
|
self.hashes.insert(hash, offset);
|
||||||
self.file.write(&bytes)?;
|
self.file.write_all(bytes)?;
|
||||||
Ok(offset)
|
Ok(offset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -892,32 +833,32 @@ impl IJTiffFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut ifd = IFD::new();
|
let mut ifd = IFD::new();
|
||||||
ifd.tags.insert(Tag::long(256, &vec![frame.image_width]));
|
ifd.tags.insert(Tag::long(256, &[frame.image_width]));
|
||||||
ifd.tags.insert(Tag::long(257, &vec![frame.image_length]));
|
ifd.tags.insert(Tag::long(257, &[frame.image_length]));
|
||||||
ifd.tags
|
ifd.tags
|
||||||
.insert(Tag::short(258, &vec![frame.bits_per_sample; frame_count]));
|
.insert(Tag::short(258, &vec![frame.bits_per_sample; frame_count]));
|
||||||
ifd.tags.insert(Tag::short(259, &vec![COMPRESSION]));
|
ifd.tags.insert(Tag::short(259, &[COMPRESSION]));
|
||||||
ifd.tags
|
ifd.tags
|
||||||
.insert(Tag::ascii(270, &self.description(c_size, z_size, t_size)));
|
.insert(Tag::ascii(270, &self.description(c_size, z_size, t_size)));
|
||||||
ifd.tags.insert(Tag::short(277, &vec![frame_count as u16]));
|
ifd.tags.insert(Tag::short(277, &[frame_count as u16]));
|
||||||
ifd.tags.insert(Tag::ascii(305, "tiffwrite_rs"));
|
ifd.tags.insert(Tag::ascii(305, "tiffwrite_rs"));
|
||||||
ifd.tags.insert(Tag::short(322, &vec![frame.tile_width]));
|
ifd.tags.insert(Tag::short(322, &[frame.tile_width]));
|
||||||
ifd.tags.insert(Tag::short(323, &vec![frame.tile_length]));
|
ifd.tags.insert(Tag::short(323, &[frame.tile_length]));
|
||||||
ifd.tags.insert(Tag::short_long_or_long8(324, &offsets));
|
ifd.tags.insert(Tag::short_long_or_long8(324, &offsets));
|
||||||
ifd.tags.insert(Tag::short_long_or_long8(325, &bytecounts));
|
ifd.tags.insert(Tag::short_long_or_long8(325, &bytecounts));
|
||||||
if frame.sample_format > 1 {
|
if frame.sample_format > 1 {
|
||||||
ifd.tags.insert(Tag::short(339, &vec![frame.sample_format]));
|
ifd.tags.insert(Tag::short(339, &[frame.sample_format]));
|
||||||
}
|
}
|
||||||
if let Some(px_size) = self.px_size {
|
if let Some(px_size) = self.px_size {
|
||||||
let r = vec![Rational32::from_f64(px_size).unwrap()];
|
let r = [Rational32::from_f64(px_size).unwrap()];
|
||||||
ifd.tags.insert(Tag::rational(282, &r));
|
ifd.tags.insert(Tag::rational(282, &r));
|
||||||
ifd.tags.insert(Tag::rational(283, &r));
|
ifd.tags.insert(Tag::rational(283, &r));
|
||||||
ifd.tags.insert(Tag::short(296, &vec![1]));
|
ifd.tags.insert(Tag::short(296, &[1]));
|
||||||
}
|
}
|
||||||
if let Colors::Colormap(_) = &self.colors {
|
if let Colors::Colormap(_) = &self.colors {
|
||||||
ifd.tags.insert(Tag::short(262, &vec![3]));
|
ifd.tags.insert(Tag::short(262, &[3]));
|
||||||
} else if let Colors::None = self.colors {
|
} else if let Colors::None = self.colors {
|
||||||
ifd.tags.insert(Tag::short(262, &vec![1]));
|
ifd.tags.insert(Tag::short(262, &[1]));
|
||||||
}
|
}
|
||||||
if frame_number == 0 {
|
if frame_number == 0 {
|
||||||
if let Colors::Colormap(colormap) = &self.colors {
|
if let Colors::Colormap(colormap) = &self.colors {
|
||||||
@@ -933,12 +874,12 @@ impl IJTiffFile {
|
|||||||
320,
|
320,
|
||||||
&self.get_color(&colors[frame_number], frame.bits_per_sample),
|
&self.get_color(&colors[frame_number], frame.bits_per_sample),
|
||||||
));
|
));
|
||||||
ifd.tags.insert(Tag::short(262, &vec![3]));
|
ifd.tags.insert(Tag::short(262, &[3]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Colors::None = &self.colors {
|
if let Colors::None = &self.colors {
|
||||||
if c_size > 1 {
|
if c_size > 1 {
|
||||||
ifd.tags.insert(Tag::short(284, &vec![2]));
|
ifd.tags.insert(Tag::short(284, &[2]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for channel in 0..samples_per_pixel {
|
for channel in 0..samples_per_pixel {
|
||||||
@@ -964,7 +905,7 @@ impl IJTiffFile {
|
|||||||
} else {
|
} else {
|
||||||
warn.push((frame_number, 0));
|
warn.push((frame_number, 0));
|
||||||
}
|
}
|
||||||
if warn.len() > 0 {
|
if !warn.is_empty() {
|
||||||
println!("The following frames were not added to the tif file:");
|
println!("The following frames were not added to the tif file:");
|
||||||
for (frame_number, channel) in &warn {
|
for (frame_number, channel) in &warn {
|
||||||
let (c, z, t) = self.get_czt(*frame_number, *channel, c_size, z_size);
|
let (c, z, t) = self.get_czt(*frame_number, *channel, c_size, z_size);
|
||||||
@@ -978,7 +919,7 @@ impl IJTiffFile {
|
|||||||
}
|
}
|
||||||
self.file
|
self.file
|
||||||
.seek(SeekFrom::Start(where_to_write_next_ifd_offset))?;
|
.seek(SeekFrom::Start(where_to_write_next_ifd_offset))?;
|
||||||
self.file.write(&0u64.to_le_bytes())?;
|
self.file.write_all(&0u64.to_le_bytes())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
10
src/py.rs
10
src/py.rs
@@ -50,7 +50,7 @@ impl PyTag {
|
|||||||
&rational
|
&rational
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|x| Rational32::from_f64(x).unwrap())
|
.map(|x| Rational32::from_f64(x).unwrap())
|
||||||
.collect(),
|
.collect::<Vec<_>>(),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -84,7 +84,7 @@ impl PyTag {
|
|||||||
&srational
|
&srational
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|x| Rational32::from_f64(x).unwrap())
|
.map(|x| Rational32::from_f64(x).unwrap())
|
||||||
.collect(),
|
.collect::<Vec<_>>(),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -125,7 +125,7 @@ impl PyTag {
|
|||||||
&complex
|
&complex
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(x, y)| Complex { re: x, im: y })
|
.map(|(x, y)| Complex { re: x, im: y })
|
||||||
.collect(),
|
.collect::<Vec<_>>(),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -176,7 +176,7 @@ impl PyIJTiffFile {
|
|||||||
/// set zstd compression level: -7 ..= 22
|
/// set zstd compression level: -7 ..= 22
|
||||||
fn set_compression_level(&mut self, compression_level: i32) {
|
fn set_compression_level(&mut self, compression_level: i32) {
|
||||||
if let Some(ref mut ijtifffile) = self.ijtifffile {
|
if let Some(ref mut ijtifffile) = self.ijtifffile {
|
||||||
ijtifffile.compression_level = compression_level.max(-7).min(22);
|
ijtifffile.compression_level = compression_level.clamp(-7, 22);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -294,6 +294,7 @@ impl PyIJTiffFile {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[pyo3(signature = (tag, czt=None))]
|
||||||
fn append_extra_tag(&mut self, tag: PyTag, czt: Option<(usize, usize, usize)>) {
|
fn append_extra_tag(&mut self, tag: PyTag, czt: Option<(usize, usize, usize)>) {
|
||||||
if let Some(ijtifffile) = self.ijtifffile.as_mut() {
|
if let Some(ijtifffile) = self.ijtifffile.as_mut() {
|
||||||
if let Some(extra_tags) = ijtifffile.extra_tags.get_mut(&czt) {
|
if let Some(extra_tags) = ijtifffile.extra_tags.get_mut(&czt) {
|
||||||
@@ -302,6 +303,7 @@ impl PyIJTiffFile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[pyo3(signature = (czt=None))]
|
||||||
fn get_tags(&self, czt: Option<(usize, usize, usize)>) -> PyResult<Vec<PyTag>> {
|
fn get_tags(&self, czt: Option<(usize, usize, usize)>) -> PyResult<Vec<PyTag>> {
|
||||||
if let Some(ijtifffile) = &self.ijtifffile {
|
if let Some(ijtifffile) = &self.ijtifffile {
|
||||||
if let Some(extra_tags) = ijtifffile.extra_tags.get(&czt) {
|
if let Some(extra_tags) = ijtifffile.extra_tags.get(&czt) {
|
||||||
|
|||||||
Reference in New Issue
Block a user