diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 4c16c36..14a7d0d 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -27,10 +27,10 @@ jobs: - runner: ubuntu-latest target: ppc64le steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - uses: actions/checkout@v6 + - uses: actions/setup-python@v6 with: - python-version: '3.10' + python-version: '3.13' - name: Build wheels uses: PyO3/maturin-action@v1 with: @@ -39,7 +39,7 @@ jobs: sccache: 'true' manylinux: auto - name: Upload wheels - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: wheels-linux-${{ matrix.platform.target }} path: dist @@ -55,10 +55,10 @@ jobs: # - runner: windows-latest # target: x86 steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - uses: actions/checkout@v6 + - uses: actions/setup-python@v6 with: - python-version: '3.10' + python-version: '3.13' architecture: ${{ matrix.platform.target }} - name: Build wheels uses: PyO3/maturin-action@v1 @@ -67,7 +67,7 @@ jobs: args: --release --out dist sccache: 'true' - name: Upload wheels - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: wheels-windows-${{ matrix.platform.target }} path: dist @@ -83,10 +83,10 @@ jobs: - runner: macos-14 target: aarch64 steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - uses: actions/checkout@v6 + - uses: actions/setup-python@v6 with: - python-version: '3.10' + python-version: '3.13' - name: Build wheels uses: PyO3/maturin-action@v1 with: @@ -94,7 +94,7 @@ jobs: args: --release --out dist sccache: 'true' - name: Upload wheels - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: wheels-macos-${{ matrix.platform.target }} path: dist @@ -103,14 +103,14 @@ jobs: needs: [ publish_pytest ] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Build sdist uses: PyO3/maturin-action@v1 with: command: sdist args: --out dist - name: Upload sdist - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: wheels-sdist path: dist @@ -120,7 +120,7 @@ jobs: runs-on: ubuntu-latest needs: [linux, windows, macos, sdist] steps: - - uses: actions/download-artifact@v4 + - uses: actions/download-artifact@v7 - name: Publish to PyPI uses: PyO3/maturin-action@v1 env: @@ -135,12 +135,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 25 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@stable - name: cargo-release Cache id: cargo_release_cache - uses: actions/cache@v3 + uses: actions/cache@v5 with: path: ~/.cargo/bin/cargo-release key: ${{ runner.os }}-cargo-release diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index b066019..30106bb 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -7,13 +7,13 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - python-version: ["3.10", "3.12"] + python-version: ["3.10", "3.12", "3.13"] os: [ubuntu-latest, windows-latest, macOS-latest] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: ${{ matrix.python-version }} - name: Install diff --git a/Cargo.toml b/Cargo.toml index 8cb6ec3..6b9d1b1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tiffwrite" -version = "2025.9.1" +version = "2025.12.0" edition = "2024" rust-version = "1.85.1" authors = ["Wim Pomp "] @@ -18,20 +18,20 @@ name = "tiffwrite" crate-type = ["cdylib", "rlib"] [dependencies] -colorcet = "0.2.1" -colorgrad = "0.7.2" -chrono = "0.4.41" -css-color = "0.2.8" -flate2 = "1.1.1" -ndarray = "0.16.1" -num = "0.4.3" -numpy = { version = "0.25.0", optional = true } -rayon = "1.10.0" -thiserror = "2.0.16" -zstd = "0.13.3" +colorcet = "0.2" +colorgrad = "0.8" +chrono = "0.4" +css-color = "0.2" +flate2 = "1" +ndarray = "0.17" +num = "0.4" +numpy = { version = "0.27", optional = true } +rayon = "1" +thiserror = "2" +zstd = "0.13" [dependencies.pyo3] -version = "0.25.1" +version = "0.27" features = ["extension-module", "abi3-py310", "generate-import-lib", "anyhow", "multiple-pymethods"] optional = true diff --git a/src/error.rs b/src/error.rs index f3da639..ae9726f 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,14 +1,13 @@ use thiserror::Error; - #[derive(Debug, Error)] pub enum Error { - #[error("io error: {0}")] + #[error(transparent)] IO(#[from] std::io::Error), + #[error(transparent)] + ColorCet(#[from] colorcet::ColorcetError), #[error("could not parse color: {0}")] ColorParse(String), - #[error("colorcet error: {0}")] - ColorCet(#[from] colorcet::ColorcetError), #[error("could not covert ColorMap into LinearGradient")] - Conversion -} \ No newline at end of file + Conversion, +} diff --git a/src/lib.rs b/src/lib.rs index 575f3fe..e4fc544 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,8 @@ +pub mod error; #[cfg(feature = "python")] mod py; -pub mod error; +use crate::error::Error; use chrono::Utc; use colorcet::ColorMap; use colorgrad::{Gradient, LinearGradient}; @@ -23,7 +24,6 @@ use std::{ }; use zstd::zstd_safe::CompressionLevel; use zstd::{DEFAULT_COMPRESSION_LEVEL, stream::Encoder}; -use crate::error::Error; const TAG_SIZE: usize = 20; const OFFSET_SIZE: usize = 8; @@ -60,7 +60,11 @@ impl IFD { } } - fn write(&mut self, ijtifffile: &mut IJTiffFile, where_to_write_offset: u64) -> Result { + fn write( + &mut self, + ijtifffile: &mut IJTiffFile, + where_to_write_offset: u64, + ) -> Result { let mut tags = self.tags.drain().collect::>(); tags.sort(); ijtifffile.file.seek(SeekFrom::End(0))?; @@ -748,7 +752,10 @@ impl IJTiffFile { /// set colormap from named colormap (see [colorcet](https://crates.io/crates/colorcet)) pub fn set_colormap>(&mut self, name: S) -> Result<(), Error> { let name = name.as_ref(); - let colormap: LinearGradient = name.parse::()?.try_into().map_err(|_| Error::Conversion)?; + let colormap: LinearGradient = name + .parse::()? + .try_into() + .map_err(|_| Error::Conversion)?; let mut colormap = colormap .colors(256) .into_iter() @@ -896,7 +903,13 @@ impl IJTiffFile { Ok(()) } - fn write_frame(&mut self, frame: CompressedFrame, c: usize, z: usize, t: usize) -> Result<(), Error> { + fn write_frame( + &mut self, + frame: CompressedFrame, + c: usize, + z: usize, + t: usize, + ) -> Result<(), Error> { let mut offsets = Vec::new(); let mut bytecounts = Vec::new(); for tile in frame.bytes { diff --git a/src/py.rs b/src/py.rs index 6998fad..33fd70e 100644 --- a/src/py.rs +++ b/src/py.rs @@ -1,6 +1,6 @@ use crate::{Colors, Compression, IJTiffFile, Tag}; use num::{Complex, FromPrimitive, Rational32}; -use numpy::PyReadonlyArray2; +use numpy::{AllowTypeChange, PyArrayLike2}; use pyo3::exceptions::PyValueError; use pyo3::prelude::*; @@ -338,7 +338,7 @@ macro_rules! impl_save { impl PyIJTiffFile { fn $t( &mut self, - frame: PyReadonlyArray2<$T>, + frame: PyArrayLike2<$T, AllowTypeChange>, c: usize, t: usize, z: usize,