- no cloning if frame is owned already
This commit is contained in:
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "tiffwrite"
|
||||
version = "2026.5.0"
|
||||
version = "2026.5.1"
|
||||
edition = "2024"
|
||||
rust-version = "1.88.0"
|
||||
authors = ["Wim Pomp <w.pomp@nki.nl>"]
|
||||
|
||||
@@ -22,7 +22,7 @@ makes that very hard anyway.
|
||||
or
|
||||
|
||||
- install [rust](https://rustup.rs/)
|
||||
- ``` pip install tiffwrite@git+https://github.com/wimpomp/tiffwrite ```
|
||||
- ``` pip install tiffwrite@git+https://git.wimpomp.nl/wim/tiffwrite ```
|
||||
|
||||
## Usage
|
||||
### Write an image stack
|
||||
|
||||
@@ -29,10 +29,6 @@ dependencies = ["numpy", "tqdm"]
|
||||
[project.optional-dependencies]
|
||||
test = ["pytest", "tifffile", "imagecodecs"]
|
||||
|
||||
[project.urls]
|
||||
homepage = "https://github.com/wimpomp/tiffwrite"
|
||||
repository = "https://github.com/wimpomp/tiffwrite"
|
||||
|
||||
[project.scripts]
|
||||
tiffwrite_generate_stub = "tiffwrite:tiffwrite_generate_stub"
|
||||
|
||||
|
||||
+53
-12
@@ -9,7 +9,7 @@ use colorgrad::{Gradient, LinearGradient};
|
||||
use css_color::Srgb;
|
||||
use flate2::write::ZlibEncoder;
|
||||
use lazy_static::lazy_static;
|
||||
use ndarray::{ArcArray2, AsArray, Ix2, s};
|
||||
use ndarray::{Array, Array2, ArrayView, ArrayView2, Dimension, Ix2, s};
|
||||
use num::{Complex, FromPrimitive, Rational32, traits::ToBytes};
|
||||
use rayon::prelude::*;
|
||||
use std::collections::HashSet;
|
||||
@@ -380,7 +380,7 @@ impl Frame {
|
||||
fn new<T>(
|
||||
hashes: Arc<Mutex<HashMap<u64, u64>>>,
|
||||
file: Arc<Mutex<BufWriter<File>>>,
|
||||
frame: ArcArray2<T>,
|
||||
frame: Array2<T>,
|
||||
compression: Compression,
|
||||
) -> Result<Frame, Error>
|
||||
where
|
||||
@@ -434,14 +434,14 @@ impl Frame {
|
||||
slices
|
||||
.into_par_iter()
|
||||
.map(|slice| {
|
||||
Frame::compress_tile_deflate(frame.clone(), slice, tile_size, tile_size)
|
||||
Frame::compress_tile_deflate(frame.view(), slice, tile_size, tile_size)
|
||||
})
|
||||
.collect::<Result<Vec<_>, Error>>()?
|
||||
} else {
|
||||
slices
|
||||
.into_iter()
|
||||
.map(|slice| {
|
||||
Frame::compress_tile_deflate(frame.clone(), slice, tile_size, tile_size)
|
||||
Frame::compress_tile_deflate(frame.view(), slice, tile_size, tile_size)
|
||||
})
|
||||
.collect::<Result<Vec<_>, Error>>()?
|
||||
}
|
||||
@@ -453,7 +453,7 @@ impl Frame {
|
||||
.into_par_iter()
|
||||
.map(|slice| {
|
||||
Frame::compress_tile_zstd(
|
||||
frame.clone(),
|
||||
frame.view(),
|
||||
slice,
|
||||
tile_size,
|
||||
tile_size,
|
||||
@@ -466,7 +466,7 @@ impl Frame {
|
||||
.into_iter()
|
||||
.map(|slice| {
|
||||
Frame::compress_tile_zstd(
|
||||
frame.clone(),
|
||||
frame.view(),
|
||||
slice,
|
||||
tile_size,
|
||||
tile_size,
|
||||
@@ -501,7 +501,7 @@ impl Frame {
|
||||
|
||||
fn encode<W, T>(
|
||||
mut encoder: W,
|
||||
frame: ArcArray2<T>,
|
||||
frame: ArrayView2<T>,
|
||||
slice: (usize, usize, usize, usize),
|
||||
tile_width: usize,
|
||||
tile_length: usize,
|
||||
@@ -532,7 +532,7 @@ impl Frame {
|
||||
}
|
||||
|
||||
fn compress_tile_deflate<T>(
|
||||
frame: ArcArray2<T>,
|
||||
frame: ArrayView2<T>,
|
||||
slice: (usize, usize, usize, usize),
|
||||
tile_width: usize,
|
||||
tile_length: usize,
|
||||
@@ -546,7 +546,7 @@ impl Frame {
|
||||
}
|
||||
|
||||
fn compress_tile_zstd<T>(
|
||||
frame: ArcArray2<T>,
|
||||
frame: ArrayView2<T>,
|
||||
slice: (usize, usize, usize, usize),
|
||||
tile_width: usize,
|
||||
tile_length: usize,
|
||||
@@ -621,6 +621,47 @@ pub enum Colors {
|
||||
Colormap(Vec<Vec<u8>>),
|
||||
}
|
||||
|
||||
/// Clone if array is a view, do not clone if array is owned already.
|
||||
pub trait IntoOwnedArray<T, D> {
|
||||
fn into_owned(self) -> Array<T, D>;
|
||||
}
|
||||
|
||||
impl<T, D> IntoOwnedArray<T, D> for Array<T, D> {
|
||||
fn into_owned(self) -> Array<T, D> {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, D> IntoOwnedArray<T, D> for &Array<T, D>
|
||||
where
|
||||
T: Clone,
|
||||
D: Dimension,
|
||||
{
|
||||
fn into_owned(self) -> Array<T, D> {
|
||||
self.to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, D> IntoOwnedArray<T, D> for ArrayView<'_, T, D>
|
||||
where
|
||||
T: Clone,
|
||||
D: Dimension,
|
||||
{
|
||||
fn into_owned(self) -> Array<T, D> {
|
||||
self.to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, D> IntoOwnedArray<T, D> for &ArrayView<'_, T, D>
|
||||
where
|
||||
T: Clone,
|
||||
D: Dimension,
|
||||
{
|
||||
fn into_owned(self) -> Array<T, D> {
|
||||
self.to_owned()
|
||||
}
|
||||
}
|
||||
|
||||
/// save 2d arrays in a tif file compatible with Fiji/ImageJ
|
||||
#[derive(Debug)]
|
||||
pub struct IJTiffFile {
|
||||
@@ -842,15 +883,15 @@ impl IJTiffFile {
|
||||
}
|
||||
|
||||
/// save a 2d array to the tiff file at channel c, slice z, and time t
|
||||
pub fn save<'a, A, T>(&mut self, frame: A, c: usize, z: usize, t: usize) -> Result<(), Error>
|
||||
pub fn save<A, T>(&mut self, frame: A, c: usize, z: usize, t: usize) -> Result<(), Error>
|
||||
where
|
||||
A: AsArray<'a, T, Ix2>,
|
||||
A: IntoOwnedArray<T, Ix2>,
|
||||
T: Bytes + Clone + Send + Sync + 'static,
|
||||
{
|
||||
self.collect_threads(false, usize::from(available_parallelism()?))?;
|
||||
let hashes = self.hashes.clone();
|
||||
let file = self.file.clone();
|
||||
let frame = frame.into().to_shared();
|
||||
let frame = frame.into_owned();
|
||||
let compression = self.compression;
|
||||
self.threads.insert(
|
||||
(c, z, t),
|
||||
|
||||
Reference in New Issue
Block a user