summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/binfile.rs13
-rw-r--r--src/lib.rs17
-rw-r--r--src/tiff.rs84
3 files changed, 110 insertions, 4 deletions
diff --git a/src/binfile.rs b/src/binfile.rs
index a43f568..5b0b783 100644
--- a/src/binfile.rs
+++ b/src/binfile.rs
@@ -12,3 +12,16 @@ pub fn dump_u32_vec(file_name: &str, data: Vec<u32>) -> Result<(), Error> {
}
Ok(())
}
+
+pub fn dump_u16_vec(file_name: &str, data: Vec<u16>) -> Result<(), Error> {
+ use std::fs::File;
+ use std::io::Write;
+ if let Ok(mut file) = File::create(file_name) {
+ for value in data {
+ file.write_all(&value.to_le_bytes())?;
+ }
+ } else {
+ return Err(Error::new(ErrorKind::Other, "Error creating file"));
+ }
+ Ok(())
+}
diff --git a/src/lib.rs b/src/lib.rs
index b8e6d2d..bf5c7f0 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -3,6 +3,7 @@ pub mod binfile;
pub const TEST_IMAGE_PATH: &str = "../test.tif";
pub const TEST_OUTPUT_PATH: &str = "../test.bin";
+pub const TEST_LABEL_OUTPUT_PATH: &str = "../test.c.bin";
#[cfg(test)]
mod tests {
@@ -80,7 +81,21 @@ mod tests {
fn tiff_data_dump_test() {
tiff::ignore_warnings();
if let Some(standard_format) = tiff::as_standard_format(TEST_IMAGE_PATH) {
- binfile::dump_u32_vec(TEST_OUTPUT_PATH, standard_format).expect("File output error");
+ println!("{:?}", standard_format);
+ let data = standard_format.buffer;
+ binfile::dump_u32_vec(TEST_OUTPUT_PATH, data).expect("File output error");
+ } else {
+ assert!(false);
+ }
+ }
+
+ #[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);
+ let data = compressed_format.buffer;
+ binfile::dump_u16_vec(TEST_LABEL_OUTPUT_PATH, data).expect("File output error");
} else {
assert!(false);
}
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<u32>,
+ pub width: usize,
+ pub height: usize,
+}
+
+pub struct CompressedOutput {
+ pub buffer: Vec<u16>,
+ 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<u8> {
total_buf
}
-pub fn as_standard_format(tiff_file_name: &str) -> Option<Vec<u32>> {
+pub fn as_standard_format(tiff_file_name: &str) -> Option<StandardOutput> {
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<Vec<u32>> {
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<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::*;