From a7ded0a844feac401be72a5b575cb0e0c3e12e01 Mon Sep 17 00:00:00 2001 From: cc Date: Wed, 20 Aug 2025 19:56:24 -0700 Subject: Standardize Label Structures Compress processed masks to simple labels Dump simple labels to file --- src/tiff.rs | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 81 insertions(+), 3 deletions(-) (limited to 'src/tiff.rs') diff --git a/src/tiff.rs b/src/tiff.rs index a1d19eb..2baba80 100644 --- a/src/tiff.rs +++ b/src/tiff.rs @@ -1,6 +1,27 @@ use std::os::raw::{c_char, c_uint, c_void, c_longlong, c_long}; use std::ffi::CString; +pub struct StandardOutput { + pub buffer: Vec, + pub width: usize, + pub height: usize, +} + +pub struct CompressedOutput { + pub buffer: Vec, + pub width: usize, + pub height: usize, +} + +impl std::fmt::Debug for StandardOutput { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("StandardOutput") + .field("width", &self.width) + .field("height", &self.height) + .finish() + } +} + /// # TIFF Internal Structure /// An opaque type #[repr(C)] @@ -133,7 +154,7 @@ pub fn read(tiff_ptr: *mut TIFF) -> Vec { total_buf } -pub fn as_standard_format(tiff_file_name: &str) -> Option> { +pub fn as_standard_format(tiff_file_name: &str) -> Option { if let Some(tiff) = open(tiff_file_name) { let width_opt = get_image_width(tiff); let height_opt = get_image_height(tiff); @@ -153,18 +174,75 @@ pub fn as_standard_format(tiff_file_name: &str) -> Option> { for c in 0..channels { let data: u8 = tiff_data[c + channels * (x + width * y)]; let data: u32 = data as u32; - let data = data << (8 * c); + let mut data = data << (8 * c); + if (channels == 4) && (c == 3) { + data = 0; + } standard_buffer[x + width*y] += data; } } } close(tiff); - return Some(standard_buffer); + return Some(StandardOutput { + buffer: standard_buffer, + width, + height, + }); } // Otherwise return None; } +fn flood(source: &StandardOutput, destination: &mut Vec, + x: usize, y: usize, + from_color: u32, to_color: u16) { + let width = source.width; + let destination_color = destination[x + y * width]; + if destination_color != 0 { + return; + } + let source_color = source.buffer[x + y * width]; + if source_color != from_color { + return; + } + destination[x + y * width] = to_color; + if x > 0 { + flood(source, destination, x-1, y, from_color, to_color); + } + if (x+1) < width { + flood(source, destination, x+1, y, from_color, to_color); + } + if y > 0 { + flood(source, destination, x, y-1, from_color, to_color); + } + if (y+1) < source.height { + flood(source, destination, x, y+1, from_color, to_color); + } +} + +pub fn standard_to_labels(buffer: StandardOutput) -> CompressedOutput { + let mut label: u16 = 1; + let mut output_buffer: Vec = vec![0u16; buffer.buffer.len()]; + for y in 0..buffer.height { + for x in 0..buffer.width { + let index = x + y*buffer.width; + if buffer.buffer[index] == 0 { + continue; + } + if output_buffer[index] == 0 { + let color = buffer.buffer[index]; + flood(&buffer, &mut output_buffer, x, y, color, label); + label += 1; + } + } + } + return CompressedOutput { + buffer: output_buffer, + width: buffer.width, + height: buffer.height, + }; +} + #[cfg(test)] mod tests { use super::*; -- cgit v1.2.1