Skip to main content

libczirw_sys/
functions.rs

1use crate::error::Error;
2use crate::handle::*;
3use crate::interop::*;
4use crate::misc::*;
5use crate::sys::*;
6use std::ffi::{CStr, CString, c_char, c_int, c_void};
7use std::mem::{ManuallyDrop, MaybeUninit};
8use std::ops::Deref;
9
10#[cfg(not(target_os = "windows"))]
11type WChar = u32;
12#[cfg(target_os = "windows")]
13type WChar = u16;
14
15/// Release the memory - this function is to be used for freeing memory allocated by the libCZIApi-library
16///  (and returned to the caller).
17///
18///  \\param  data    Pointer to the memory to be freed.
19pub fn free<T: Ptr>(data: T) {
20    let ptr = data.as_mut_ptr() as *mut c_void;
21    unsafe { libCZI_Free(ptr) };
22}
23
24/// Allocate memory of the specified size.
25///
26///  \\param          size    The size of the memory block to be allocated in bytes.
27///  \\param \[out\]    data    If successful, a pointer to the allocated memory is put here. The memory must be freed using 'libCZI_Free'.
28///
29///  \\returns    An error-code indicating success or failure of the operation.
30pub fn allocate_memory<T: Ptr>(size: usize) -> Result<MaybeUninit<T>, Error> {
31    let mut data = MaybeUninit::<T>::uninit();
32    let mut ptr = data.as_mut_ptr() as *mut c_void;
33    lib_czi_error(unsafe { libCZI_AllocateMemory(size as u64, &mut ptr) })?;
34    Ok(data)
35}
36
37impl LibCZIVersionInfo {
38    /// Get version information about the libCZIApi-library.
39    ///
40    ///  \\param \[out\] version_info    If successful, the version information is put here.
41    ///
42    ///  \\returns    An error-code indicating success or failure of the operation.
43    pub fn get_lib_czi_version_info() -> Result<LibCZIVersionInfo, Error> {
44        let mut version_info = MaybeUninit::uninit();
45        let ptr = version_info.as_mut_ptr();
46        lib_czi_error(unsafe { libCZI_GetLibCZIVersionInfo(ptr) })?;
47        Ok(unsafe { LibCZIVersionInfo::assume_init(version_info) })
48    }
49}
50
51impl LibCZIBuildInformation {
52    /// Get information about the build of the libCZIApi-library.
53    ///
54    ///  \\param \[out\] build_info  If successful, the build information is put here. Note that all strings must be freed by the caller (using 'libCZI_Free').
55    ///
56    ///  \\returns    An error-code indicating success or failure of the operation.
57    pub fn get() -> Result<LibCZIBuildInformation, Error> {
58        let mut build_info = MaybeUninit::uninit();
59        let ptr = build_info.as_mut_ptr();
60        lib_czi_error(unsafe { libCZI_GetLibCZIBuildInformation(ptr) })?;
61        Ok(unsafe { LibCZIBuildInformation::assume_init(build_info) })
62    }
63}
64
65impl CziReader {
66    /// Create a new CZI-reader object.
67    ///
68    ///  \\param \[out\] reader_object If the operation is successful, a handle to the newly created reader object is put here.
69    ///
70    ///  \\returns    An error-code indicating success or failure of the operation.
71    pub fn create() -> Result<Self, Error> {
72        let mut reader = MaybeUninit::uninit();
73        let ptr = reader.as_mut_ptr();
74        lib_czi_error(unsafe { libCZI_CreateReader(ptr) })?;
75        Ok(unsafe { Self::assume_init(reader) })
76    }
77
78    /// Instruct the specified reader-object to open a CZI-document. The 'open_info' parameter contains
79    ///  a handle to a stream-object which is used to read the document.
80    ///
81    ///  \\param  reader_object A handle representing the reader-object.
82    ///  \\param  open_info     Parameters controlling the operation.
83    ///
84    ///  \\returns    An error-code indicating success or failure of the operation.
85    pub fn open(&self, open_info: ReaderOpenInfo) -> Result<(), Error> {
86        lib_czi_error(unsafe { libCZI_ReaderOpen(**self, open_info.as_ptr()) })?;
87        Ok(())
88    }
89
90    /// Get information about the file-header of the CZI document. The information is put into the 'file_header_info_interop' structure.
91    ///  This file_header_info_interop structure contains the GUID of the CZI document and the version levels of CZI.
92    ///
93    ///  \\param          reader_object               The reader object.
94    ///  \\param \[out\]    file_header_info_interop    If successful, the retrieved information is put here.
95    ///
96    ///  \\returns An error-code indicating success or failure of the operation.
97    pub fn get_file_header_info(&self) -> Result<FileHeaderInfo, Error> {
98        let mut file_header_info = MaybeUninit::uninit();
99        let ptr = file_header_info.as_mut_ptr();
100        lib_czi_error(unsafe { libCZI_ReaderGetFileHeaderInfo(**self, ptr) })?;
101        Ok(unsafe { FileHeaderInfo::assume_init(file_header_info) })
102    }
103
104    /// Reads the sub-block identified by the specified index. If there is no sub-block present (for the
105    ///  specified index) then the function returns 'LibCZIApi_ErrorCode_OK', but the 'sub_block_object'
106    ///  is set to 'kInvalidObjectHandle'.
107    ///
108    ///  \\param          reader_object       The reader object.
109    ///  \\param          index               Index of the sub-block.
110    ///  \\param \[out\]    sub_block_object    If successful, a handle to the sub-block object is put here; otherwise 'kInvalidObjectHandle'.
111    ///
112    ///  \\returns    An error-code indicating success or failure of the operation.
113    pub fn read_sub_block(&self, index: i32) -> Result<SubBlock, Error> {
114        let mut sub_block = MaybeUninit::uninit();
115        let ptr = sub_block.as_mut_ptr();
116        lib_czi_error(unsafe { libCZI_ReaderReadSubBlock(**self, index as c_int, ptr) })?;
117        Ok(unsafe { SubBlock::assume_init(sub_block) })
118    }
119
120    /// Get statistics about the sub-blocks in the CZI-document. This function provides a simple version of the statistics, the
121    ///  information retrieved does not include the per-scene statistics.
122    ///
123    ///  \\param          reader_object   The reader object.
124    ///  \\param \[out\]    statistics      If non-null, the simple statistics will be put here.
125    ///
126    ///  \\returns    An error-code indicating success or failure of the operation.
127    pub fn get_statistics_simple(&self) -> Result<SubBlockStatistics, Error> {
128        let mut statistics = MaybeUninit::uninit();
129        let ptr = statistics.as_mut_ptr();
130        lib_czi_error(unsafe { libCZI_ReaderGetStatisticsSimple(**self, ptr) })?;
131        Ok(unsafe { SubBlockStatistics::assume_init(statistics) })
132    }
133
134    /// Get extended statistics about the sub-blocks in the CZI-document. This function provides a more detailed version of the statistics,
135    ///  including the per-scene statistics. Note that the statistics is of variable size, and the semantic is as follows:
136    ///  - On input, the argument 'number_of_per_channel_bounding_boxes' must point to an integer which describes the size of the argument 'statistics'.
137    ///    This number gives how many elements the array 'per_scenes_bounding_boxes' in 'SubBlockStatisticsInteropEx' can hold. Only that number of
138    ///    per-scene information elements will be put into the 'statistics' structure at most, in any case.
139    ///  - On output, the argument 'number_of_per_channel_bounding_boxes' will be set to the number of per-channel bounding boxes that were actually
140    ///    available.
141    ///  - In the returned 'SubBlockStatisticsInteropEx' structure, the 'number_of_per_scenes_bounding_boxes' field will be set to the number of per-scene
142    ///    information that is put into this struct (which may be less than number of scenes that are available).
143    ///
144    ///  So, the caller is expected to check the returned 'number_of_per_channel_bounding_boxes' to see how many per-channel bounding boxes are available.
145    ///  If this number is greater than the number of elements (given with the 'number_of_per_scenes_bounding_boxes' value in the 'statistics' structure),
146    ///  then the caller should allocate a larger 'statistics' structure and call this function again (with an increased 'number_of_per_scenes_bounding_boxes').
147    ///
148    ///  \\param          reader_object                           The reader object.
149    ///  \\param \[out\]    statistics                              If non-null, the statistics will be put here.
150    ///  \\param \[in,out\] number_of_per_channel_bounding_boxes    On input, it gives the number of elements that can be put into the 'per_scenes_bounding_boxes' array.
151    ///                                                          On output, it gives the number of elements which are available.
152    ///
153    ///  \\returns    An error-code indicating success or failure of the operation.
154    pub fn get_statistics_ex(
155        &self,
156        number_of_per_channel_bounding_boxes: i32,
157    ) -> Result<(SubBlockStatisticsEx, i32), Error> {
158        let mut statistics = MaybeUninit::uninit();
159        let ptr = statistics.as_mut_ptr();
160        let number_of_per_channel_bounding_boxes =
161            Box::into_raw(Box::new(number_of_per_channel_bounding_boxes));
162        lib_czi_error(unsafe {
163            libCZI_ReaderGetStatisticsEx(**self, ptr, number_of_per_channel_bounding_boxes)
164        })?;
165        Ok(unsafe {
166            (
167                SubBlockStatisticsEx::assume_init(statistics),
168                *Box::from_raw(number_of_per_channel_bounding_boxes),
169            )
170        })
171    }
172
173    /// Get \"pyramid-statistics\" about the CZI-document. This function provides a JSON-formatted string which contains information about the pyramid.
174    ///  The JSON-schema is as follows:
175    ///  \\code
176    ///  {
177    ///      \"scenePyramidStatistics\": {
178    ///          \<sceneIndex\>: [
179    ///          {
180    ///              \"layerInfo\": {
181    ///              \"minificationFactor\": \<number\>,
182    ///              \"pyramidLayerNo\" : \<number\>
183    ///          },
184    ///          \"count\" : \<number\>
185    ///          }
186    ///      ]}
187    ///  }
188    ///  \\endcode
189    ///  It resembles the corresponding C++-structure 'PyramidStatistics' in the libCZI-library.
190    ///
191    ///  \\param          reader_object              The reader object.
192    ///  \\param \[out\]    pyramid_statistics_as_json If successful, a pointer to a JSON-formatted string is placed here. The caller
193    ///                                              is responsible for freeing this memory (by calling libCZI_Free).
194    ///
195    ///  \\returns An error-code indicating success or failure of the operation.
196    pub fn get_pyramid_statistics(&self) -> Result<String, Error> {
197        let mut ptr = MaybeUninit::<*mut c_char>::uninit();
198        lib_czi_error(unsafe { libCZI_ReaderGetPyramidStatistics(**self, ptr.as_mut_ptr()) })?;
199        let ptr = unsafe { ptr.assume_init() };
200        assert!(!ptr.is_null());
201        let statistics = unsafe { CStr::from_ptr(ptr) }
202            .to_string_lossy()
203            .into_owned();
204        unsafe { libCZI_Free(ptr as *mut c_void) };
205        Ok(statistics)
206    }
207
208    /// Create a metadata-segment object from the reader-object. The metadata-segment object can be used to retrieve the XML-metadata of the CZI-document.
209    ///
210    /// \\param          reader_object           The reader object.
211    /// \\param \[out\]    metadata_segment_object If successful, a handle to the metadata-segment object is put here.
212    ///
213    /// \\returns An error-code indicating success or failure of the operation.
214    pub fn get_metadata_segment(&self) -> Result<MetadataSegment, Error> {
215        let mut metadata_segment = MaybeUninit::uninit();
216        let ptr = metadata_segment.as_mut_ptr();
217        lib_czi_error(unsafe { libCZI_ReaderGetMetadataSegment(**self, ptr) })?;
218        Ok(unsafe { MetadataSegment::assume_init(metadata_segment) })
219    }
220
221    /// Get the number of attachments available.
222    ///
223    /// \\param          reader_object           The reader object.
224    /// \\param \[out\]    count                   The number of available attachments is put here.
225    /// \\returns    An error-code indicating success or failure of the operation.
226    pub fn get_attachment_count(&self) -> Result<i32, Error> {
227        let mut count = MaybeUninit::<c_int>::uninit();
228        lib_czi_error(unsafe { libCZI_ReaderGetAttachmentCount(**self, count.as_mut_ptr()) })?;
229        Ok(unsafe { count.assume_init() })
230    }
231
232    /// Get information about the attachment at the specified index. The information is put into the 'attachment_info_interop' structure.
233    /// If the index is not valid, then the function returns 'LibCZIApi_ErrorCode_IndexOutOfRange'.
234    ///
235    /// \\param          reader_object           The reader object.
236    /// \\param          index                   The index of the attachment to query information for.
237    /// \\param \[out\]    attachment_info_interop If successful, the retrieved information is put here.
238    ///
239    /// \\returns An error-code indicating success or failure of the operation.
240    pub fn get_attachment_info_from_directory(&self, index: i32) -> Result<AttachmentInfo, Error> {
241        let mut attachment_info = MaybeUninit::uninit();
242        let ptr = attachment_info.as_mut_ptr();
243        lib_czi_error(unsafe { libCZI_ReaderGetAttachmentInfoFromDirectory(**self, index, ptr) })?;
244        Ok(unsafe { AttachmentInfo::assume_init(attachment_info) })
245    }
246
247    /// Read the attachment with the specified index and create an attachment object representing it. If the specified index
248    /// is invalid, then the returned attachment-object handle will have the value 'kInvalidObjectHandle'.
249    /// \\param       reader_object              The reader object.
250    /// \\param       index                      The index of the attachment to get.
251    /// \\param \[out\] attachment_object          If successful and index is valid, a handle representing the attachment object is put here. If the index is
252    ///                                         invalid, then the handle will have the value 'kInvalidObjectHandle'.
253    /// \\returns  An error-code indicating success or failure of the operation.
254    pub fn read_attachment(&self, index: i32) -> Result<Attachment, Error> {
255        let mut attachment = MaybeUninit::uninit();
256        let ptr = attachment.as_mut_ptr();
257        lib_czi_error(unsafe { libCZI_ReaderReadAttachment(**self, index, ptr) })?;
258        Ok(unsafe { Attachment::assume_init(attachment) })
259    }
260
261    /// Release the specified reader-object. After this function is called, the handle is no
262    /// longer valid.
263    ///
264    /// \\param  reader_object   The reader object.
265    ///
266    /// \\returns    An error-code indicating success or failure of the operation.
267    pub fn release(&self) -> Result<(), Error> {
268        lib_czi_error(unsafe { libCZI_ReleaseReader(**self) })?;
269        Ok(())
270    }
271
272    /// Get information about the sub-block with the specified index. The information is put into the 'sub_block_info_interop' structure.
273    /// If the index is not valid, then the function returns 'LibCZIApi_ErrorCode_IndexOutOfRange'.
274    ///
275    /// \\param          reader_object           The reader object.
276    /// \\param          index                   The index of the attachment to query information for.
277    /// \\param \[out\]    sub_block_info_interop  If successful, the retrieved information is put here.
278    ///
279    /// \\returns An error-code indicating success or failure of the operation.
280    pub fn try_get_sub_block_info_for_index(&self, index: i32) -> Result<SubBlockInfo, Error> {
281        let mut sub_block_info = MaybeUninit::uninit();
282        let ptr = sub_block_info.as_mut_ptr();
283        lib_czi_error(unsafe { libCZI_TryGetSubBlockInfoForIndex(**self, index, ptr) })?;
284        Ok(unsafe { SubBlockInfo::assume_init(sub_block_info) })
285    }
286
287    /// Create a single channel scaling tile accessor.
288    ///
289    /// \\param reader_object            A handle representing the reader-object.
290    /// \\param accessor_object \[out\]    If the operation is successful, a handle to the newly created single-channel-scaling-tile-accessor is put here.
291    ///
292    /// \\returns    An error-code indicating success or failure of the operation.
293    pub fn create_single_channel_tile_accessor(
294        &self,
295    ) -> Result<SingleChannelScalingTileAccessor, Error> {
296        let mut accessor = MaybeUninit::uninit();
297        let ptr = accessor.as_mut_ptr();
298        lib_czi_error(unsafe { libCZI_CreateSingleChannelTileAccessor(**self, ptr) })?;
299        Ok(unsafe { SingleChannelScalingTileAccessor::assume_init(accessor) })
300    }
301}
302
303impl Drop for CziReader {
304    fn drop(&mut self) {
305        self.release().ok();
306    }
307}
308
309/// Get information about the stream class at the specified index.
310///
311/// \\param          index                   Zero-based index of the stream class to query information about.
312/// \\param \[out\]    input_stream_class_info If successful, information about the stream class is put here. Note that the strings in the structure
313///                                         must be freed (by the caller) using 'libCZI_Free'.
314///
315/// \\returns An error-code indicating success or failure of the operation.
316pub fn get_stream_classes_count(index: i32) -> Result<InputStreamClassInfo, Error> {
317    let mut input_stream_class_info = MaybeUninit::uninit();
318    let ptr = input_stream_class_info.as_mut_ptr();
319    lib_czi_error(unsafe { libCZI_GetStreamClassInfo(index, ptr) })?;
320    Ok(unsafe { InputStreamClassInfo::assume_init(input_stream_class_info) })
321}
322
323impl InputStream {
324    /// Create an input stream object of the specified type, using the specified JSON-formatted property bag and
325    /// the specified file identifier as input.
326    ///
327    /// \\param          stream_class_name       Name of the stream class to be instantiated.
328    /// \\param          creation_property_bag   JSON formatted string (containing additional parameters for the stream creation) in UTF8-encoding.
329    /// \\param          stream_identifier       The filename (or, more generally, a URI of some sort) identifying the file to be opened in UTF8-encoding.
330    /// \\param \[out\]    stream_object           If successful, a handle representing the newly created stream object is put here.
331    ///
332    /// \\returns    An error-code that indicates whether the operation is successful or not.
333    pub fn create(
334        stream_class_name: impl AsRef<str>,
335        creation_property_bag: impl AsRef<str>,
336        stream_identifier: impl AsRef<str>,
337    ) -> Result<Self, Error> {
338        let mut stream = MaybeUninit::uninit();
339        let ptr = stream.as_mut_ptr();
340        let stream_class_name = ManuallyDrop::new(CString::new(stream_class_name.as_ref())?);
341        let creation_property_bag =
342            ManuallyDrop::new(CString::new(creation_property_bag.as_ref())?);
343        let stream_identifier = ManuallyDrop::new(CString::new(stream_identifier.as_ref())?);
344        lib_czi_error(unsafe {
345            libCZI_CreateInputStream(
346                stream_class_name.as_ptr(),
347                creation_property_bag.as_ptr(),
348                stream_identifier.as_ptr(),
349                ptr,
350            )
351        })?;
352        Ok(unsafe { Self::assume_init(stream) })
353    }
354
355    /// Create an input stream object for a file identified by its filename, which is given as a wide string. Note that wchar_t on
356    /// Windows is 16-bit wide, and on Unix-like systems it is 32-bit wide.
357    ///
358    /// \\param  \[in\]    filename        Filename of the file which is to be opened (zero terminated wide string). Note that on Windows, this
359    ///                                 is a string with 16-bit code units, and on Unix-like systems it is typically a string with 32-bit code units.
360    ///
361    /// \\param  \[out\]   stream_object   The output stream object that will hold the created stream.
362    /// \\return         An error-code that indicates whether the operation is successful or not. Non-positive values indicates successful, positive values
363    ///                 indicates unsuccessful operation.
364    pub fn create_from_file_wide(file_name: Vec<WChar>) -> Result<Self, Error> {
365        let mut stream = MaybeUninit::uninit();
366        let ptr = stream.as_mut_ptr();
367        lib_czi_error(unsafe { libCZI_CreateInputStreamFromFileWide(file_name.as_ptr(), ptr) })?;
368        Ok(unsafe { Self::assume_init(stream) })
369    }
370
371    /// Create an input stream object for a file identified by its filename, which is given as an UTF8-encoded string.
372    ///
373    /// \\param  \[in\]    filename        Filename of the file which is to be opened (in UTF8 encoding).
374    /// \\param  \[out\]   stream_object   The output stream object that will hold the created stream.
375    /// \\return         An error-code that indicates whether the operation is successful or not. Non-positive values indicates successful, positive values
376    ///                 indicates unsuccessful operation.
377    pub fn create_from_file_utf8<S: AsRef<str>>(file_name: S) -> Result<Self, Error> {
378        let mut stream = MaybeUninit::uninit();
379        let ptr = stream.as_mut_ptr();
380        let file_name = ManuallyDrop::new(CString::new(file_name.as_ref())?);
381        // let file_name = file_name.as_ref().as_bytes().to_vec();
382        lib_czi_error(unsafe {
383            libCZI_CreateInputStreamFromFileUTF8(file_name.as_ptr() as *const c_char, ptr)
384        })?;
385        Ok(unsafe { Self::assume_init(stream) })
386    }
387
388    /// Create an input stream object which is using externally provided functions for operation
389    /// and reading the data. Please refer to the documentation of
390    /// 'ExternalInputStreamStructInterop' for more information.
391    ///
392    /// \\param          external_input_stream_struct    Structure containing the information about the externally provided functions.
393    /// \\param \[out\]    stream_object                   If successful, the handle to the newly created input stream object is put here.
394    ///
395    /// \\returns    An error-code indicating success or failure of the operation.
396    pub fn create_from_external(
397        external_input_stream: ExternalInputStreamStruct,
398    ) -> Result<Self, Error> {
399        let mut stream = MaybeUninit::uninit();
400        let ptr = stream.as_mut_ptr();
401        lib_czi_error(unsafe {
402            libCZI_CreateInputStreamFromExternal(external_input_stream.as_ptr(), ptr)
403        })?;
404        Ok(unsafe { Self::assume_init(stream) })
405    }
406
407    /// Release the specified input stream object. After this function is called, the handle is no
408    /// longer valid. Note that calling this function will only decrement the usage count of the
409    /// underlying object; whereas the object itself (and the resources it holds) will only be
410    /// released when the usage count reaches zero.
411    ///
412    /// \\param  stream_object   The input stream object.
413    ///
414    /// \\returns    An error-code indicating success or failure of the operation.
415    pub fn release(&self) -> Result<(), Error> {
416        lib_czi_error(unsafe { libCZI_ReleaseInputStream(**self) })?;
417        Ok(())
418    }
419}
420
421impl Drop for InputStream {
422    fn drop(&mut self) {
423        self.release().ok();
424    }
425}
426
427impl SubBlock {
428    /// Create a bitmap object from the specified sub-block object. The bitmap object can be used to access the pixel
429    /// data contained in the sub-block. If the subblock contains compressed data, then decompression will be performed
430    /// in this call.
431    ///
432    /// \\param          sub_block_object The sub-block object.
433    /// \\param \[out\]    bitmap_object    If successful, the handle to the newly created bitmap object is put here.
434    ///
435    /// \\returns An error-code indicating success or failure of the operation.
436    pub fn create_bitmap(&self) -> Result<Bitmap, Error> {
437        let mut bitmap = MaybeUninit::uninit();
438        let ptr = bitmap.as_mut_ptr();
439        lib_czi_error(unsafe { libCZI_SubBlockCreateBitmap(**self, ptr) })?;
440        Ok(unsafe { Bitmap::assume_init(bitmap) })
441    }
442
443    /// Get Information about the sub-block.
444    ///
445    /// \\param       sub_block_object The sub-block object.
446    /// \\param \[out\] sub_block_info   If successful, information about the sub-block object is put here.
447    ///
448    /// \\returns An error-code indicating success or failure of the operation.
449    pub fn get_info(&self) -> Result<SubBlockInfo, Error> {
450        let mut sub_block_info = MaybeUninit::uninit();
451        let ptr = sub_block_info.as_mut_ptr();
452        lib_czi_error(unsafe { libCZI_SubBlockGetInfo(**self, ptr) })?;
453        Ok(unsafe { SubBlockInfo::assume_init(sub_block_info) })
454    }
455
456    /// Copy the raw data from the specified sub-block object to the specified memory buffer. The value of the 'size' parameter
457    /// on input is the size of the buffer pointed to by 'data'. On output, the value of 'size' is the actual size of the data. At most
458    /// the initial value of 'size' bytes are copied to the buffer. If the initial value of 'size' is zero (0) or 'data' is null, then
459    /// no data is copied.
460    /// For the 'type' parameter, the following values are valid: 0 (data) and 1 (metadata).
461    /// For 0 (data), the data is the raw pixel data of the bitmap. This data may be compressed.
462    /// For 1 (metadata), the data is the raw metadata in XML-format (UTF8-encoded).
463    ///
464    /// \\param          sub_block_object    The sub block object.
465    /// \\param          type                The type - 0 for \"pixel-data\", 1 for \"sub-block metadata\".
466    /// \\param \[in,out\] size                On input, the size of the memory block pointed to by 'data', on output the actual size of the available data.
467    /// \\param \[out\]    data                Pointer where the data is to be copied to. At most the initial content of 'size' bytes are copied.
468    ///
469    /// \\returns    An error-code indicating success or failure of the operation.
470    pub fn get_raw_data(&self, tp: RawDataType, size: i32) -> Result<(i32, Vec<u8>), Error> {
471        let mut data = vec![0u8; size as usize];
472        let size = Box::into_raw(Box::new(size as u64));
473        lib_czi_error(unsafe {
474            libCZI_SubBlockGetRawData(**self, tp as c_int, size, data.as_mut_ptr() as *mut c_void)
475        })?;
476        Ok((unsafe { *Box::from_raw(size) as i32 }, data))
477    }
478
479    /// Release the specified sub-block object.
480    ///
481    /// \\param  sub_block_object The sub block object to be released.
482    ///
483    /// \\returns An error-code indicating success or failure of the operation.
484    pub fn release(&self) -> Result<(), Error> {
485        lib_czi_error(unsafe { libCZI_ReleaseSubBlock(**self) })?;
486        Ok(())
487    }
488}
489
490impl Drop for SubBlock {
491    fn drop(&mut self) {
492        self.release().ok();
493    }
494}
495
496impl Attachment {
497    /// Get information about the specified attachment object.
498    /// \\param attachment_object            The attachment object.
499    /// \\param \[out\]    attachment_info     Information about the attachment.
500    /// \\returns     An error-code indicating success or failure of the operation.
501    pub fn get_info(&self) -> Result<AttachmentInfo, Error> {
502        let mut attachment_info = MaybeUninit::uninit();
503        let ptr = attachment_info.as_mut_ptr();
504        lib_czi_error(unsafe { libCZI_AttachmentGetInfo(**self, ptr) })?;
505        Ok(unsafe { AttachmentInfo::assume_init(attachment_info) })
506    }
507
508    /// Copy the raw data from the specified attachment object to the specified memory buffer. The value of the 'size' parameter
509    /// on input is the size of the buffer pointed to by 'data'. On output, the value of 'size' is the actual size of the data. At most
510    /// the initial value of 'size' bytes are copied to the buffer. If the initial value of 'size' is zero (0) or 'data' is null, then
511    /// no data is copied.
512    /// \\param          attachment_object   The attachment object.
513    /// \\param \[in,out\] size                On input, the size of the memory block pointed to by 'data', on output the actual size of the available data.
514    /// \\param \[out\]    data                Pointer where the data is to be copied to. At most the initial content of 'size' bytes are copied.
515    ///
516    /// \\returns    An error-code indicating success or failure of the operation.
517    pub fn get_raw_data(&self, size: i32) -> Result<(i32, Vec<u8>), Error> {
518        let mut data = vec![0u8; size as usize];
519        let size = Box::into_raw(Box::new(size as u64));
520        lib_czi_error(unsafe {
521            libCZI_AttachmentGetRawData(**self, size, data.as_mut_ptr() as *mut c_void)
522        })?;
523        Ok((unsafe { *Box::from_raw(size) as i32 }, data))
524    }
525
526    /// convenience method that extracts some types of data
527    pub fn get_data(&self) -> Result<AttachmentData, Error> {
528        let (n, _) = self.get_raw_data(0)?;
529        let (_, data) = self.get_raw_data(n)?;
530        Ok(match self.get_info()?.get_content_file_type()?.as_str() {
531            "CZTIMS" | "CZFOC" => AttachmentData::from_float(data.as_slice())?,
532            "CZEXP" | "CZHWS" | "CZMVM" | "CZFBMX" => AttachmentData::from_xml(data.as_slice())?,
533            _ => AttachmentData::Unknown(data),
534        })
535    }
536
537    /// Release the specified attachment object.
538    ///
539    /// \\param  attachment_object The attachment object to be released.
540    ///
541    /// \\returns An error-code indicating success or failure of the operation.
542    pub fn release(&self) -> Result<(), Error> {
543        lib_czi_error(unsafe { libCZI_ReleaseAttachment(**self) })?;
544        Ok(())
545    }
546}
547
548impl Drop for Attachment {
549    fn drop(&mut self) {
550        self.release().ok();
551    }
552}
553
554impl Bitmap {
555    /// Get information about the specified bitmap object.
556    ///
557    /// \\param          bitmap_object The bitmap object.
558    /// \\param \[out\]    bitmap_info   If successful, information about the bitmap object is put here.
559    ///
560    /// \\returns An error-code indicating success or failure of the operation.
561    pub fn get_info(&self) -> Result<BitmapInfo, Error> {
562        let mut bitmap_info = MaybeUninit::uninit();
563        let ptr = bitmap_info.as_mut_ptr();
564        lib_czi_error(unsafe { libCZI_BitmapGetInfo(**self, ptr) })?;
565        Ok(unsafe { BitmapInfo::assume_init(bitmap_info) })
566    }
567
568    /// Locks the bitmap object. Once the bitmap is locked, the pixel data can be accessed. Memory access to the
569    /// pixel data must only occur while the bitmap is locked. The lock must be released by calling 'libCZI_BitmapUnlock'.
570    /// It is a fatal error if the bitmap is destroyed while still being locked. Calls to Lock and Unlock are counted, and
571    /// they must be balanced.
572    ///
573    /// \\param          bitmap_object The bitmap object.
574    /// \\param \[out\]    lockInfo      If successful, information about how to access the pixel data is put here.
575    ///
576    /// \\returns An error-code indicating success or failure of the operation.
577    pub fn lock(self) -> Result<LockedBitmap, Error> {
578        let mut bitmap_info = MaybeUninit::uninit();
579        let ptr = bitmap_info.as_mut_ptr();
580        lib_czi_error(unsafe { libCZI_BitmapLock(*self, ptr) })?;
581        let bitmap_lock_info = unsafe { BitmapLockInfo::assume_init(bitmap_info) };
582        Ok(LockedBitmap {
583            bitmap: self,
584            lock_info: bitmap_lock_info,
585        })
586    }
587
588    /// Release the specified bitmap object.
589    /// It is a fatal error trying to release a bitmap object that is still locked.
590    ///
591    /// \\param  bitmap_object The bitmap object.
592    ///
593    /// \\returns An error-code indicating success or failure of the operation.
594    pub fn release(&self) -> Result<(), Error> {
595        lib_czi_error(unsafe { libCZI_ReleaseBitmap(**self) })?;
596        Ok(())
597    }
598}
599
600impl TryFrom<&SubBlock> for Bitmap {
601    type Error = Error;
602
603    fn try_from(sub_block: &SubBlock) -> Result<Self, Error> {
604        sub_block.create_bitmap()
605    }
606}
607
608impl Drop for Bitmap {
609    fn drop(&mut self) {
610        self.release().ok();
611    }
612}
613
614/// Locked version of bitmap so that the data can be accessed
615pub struct LockedBitmap {
616    bitmap: Bitmap,
617    pub lock_info: BitmapLockInfo,
618}
619
620impl Deref for LockedBitmap {
621    type Target = Bitmap;
622
623    fn deref(&self) -> &Self::Target {
624        &self.bitmap
625    }
626}
627
628impl Drop for LockedBitmap {
629    fn drop(&mut self) {
630        unsafe { libCZI_BitmapUnlock(self.handle()) };
631    }
632}
633
634impl LockedBitmap {
635    /// Unlock the bitmap object. Once the bitmap is unlocked, the pixel data must not be accessed anymore.
636    ///
637    /// \\param  bitmap_object The bitmap object.
638    ///
639    /// \\returns An error-code indicating success or failure of the operation.
640    pub fn unlock(self) -> Result<Bitmap, Error> {
641        lib_czi_error(unsafe { libCZI_BitmapUnlock(**self) })?;
642        Ok(self.bitmap.clone())
643    }
644
645    /// Copy the pixel data from the specified bitmap object to the specified memory buffer. The specified
646    /// destination bitmap must have same width, height and pixel type as the source bitmap.
647    ///
648    /// \\param          bitmap_object The bitmap object.
649    /// \\param          width         The width of the destination bitmap.
650    /// \\param          height        The height of the destination bitmap.
651    /// \\param          pixel_type    The pixel type.
652    /// \\param          stride        The stride (given in bytes).
653    /// \\param \[out\]    ptr           Pointer to the memory location where the bitmap is to be copied to.
654    ///
655    /// \\returns A LibCZIApiErrorCode.
656    pub fn copy(
657        &self,
658        width: u32,
659        height: u32,
660        pixel_type: PixelType,
661        stride: u32,
662    ) -> Result<Bitmap, Error> {
663        let mut data = MaybeUninit::<Self>::uninit();
664        lib_czi_error(unsafe {
665            libCZI_BitmapCopyTo(
666                ***self,
667                width,
668                height,
669                pixel_type as i32,
670                stride,
671                data.as_mut_ptr() as *mut c_void,
672            )
673        })?;
674        Ok(unsafe { data.assume_init().unlock()? })
675    }
676}
677
678impl MetadataSegment {
679    /// Get the XML-metadata information from the specified metadata-segment object.
680    /// Note that the XML-metadata is returned as a pointer to the data (in the 'data' field of the 'MetadataAsXmlInterop' structure), which
681    /// must be freed by the caller using 'libCZI_Free'.
682    ///
683    /// \\param          metadata_segment_object The metadata segment object.
684    /// \\param \[out\]    metadata_as_xml_interop If successful, the XML-metadata information is put here.
685    ///
686    /// \\returns    An error-code indicating success or failure of the operation.
687    pub fn get_metadata_as_xml(&self) -> Result<MetadataAsXml, Error> {
688        let mut metadata_as_xml_interop = MaybeUninit::uninit();
689        let ptr = metadata_as_xml_interop.as_mut_ptr();
690        lib_czi_error(unsafe { libCZI_MetadataSegmentGetMetadataAsXml(**self, ptr) })?;
691        Ok(unsafe { MetadataAsXml::assume_init(metadata_as_xml_interop) })
692    }
693
694    /// Create a CZI-document-information object from the specified metadata-segment object.
695    ///
696    /// \\param          metadata_segment_object The metadata segment object.
697    /// \\param \[in,out\] czi_document_info       If successful, a handle to the newly created CZI-document-info object is put here.
698    ///
699    /// \\returns    An error-code indicating success or failure of the operation.
700    pub fn get_czi_document_info(&self) -> Result<CziDocumentInfo, Error> {
701        let mut czi_document = MaybeUninit::uninit();
702        let ptr = czi_document.as_mut_ptr();
703        lib_czi_error(unsafe { libCZI_MetadataSegmentGetCziDocumentInfo(**self, ptr) })?;
704        Ok(unsafe { CziDocumentInfo::assume_init(czi_document) })
705    }
706
707    /// Release the specified metadata-segment object.
708    ///
709    /// \\param  metadata_segment_object The metadata-segment object to be released.
710    ///
711    /// \\returns    An error-code indicating success or failure of the operation.
712    pub fn release(&self) -> Result<(), Error> {
713        lib_czi_error(unsafe { libCZI_ReleaseMetadataSegment(**self) })?;
714        Ok(())
715    }
716}
717
718impl Drop for MetadataSegment {
719    fn drop(&mut self) {
720        self.release().ok();
721    }
722}
723
724impl CziDocumentInfo {
725    /// Get \"general document information\" from the specified czi-document information object. The information is returned as a JSON-formatted string.
726    /// The JSON returned is an object, with the following possible key-value pairs:
727    /// \"name\" : \<name of the document\>, type string
728    /// \"title\" : \<title of the document\>, type string
729    /// \"user_name\" : \<user name\>, type string
730    /// \"description\" : \<description\>, type string
731    /// \"comment\" : \<comment\>, type string
732    /// \"keywords\" : \<keyword1\>,\<keyword2\>,...\", type string
733    /// \"rating\" : \<rating\>, type integer
734    /// \"creation_date\" : \<creation date\>, type string, conforming to ISO 8601
735    ///
736    /// \\param          czi_document_info           The CZI-document-info object.
737    /// \\param \[out\]    general_document_info_json  If successful, the general document information is put here. Note that the data must be freed using 'libCZI_Free' by the caller.
738    ///
739    /// \\returns    An error-code indicating success or failure of the operation.
740    pub fn get_general_document_info(&self) -> Result<String, Error> {
741        let mut ptr = MaybeUninit::<*mut c_char>::uninit();
742        lib_czi_error(unsafe {
743            libCZI_CziDocumentInfoGetGeneralDocumentInfo(
744                **self,
745                ptr.as_mut_ptr() as *mut *mut c_void,
746            )
747        })?;
748        let ptr = unsafe { ptr.assume_init() };
749        assert!(!ptr.is_null());
750        let info = unsafe { CStr::from_ptr(ptr) }
751            .to_string_lossy()
752            .into_owned();
753        unsafe { libCZI_Free(ptr as *mut c_void) };
754        Ok(info)
755    }
756
757    /// Get scaling information from the specified czi-document information object. The information gives the size of an image pixels.
758    ///
759    /// \\param          czi_document_info           Handle to the CZI-document-info object from which the scaling information will be retrieved.
760    /// \\param \[out\]    scaling_info_interop        If successful, the scaling information is put here.
761    ///
762    /// \\returns        An error-code indicating success or failure of the operation.
763    pub fn get_scaling_info(&self) -> Result<ScalingInfo, Error> {
764        let mut scaling_info_interop = MaybeUninit::uninit();
765        let ptr = scaling_info_interop.as_mut_ptr();
766        lib_czi_error(unsafe { libCZI_CziDocumentInfoGetScalingInfo(**self, ptr) })?;
767        Ok(unsafe { ScalingInfo::assume_init(scaling_info_interop) })
768    }
769
770    /// Get the display-settings from the document's XML-metadata. The display-settings are returned in the form of an object,
771    /// for which a handle is returned.
772    ///
773    /// \\param          czi_document_info       The CZI-document-info object.
774    /// \\param \[in,out\] display_settings_handle If successful, a handle to the display-settings object is put here.
775    ///
776    /// \\returns    An error-code indicating success or failure of the operation.
777    pub fn get_display_settings(&self) -> Result<DisplaySettings, Error> {
778        let mut display_settings = MaybeUninit::uninit();
779        let ptr = display_settings.as_mut_ptr();
780        lib_czi_error(unsafe { libCZI_CziDocumentInfoGetDisplaySettings(**self, ptr) })?;
781        Ok(unsafe { DisplaySettings::assume_init(display_settings) })
782    }
783
784    /// Get the dimension information from the document's XML-metadata. The information is returned as a JSON-formatted string.
785    ///
786    /// \\param          czi_document_info       Handle to the CZI-document-info object from which the dimension information will be retrieved.
787    /// \\param          dimension_index         Index of the dimension.
788    /// \\param \[out\]    dimension_info_json     If successful, the information is put here as JSON format. Note that the data must be freed using 'libCZI_Free' by the caller.
789    ///
790    /// \\returns        An error-code indicating success or failure of the operation.
791    pub fn get_dimension_info(&self, dimension_index: u32) -> Result<String, Error> {
792        let mut ptr = MaybeUninit::<*mut c_char>::uninit();
793        lib_czi_error(unsafe {
794            libCZI_CziDocumentInfoGetDimensionInfo(
795                **self,
796                dimension_index,
797                ptr.as_mut_ptr() as *mut *mut c_void,
798            )
799        })?;
800        let ptr = unsafe { ptr.assume_init() };
801        assert!(!ptr.is_null());
802        Ok(unsafe { CStr::from_ptr(ptr) }
803            .to_string_lossy()
804            .into_owned())
805    }
806
807    /// Release the specified CZI-document-info object.
808    ///
809    /// \\param  czi_document_info The CZI-document-info object.
810    ///
811    /// \\returns    An error-code indicating success or failure of the operation.
812    pub fn release(&self) -> Result<(), Error> {
813        lib_czi_error(unsafe { libCZI_ReleaseCziDocumentInfo(**self) })?;
814        Ok(())
815    }
816}
817
818impl Drop for CziDocumentInfo {
819    fn drop(&mut self) {
820        self.release().ok();
821    }
822}
823
824impl OutputStream {
825    /// Create an output stream object for a file identified by its filename, which is given as a wide string. Note that wchar_t on
826    /// Windows is 16-bit wide, and on Unix-like systems it is 32-bit wide.
827    ///
828    /// \\param          filename                Filename of the file which is to be opened (zero terminated wide string). Note that on Windows, this
829    ///                                         is a string with 16-bit code units, and on Unix-like systems it is typically a string with 32-bit code units.
830    /// \\param          overwrite               Indicates whether the file should be overwritten.
831    /// \\param \[out\]    output_stream_object    The output stream object that will hold the created stream.
832    ///
833    /// \\return         An error-code that indicates whether the operation is successful or not. Non-positive values indicates successful, positive values
834    ///                 indicates unsuccessful operation.
835    pub fn create_for_file_wide(file_name: Vec<WChar>, overwrite: bool) -> Result<Self, Error> {
836        let mut output_stream = MaybeUninit::uninit();
837        let ptr = output_stream.as_mut_ptr();
838        lib_czi_error(unsafe {
839            libCZI_CreateOutputStreamForFileWide(file_name.as_ptr(), overwrite, ptr)
840        })?;
841        Ok(unsafe { Self::assume_init(output_stream) })
842    }
843
844    /// Create an input stream object for a file identified by its filename, which is given as an UTF8 - encoded string.
845    ///
846    /// \\param          filename                Filename of the file which is to be opened (in UTF8 encoding).
847    /// \\param          overwrite               Indicates whether the file should be overwritten.
848    /// \\param \[out\]    output_stream_object    The output stream object that will hold the created stream.
849    ///
850    /// \\return         An error-code that indicates whether the operation is successful or not. Non-positive values indicates successful, positive values
851    ///                 indicates unsuccessful operation.
852    pub fn create_for_file_utf8<S: AsRef<str>>(
853        file_name: S,
854        overwrite: bool,
855    ) -> Result<Self, Error> {
856        let mut output_stream = MaybeUninit::uninit();
857        let ptr = output_stream.as_mut_ptr();
858        let file_name = ManuallyDrop::new(CString::new(file_name.as_ref())?);
859        lib_czi_error(unsafe {
860            libCZI_CreateOutputStreamForFileUTF8(file_name.as_ptr(), overwrite, ptr)
861        })?;
862        Ok(unsafe { Self::assume_init(output_stream) })
863    }
864
865    /// Release the specified output stream object. After this function is called, the handle is no
866    /// longer valid. Note that calling this function will only decrement the usage count of the
867    /// underlying object; whereas the object itself (and the resources it holds) will only be
868    /// released when the usage count reaches zero.
869    ///
870    /// \\param  output_stream_object   The output stream object.
871    ///
872    /// \\returns    An error-code indicating success or failure of the operation.
873    pub fn release(&self) -> Result<(), Error> {
874        lib_czi_error(unsafe { libCZI_ReleaseOutputStream(**self) })?;
875        Ok(())
876    }
877
878    /// Create an output stream object which is using externally provided functions for operation
879    /// and writing the data. Please refer to the documentation of
880    /// 'ExternalOutputStreamStructInterop' for more information.
881    ///
882    /// \\param          external_output_stream_struct    Structure containing the information about the externally provided functions.
883    /// \\param \[out\]    output_stream_object             If successful, the handle to the newly created output stream object is put here.
884    ///
885    /// \\returns    An error-code indicating success or failure of the operation.
886    pub fn create_from_external(
887        external_input_stream: ExternalOutputStreamStruct,
888    ) -> Result<Self, Error> {
889        let mut stream = MaybeUninit::uninit();
890        let ptr = stream.as_mut_ptr();
891        lib_czi_error(unsafe {
892            libCZI_CreateOutputStreamFromExternal(external_input_stream.as_ptr(), ptr)
893        })?;
894        Ok(unsafe { Self::assume_init(stream) })
895    }
896}
897
898impl Drop for OutputStream {
899    fn drop(&mut self) {
900        self.release().ok();
901    }
902}
903
904impl CziWriter {
905    /// Create a writer object for authoring a document in CZI-format. The options string is a JSON-formatted string, here
906    /// is an example:
907    /// \\code
908    /// {
909    /// \"allow_duplicate_subblocks\" : true
910    /// }
911    /// \\endcode
912    ///
913    /// \\param \[out\] writer_object If the operation is successful, a handle to the newly created writer object is put here.
914    /// \\param       options       A JSON-formatted zero-terminated string (in UTF8-encoding) containing options for the writer creation.
915    ///
916    /// \\returns An error-code indicating success or failure of the operation.
917    pub fn create<S: AsRef<str>>(options: S) -> Result<Self, Error> {
918        let mut writer = MaybeUninit::uninit();
919        let ptr = writer.as_mut_ptr();
920        let options = ManuallyDrop::new(CString::new(options.as_ref())?);
921        lib_czi_error(unsafe { libCZI_CreateWriter(ptr, options.as_ptr()) })?;
922        Ok(unsafe { Self::assume_init(writer) })
923    }
924
925    /// Initializes the writer object with the specified output stream object. The options string is a JSON-formatted string, here
926    /// is an example:
927    /// \\code
928    /// {
929    /// \"file_guid\" : \"123e4567-e89b-12d3-a456-426614174000\",
930    /// \"reserved_size_attachments_directory\" : 4096,
931    /// \"reserved_size_metadata_segment\" : 50000,
932    /// \"minimum_m_index\" : 0,
933    /// \"maximum_m_index\" : 100
934    /// }
935    /// \\endcode
936    ///
937    /// \\param \[out\] writer_object If the operation is successful, a handle to the newly created writer object is put here.
938    /// \\param       output_stream_object The output stream object to be used for writing the CZI data.
939    /// \\param       parameters       A JSON-formatted zero-terminated string (in UTF8-encoding) containing options for the writer initialization.
940    ///
941    /// \\returns An error-code indicating success or failure of the operation.
942    pub fn init<S: AsRef<str>>(
943        &self,
944        output_stream: &OutputStream,
945        parameters: S,
946    ) -> Result<(), Error> {
947        let parameters = ManuallyDrop::new(CString::new(parameters.as_ref())?);
948        lib_czi_error(unsafe {
949            libCZI_WriterCreate(**self, **output_stream, parameters.as_ptr())
950        })?;
951        Ok(())
952    }
953
954    /// Add the specified sub-block to the writer object. The sub-block information is provided in the 'add_sub_block_info_interop' structure.
955    ///
956    /// \\param  writer_object               The writer object.
957    /// \\param  add_sub_block_info_interop  Information describing the sub-block to be added.
958    ///
959    /// \\returns    An error-code indicating success or failure of the operation.
960    pub fn add_sub_block(&self, add_sub_block_info: AddSubBlockInfo) -> Result<(), Error> {
961        lib_czi_error(unsafe { libCZI_WriterAddSubBlock(**self, add_sub_block_info.as_ptr()) })?;
962        Ok(())
963    }
964
965    /// Add the specified attachment to the writer object. The attachment is provided in the 'add_attachment_info_interop' structure.
966    ///
967    /// \\param  writer_object               The writer object.
968    /// \\param  add_attachment_info_interop Information describing the attachment to be added.
969    ///
970    /// \\returns    An error-code indicating success or failure of the operation.
971    pub fn add_attachement(&self, add_attachment_info: AddAttachmentInfo) -> Result<(), Error> {
972        lib_czi_error(unsafe { libCZI_WriterAddAttachment(**self, add_attachment_info.as_ptr()) })?;
973        Ok(())
974    }
975
976    /// Add the specified metadata to the writer object. The metadata is provided in the 'write_metadata_info_interop' structure.
977    ///
978    /// \\param  writer_object               Handle to the writer object to which the metadata will be added.
979    /// \\param  write_metadata_info_interop Information describing the metadata to be added.
980    ///
981    /// \\returns    An error-code indicating success or failure of the operation.
982    pub fn write_metadata(&self, write_metadata_info: WriteMetadataInfo) -> Result<(), Error> {
983        lib_czi_error(unsafe { libCZI_WriterWriteMetadata(**self, write_metadata_info.as_ptr()) })?;
984        Ok(())
985    }
986
987    /// inalizes the CZI (i.e. writes out the final directory-segments) and closes the file.
988    /// Note that this method must be called explicitly in order to get a valid CZI - calling 'libCZI_ReleaseWriter' without
989    /// a prior call to this method will close the file immediately without finalization.
990    ///
991    /// \\param  writer_object   Handle to the writer object that is to be closed.
992    ///
993    /// \\returns    An error-code indicating success or failure of the operation.
994    pub fn close(&self) -> Result<(), Error> {
995        lib_czi_error(unsafe { libCZI_WriterClose(**self) })?;
996        Ok(())
997    }
998
999    /// Release the specified writer object.
1000    ///
1001    /// \\param  writer_object Handle to the writer object that is to be released.
1002    ///
1003    /// \\returns    An error-code indicating success or failure of the operation.
1004    pub fn release(&self) -> Result<(), Error> {
1005        lib_czi_error(unsafe { libCZI_ReleaseWriter(**self) })?;
1006        Ok(())
1007    }
1008}
1009
1010impl Drop for CziWriter {
1011    fn drop(&mut self) {
1012        self.close().ok();
1013        self.release().ok();
1014    }
1015}
1016
1017impl SingleChannelScalingTileAccessor {
1018    /// Gets the size information of the specified tile accessor based on the region of interest and zoom factor.
1019    ///
1020    /// \\param  accessor_object     Handle to the tile accessor object for which the size is to be calculated. This object is responsible for managing the access to the tiles within the specified plane.
1021    /// \\param  roi                 The region of interest that defines the region of interest within the plane for which the size is to be calculated.
1022    /// \\param  zoom                A floating-point value representing the zoom factor.
1023    /// \\param  size \[out\]          The size of the tile accessor. It contains width and height information.
1024    ///
1025    /// \\returns    An error-code indicating success or failure of the operation.
1026    pub fn calc_size(&self, roi: IntRect, zoom: f32) -> Result<IntSize, Error> {
1027        let mut size = MaybeUninit::uninit();
1028        let ptr = size.as_mut_ptr();
1029        lib_czi_error(unsafe {
1030            libCZI_SingleChannelTileAccessorCalcSize(**self, roi.as_ptr(), zoom, ptr)
1031        })?;
1032        Ok(unsafe { IntSize::assume_init(size) })
1033    }
1034
1035    /// Gets the tile bitmap of the specified plane and the specified roi with the specified zoom factor.
1036    ///
1037    /// \\param  accessor_object         Handle to the tile accessor object. This object is responsible for managing the access to the tiles within the specified plane.
1038    /// \\param  coordinate              Pointer to a `CoordinateInterop` structure that specifies the coordinates within the plane from which the tile bitmap is to be retrieved.
1039    /// \\param  roi                     The region of interest that defines within the plane for which the tile bitmap is requested.
1040    /// \\param  zoom                    A floating-point value representing the zoom factor.
1041    /// \\param  options                 A pointer to an AccessorOptionsInterop structure that may contain additional options for accessing the tile bitmap.
1042    /// \\param  bitmap_object \[out\]     If the operation is successful, the created bitmap object will be put here.
1043    ///
1044    /// \\returns    An error-code indicating success or failure of the operation.
1045    pub fn get(
1046        &self,
1047        coordinate: Coordinate,
1048        roi: IntRect,
1049        zoom: f32,
1050        options: AccessorOptions,
1051    ) -> Result<Bitmap, Error> {
1052        let mut bitmap = MaybeUninit::uninit();
1053        let ptr = bitmap.as_mut_ptr();
1054        lib_czi_error(unsafe {
1055            libCZI_SingleChannelTileAccessorGet(
1056                **self,
1057                coordinate.as_ptr(),
1058                roi.as_ptr(),
1059                zoom,
1060                options.as_ptr(),
1061                ptr,
1062            )
1063        })?;
1064        Ok(unsafe { Bitmap::assume_init(bitmap) })
1065    }
1066
1067    /// Release the specified accessor object.
1068    ///
1069    /// \\param  accessor_object      The accessor object.
1070    ///
1071    /// \\returns    An error-code indicating success or failure of the operation.
1072    pub fn release(&self) -> Result<(), Error> {
1073        lib_czi_error(unsafe { libCZI_ReleaseCreateSingleChannelTileAccessor(**self) })?;
1074        Ok(())
1075    }
1076}
1077
1078impl Drop for SingleChannelScalingTileAccessor {
1079    fn drop(&mut self) {
1080        self.release().ok();
1081    }
1082}
1083
1084impl DisplaySettings {
1085    /// Given a display-settings object and the channel-number, this function fills out the
1086    /// composition-channel-information which is needed for the multi-channel-composition.
1087    /// Note that in the returned 'CompositionChannelInfoInterop' structure, the 'lut' field is a pointer to the LUT-data,
1088    /// which must be freed with 'libCZI_Free' by the caller.
1089    ///
1090    /// \\param          display_settings_handle             The display settings handle.
1091    /// \\param          channel_index                       The channel-index (referring to the display settings object) we are concerned with.
1092    /// \\param          sixteen_or_eight_bits_lut           True for generating a 16-bit LUT; if false, then an 8-bit LUT is generated.
1093    /// \\param \[out\]    composition_channel_info_interop    The composition channel information is put here.
1094    ///
1095    /// \\returns    An error-code indicating success or failure of the operation.
1096    pub fn compositor_fill_out_composition_channel_info_interop(
1097        &self,
1098        channel_index: i32,
1099        sixteen_or_eight_bits_lut: bool,
1100    ) -> Result<CompositionChannelInfo, Error> {
1101        let mut composition_channel_info = MaybeUninit::uninit();
1102        let ptr = composition_channel_info.as_mut_ptr();
1103        lib_czi_error(unsafe {
1104            libCZI_CompositorFillOutCompositionChannelInfoInterop(
1105                **self,
1106                channel_index,
1107                sixteen_or_eight_bits_lut,
1108                ptr,
1109            )
1110        })?;
1111        Ok(unsafe { CompositionChannelInfo::assume_init(composition_channel_info) })
1112    }
1113
1114    pub fn get_channel_display_settings(
1115        &self,
1116        channel_id: i32,
1117    ) -> Result<ChannelDisplaySettings, Error> {
1118        let mut channel_display_setting = MaybeUninit::uninit();
1119        let ptr = channel_display_setting.as_mut_ptr();
1120        lib_czi_error(unsafe {
1121            libCZI_DisplaySettingsGetChannelDisplaySettings(**self, channel_id, ptr)
1122        })?;
1123        Ok(unsafe { ChannelDisplaySettings::assume_init(channel_display_setting) })
1124    }
1125
1126    /// Release the specified display settings object.
1127    ///
1128    /// \\param  display_settings_handle      The display settings object.
1129    ///
1130    /// \\returns    An error-code indicating success or failure of the operation.
1131    pub fn release(&self) -> Result<(), Error> {
1132        lib_czi_error(unsafe { libCZI_ReleaseDisplaySettings(**self) })?;
1133        Ok(())
1134    }
1135}
1136
1137impl Drop for DisplaySettings {
1138    fn drop(&mut self) {
1139        self.release().ok();
1140    }
1141}
1142
1143/// Perform a multi-channel-composition operation. The source bitmaps are provided in the 'source_bitmaps' array, and the
1144/// array of 'CompositionChannelInfoInterop' structures provide the information needed for the composition. The resulting bitmap
1145/// is then put into the 'bitmap_object' handle.
1146///
1147/// \\param       channelCount       The number of channels - this defines the size of the 'source_bitmaps' and 'channel_info' arrays.
1148/// \\param       source_bitmaps     The array of source bitmaps.
1149/// \\param       channel_info       The array of channel information.
1150/// \\param \[out\] bitmap_object      The resulting bitmap is put here.
1151///
1152/// \\return     An error-code indicating success or failure of the operation.
1153pub fn compositor_do_multi_channel_composition(
1154    channel_count: i32,
1155    source_bitmaps: Vec<Bitmap>,
1156    channel_info: CompositionChannelInfo,
1157) -> Result<Bitmap, Error> {
1158    let mut bitmap = MaybeUninit::uninit();
1159    let ptr = bitmap.as_mut_ptr();
1160    lib_czi_error(unsafe {
1161        libCZI_CompositorDoMultiChannelComposition(
1162            channel_count,
1163            source_bitmaps.as_ptr() as *const BitmapObjectHandle,
1164            channel_info.as_ptr(),
1165            ptr,
1166        )
1167    })?;
1168    Ok(unsafe { Bitmap::assume_init(bitmap) })
1169}
1170
1171impl ChannelDisplaySettings {
1172    /// Release the specified channel-display settings object.
1173    ///
1174    /// \\param  channel_display_settings_handle      The channel-display settings object.
1175    ///
1176    /// \\returns    An error-code indicating success or failure of the operation.
1177    pub fn release(&self) -> Result<(), Error> {
1178        lib_czi_error(unsafe { libCZI_ReleaseDisplaySettings(**self) })?;
1179        Ok(())
1180    }
1181}
1182
1183impl Drop for ChannelDisplaySettings {
1184    fn drop(&mut self) {
1185        self.release().ok();
1186    }
1187}