summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcc <cc@localhost>2025-08-20 20:09:34 -0700
committercc <cc@localhost>2025-08-20 20:09:34 -0700
commitabdbc42639d0acd6fc0db381f7cbe6a37928643f (patch)
tree61d779ad5fe85020d3301106b72c1d1f859200d6
parenta7ded0a844feac401be72a5b575cb0e0c3e12e01 (diff)
Modularize Label Formats
-rw-r--r--src/label_formats/label_format.rs5
-rw-r--r--src/label_formats/large_label_format.rs66
-rw-r--r--src/label_formats/mod.rs6
-rw-r--r--src/lib.rs7
-rw-r--r--src/tiff.rs74
5 files changed, 84 insertions, 74 deletions
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<u16>,
+ 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<u32>,
+ 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<u16>,
+ 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<u16> = 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<u32>,
- pub width: usize,
- pub height: usize,
-}
-
-pub struct CompressedOutput {
- pub buffer: Vec<u16>,
- 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<u8> {
total_buf
}
-pub fn as_standard_format(tiff_file_name: &str) -> Option<StandardOutput> {
+pub fn to_large_labels(tiff_file_name: &str) -> Option<LargeLabelFormat> {
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<StandardOutput> {
}
}
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<StandardOutput> {
return None;
}
-fn flood(source: &StandardOutput, destination: &mut Vec<u16>,
- 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<u16> = 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::*;