- first commit

This commit is contained in:
Wim Pomp
2025-08-10 17:34:35 +02:00
commit 3e98e7e86f
11 changed files with 2813 additions and 0 deletions

1158
src/functions.rs Normal file

File diff suppressed because it is too large Load Diff

110
src/handle.rs Normal file
View File

@@ -0,0 +1,110 @@
use crate::misc::Ptr;
use crate::sys::*;
use std::mem::MaybeUninit;
use std::ops::Deref;
/// CZI-reader object.
#[derive(Clone, Debug)]
pub struct CziReader(pub (crate) CziReaderObjectHandle);
/// sub-block object.
#[derive(Clone, Debug)]
pub struct SubBlock(pub (crate) SubBlockObjectHandle);
/// input stream object.
#[derive(Clone, Debug)]
pub struct InputStream(pub (crate) InputStreamObjectHandle);
/// output stream object.
#[derive(Clone, Debug)]
pub struct OutputStream(pub (crate) OutputStreamObjectHandle);
/// memory allocation object - which is a pointer to a memory block, which must be
/// freed with 'libCZI_Free'.
/// TODO(JBL): this is not really used so far, should be removed I guess.
#[derive(Clone, Debug)]
pub struct MemoryAllocation(pub (crate) MemoryAllocationObjectHandle);
/// bitmap object.
#[derive(Clone, Debug)]
pub struct Bitmap(pub (crate) BitmapObjectHandle);
/// metadata segment object.
#[derive(Clone, Debug)]
pub struct MetadataSegment(pub (crate) MetadataSegmentObjectHandle);
/// attachment object.
#[derive(Clone, Debug)]
pub struct Attachment(pub (crate) AttachmentObjectHandle);
/// writer object.
#[derive(Clone, Debug)]
pub struct CziWriter(pub (crate) CziWriterObjectHandle);
/// single-channel-scaling-tile-accessor.
#[derive(Clone, Debug)]
pub struct SingleChannelScalingTileAccessor(pub (crate) SingleChannelScalingTileAccessorObjectHandle);
/// document info object.
#[derive(Clone, Debug)]
pub struct CziDocumentInfo(pub (crate) CziDocumentInfoHandle);
/// display settings object.
#[derive(Clone, Debug)]
pub struct DisplaySettings(pub (crate) DisplaySettingsHandle);
/// channel display settings object.
#[derive(Clone, Debug)]
pub struct ChannelDisplaySettings(pub (crate) ChannelDisplaySettingsHandle);
macro_rules! impl_struct {
($($n:ident: $t:ty: $s:ty $(,)?)*) => {
$(
impl $t {
#[allow(dead_code)]
pub (crate) fn handle(&self) -> ObjectHandle { self.0 }
}
impl Ptr for $t {
type Pointer = $s;
unsafe fn assume_init(ptr: MaybeUninit<Self::Pointer>) -> Self {
Self(unsafe { ptr.assume_init() })
}
fn as_mut_ptr(&self) -> *mut Self::Pointer {
&self.0 as *const _ as *mut _
}
fn as_ptr(&self) -> *const Self::Pointer {
&self.0 as *const _ as *const _
}
}
impl Deref for $t {
type Target = ObjectHandle;
fn deref(&self) -> &Self::Target {
&self.0
}
}
)*
};
}
impl_struct! {
CziReader: CziReader: CziReaderObjectHandle,
SubBlock: SubBlock: SubBlockObjectHandle,
InputStream: InputStream: InputStreamObjectHandle,
OutputStream: OutputStream: OutputStreamObjectHandle,
MemoryAllocation: MemoryAllocation: MemoryAllocationObjectHandle,
Bitmap: Bitmap: BitmapObjectHandle,
MetadataSegment: MetadataSegment: MetadataSegmentObjectHandle,
Attachment: Attachment: AttachmentObjectHandle,
CziWriter: CziWriter: CziWriterObjectHandle,
SingleChannelScalingTileAccessor: SingleChannelScalingTileAccessor: SingleChannelScalingTileAccessorObjectHandle,
CziDocumentInfo: CziDocumentInfo: CziDocumentInfoHandle,
DisplaySettings: DisplaySettings: DisplaySettingsHandle,
ChannelDisplaySettings: ChannelDisplaySettings: ChannelDisplaySettingsHandle,
}

1125
src/interop.rs Normal file

File diff suppressed because it is too large Load Diff

83
src/lib.rs Normal file
View File

@@ -0,0 +1,83 @@
mod functions;
mod handle;
mod interop;
mod misc;
pub mod sys;
pub use functions::*;
pub use handle::*;
pub use interop::*;
pub use misc::{LibCZIApiError, RawDataType, PixelType};
#[cfg(test)]
mod tests {
use crate::handle::{CziReader, InputStream};
use crate::interop::{LibCZIBuildInformation, ReaderOpenInfo};
use anyhow::{Error, Result};
use std::env;
#[test]
fn test_libczi_xml() -> Result<()> {
let path = env::home_dir()
.unwrap()
.join("code/rust/ndbioimage/tests/files/Experiment-2029.czi");
assert!(path.exists());
let czi = CziReader::create()?;
let stream = InputStream::create_from_file_utf8(
path.to_str().ok_or(Error::msg("cannot into str"))?,
)?;
let open_info = ReaderOpenInfo::new(&stream);
czi.open(open_info)?;
let metadata_segment = czi.get_metadata_segment()?;
let xml = metadata_segment.get_metadata_as_xml()?;
let s = String::try_from(&xml)?;
println!("xml: {}", &s[..s.len().min(100)]);
Ok(())
}
#[test]
fn test_libczi_pyramid_statistics() -> Result<()> {
let path = env::home_dir()
.unwrap()
.join("code/rust/ndbioimage/tests/files/Experiment-2029.czi");
assert!(path.exists());
let czi = CziReader::create()?;
let stream = InputStream::create_from_file_utf8(
path.to_str().ok_or(Error::msg("cannot into str"))?,
)?;
let open_info = ReaderOpenInfo::new(&stream);
czi.open(open_info)?;
let s = czi.get_pyramid_statistics()?;
println!("xml: {}", &s[..s.len().min(100)]);
Ok(())
}
#[test]
fn test_libczi_document_info() -> Result<()> {
let path = env::home_dir()
.unwrap()
.join("code/rust/ndbioimage/tests/files/Experiment-2029.czi");
assert!(path.exists());
let czi = CziReader::create()?;
let stream = InputStream::create_from_file_utf8(
path.to_str().ok_or(Error::msg("cannot into str"))?,
)?;
let open_info = ReaderOpenInfo::new(&stream);
czi.open(open_info)?;
let metadata_segment = czi.get_metadata_segment()?;
let document_info = metadata_segment.get_czi_document_info()?;
let general_document_info = document_info.get_general_document_info()?;
println!("xml: {}", &general_document_info[..general_document_info.len().min(100)]);
Ok(())
}
#[test]
fn test_lib_czi_build_information() -> Result<()> {
let build_info = LibCZIBuildInformation::get()?;
println!("compiler information: {:?}", build_info.get_compiler_information());
println!("repository url: {:?}", build_info.get_repository_url());
println!("repository branch: {:?}", build_info.get_repository_branch());
println!("repository tag: {:?}", build_info.get_repository_tag());
Ok(())
}
}

115
src/misc.rs Normal file
View File

@@ -0,0 +1,115 @@
use anyhow::{anyhow, Error, Result};
use std::fmt;
use std::mem::MaybeUninit;
use std::os::raw::c_int;
/// the error type for libCZIAPI
#[derive(Clone, Debug)]
pub enum LibCZIApiError {
OK,
InvalidArgument,
InvalidHandle,
OutOfMemory,
IndexOutOfRange,
LockUnlockSemanticViolated,
UnspecifiedError,
}
impl std::error::Error for LibCZIApiError {}
impl TryFrom<c_int> for LibCZIApiError {
type Error = Error;
fn try_from(code: c_int) -> Result<Self> {
match code {
0 => Ok(LibCZIApiError::OK),
1 => Err(Error::from(LibCZIApiError::InvalidArgument)),
2 => Err(Error::from(LibCZIApiError::InvalidHandle)),
3 => Err(Error::from(LibCZIApiError::OutOfMemory)),
4 => Err(Error::from(LibCZIApiError::IndexOutOfRange)),
20 => Err(Error::from(LibCZIApiError::LockUnlockSemanticViolated)),
50 => Err(Error::from(LibCZIApiError::UnspecifiedError)),
_ => Err(anyhow!("Unknown error code {}", code)),
}
}
}
impl fmt::Display for LibCZIApiError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "LibCZIApi {self:?}")
}
}
/// enum for SubBlock.get_raw_data
pub enum RawDataType {
Data,
Metadata,
}
/// pixel type
pub enum PixelType {
Gray8,
Gray16,
Gray32Float,
Bgr24,
Bgr48,
Bgr96Float,
Bgra32,
Gray64ComplexFloat,
Bgr192ComplexFloat,
Gray32,
Gray64Float,
}
impl TryFrom<i32> for PixelType {
type Error = Error;
fn try_from(pixel_type: i32) -> Result<Self> {
match pixel_type {
0 => Ok(PixelType::Gray8),
1 => Ok(PixelType::Gray16),
2 => Ok(PixelType::Gray32Float),
3 => Ok(PixelType::Bgr24),
4 => Ok(PixelType::Bgr48),
8 => Ok(PixelType::Bgr96Float),
9 => Ok(PixelType::Bgra32),
10 => Ok(PixelType::Gray64ComplexFloat),
11 => Ok(PixelType::Bgr192ComplexFloat),
12 => Ok(PixelType::Gray32),
13 => Ok(PixelType::Gray64Float),
_ => Err(anyhow!("Unknown pixel type {}", pixel_type)),
}
}
}
impl From<PixelType> for i32 {
fn from(pixel_type: PixelType) -> Self {
match pixel_type {
PixelType::Gray8 => 0,
PixelType::Gray16 => 1,
PixelType::Gray32Float => 2,
PixelType::Bgr24 => 3,
PixelType::Bgr48 => 4,
PixelType::Bgr96Float => 8,
PixelType::Bgra32 => 9,
PixelType::Gray64ComplexFloat => 10,
PixelType::Bgr192ComplexFloat => 11,
PixelType::Gray32 => 12,
PixelType::Gray64Float => 13,
}
}
}
pub trait Ptr {
type Pointer;
unsafe fn assume_init(ptr: MaybeUninit<Self::Pointer>) -> Self;
fn as_mut_ptr(&self) -> *mut Self::Pointer
where
Self: Sized;
fn as_ptr(&self) -> *const Self::Pointer
where
Self: Sized;
}

9
src/sys.rs Normal file
View File

@@ -0,0 +1,9 @@
#![allow(non_upper_case_globals)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(unsafe_op_in_unsafe_fn)]
#![allow(dead_code)]
#![allow(rustdoc::broken_intra_doc_links)]
#![allow(rustdoc::invalid_html_tags)]
include!(concat!(env!("OUT_DIR"), "/lib_czi_api.rs"));