From abdbc42639d0acd6fc0db381f7cbe6a37928643f Mon Sep 17 00:00:00 2001 From: cc Date: Wed, 20 Aug 2025 20:09:34 -0700 Subject: Modularize Label Formats --- src/label_formats/label_format.rs | 5 +++ src/label_formats/large_label_format.rs | 66 +++++++++++++++++++++++++++++ src/label_formats/mod.rs | 6 +++ src/lib.rs | 7 ++-- src/tiff.rs | 74 ++------------------------------- 5 files changed, 84 insertions(+), 74 deletions(-) create mode 100644 src/label_formats/label_format.rs create mode 100644 src/label_formats/large_label_format.rs create mode 100644 src/label_formats/mod.rs diff --git a/src/label_formats/label_format.rs b/src/label_formats/label_format.rs new file mode 100644 index 0000000..0f33932 --- /dev/null +++ b/src/label_formats/label_format.rs @@ -0,0 +1,5 @@ +pub struct LabelFormat { + pub buffer: Vec, + pub width: usize, + pub height: usize, +} diff --git a/src/label_formats/large_label_format.rs b/src/label_formats/large_label_format.rs new file mode 100644 index 0000000..121a4df --- /dev/null +++ b/src/label_formats/large_label_format.rs @@ -0,0 +1,66 @@ +use super::LabelFormat; + +pub struct LargeLabelFormat { + pub buffer: Vec, + pub width: usize, + pub height: usize, +} + +impl std::fmt::Debug for LargeLabelFormat { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("LargeLabelFormat") + .field("width", &self.width) + .field("height", &self.height) + .finish() + } +} + +fn flood(source: &LargeLabelFormat, 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 compress_large_labels(buffer: LargeLabelFormat) -> LabelFormat { + 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 LabelFormat { + buffer: output_buffer, + width: buffer.width, + height: buffer.height, + }; +} diff --git a/src/label_formats/mod.rs b/src/label_formats/mod.rs new file mode 100644 index 0000000..7386df8 --- /dev/null +++ b/src/label_formats/mod.rs @@ -0,0 +1,6 @@ +mod large_label_format; +mod label_format; + +pub use large_label_format::LargeLabelFormat; +pub use large_label_format::compress_large_labels; +pub use label_format::LabelFormat; diff --git a/src/lib.rs b/src/lib.rs index bf5c7f0..3af14d1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ pub mod tiff; pub mod binfile; +pub mod label_formats; pub const TEST_IMAGE_PATH: &str = "../test.tif"; pub const TEST_OUTPUT_PATH: &str = "../test.bin"; @@ -80,7 +81,7 @@ mod tests { #[test] fn tiff_data_dump_test() { tiff::ignore_warnings(); - if let Some(standard_format) = tiff::as_standard_format(TEST_IMAGE_PATH) { + if let Some(standard_format) = tiff::to_large_labels(TEST_IMAGE_PATH) { println!("{:?}", standard_format); let data = standard_format.buffer; binfile::dump_u32_vec(TEST_OUTPUT_PATH, data).expect("File output error"); @@ -92,8 +93,8 @@ mod tests { #[test] fn tiff_compressed_data_dump_test() { tiff::ignore_warnings(); - if let Some(standard_format) = tiff::as_standard_format(TEST_IMAGE_PATH) { - let compressed_format = tiff::standard_to_labels(standard_format); + if let Some(standard_format) = tiff::to_large_labels(TEST_IMAGE_PATH) { + let compressed_format = label_formats::compress_large_labels(standard_format); let data = compressed_format.buffer; binfile::dump_u16_vec(TEST_LABEL_OUTPUT_PATH, data).expect("File output error"); } else { diff --git a/src/tiff.rs b/src/tiff.rs index 2baba80..67d4aec 100644 --- a/src/tiff.rs +++ b/src/tiff.rs @@ -1,26 +1,8 @@ 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, -} +use crate::label_formats::LargeLabelFormat; -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 @@ -154,7 +136,7 @@ pub fn read(tiff_ptr: *mut TIFF) -> Vec { total_buf } -pub fn as_standard_format(tiff_file_name: &str) -> Option { +pub fn to_large_labels(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); @@ -183,7 +165,7 @@ pub fn as_standard_format(tiff_file_name: &str) -> Option { } } close(tiff); - return Some(StandardOutput { + return Some(LargeLabelFormat { buffer: standard_buffer, width, height, @@ -193,56 +175,6 @@ pub fn as_standard_format(tiff_file_name: &str) -> Option { 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