1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
|
use std::os::raw::{c_char, c_uint, c_void, c_longlong, c_long};
use std::ffi::CString;
/// # TIFF Internal Structure
/// An opaque type
#[repr(C)]
pub struct TIFF {
_unused: [u8; 0],
}
/// # TIFF Warning Handler Definition
type TIFFWarningHandler = Option<unsafe extern "C" fn(module: *const c_char, fmt: *const c_char, ap: *mut c_void)>;
/// # TIFF Ignore Warnings Handle
unsafe extern "C" fn tiff_ignore_warning_handle(_module: *const c_char, _fmt: *const c_char, _ap: *mut std::ffi::c_void) {
// Do nothing
}
#[link(name = "tiff")]
unsafe extern "C" {
fn TIFFSetWarningHandler(handler: TIFFWarningHandler) -> TIFFWarningHandler;
fn TIFFOpen(filename: *const c_char, mode: *const c_char) -> *mut TIFF;
fn TIFFClose(tiff_ptr: *mut TIFF);
fn TIFFGetField(tiff_ptr: *mut TIFF, tag: c_uint, ...) -> c_long;
fn TIFFStripSize(tiff_ptr: *mut TIFF) -> c_longlong;
fn TIFFNumberOfStrips(tiff_ptr: *mut TIFF) -> c_longlong;
fn TIFFReadRawStrip(tiff_ptr: *mut TIFF, strip: c_uint, buf: *mut c_void, size: c_longlong) -> c_longlong;
}
/// From tiff.h
const TIFFTAG_IMAGEWIDTH: u32 = 256;
/// From tiff.h
const TIFFTAG_IMAGEHEIGHT: u32 = 257;
/// # Ignore TIFF Warnings
pub fn ignore_warnings() {
unsafe {
let _ = TIFFSetWarningHandler(Some(tiff_ignore_warning_handle));
}
}
/// # Open TIFF File
pub fn open(filename: &str) -> Option<*mut TIFF> {
let c_filename = CString::new(filename).expect("Cast error");
let c_mode = CString::new("r").expect("Cast error");
unsafe {
let result = TIFFOpen(c_filename.as_ptr(), c_mode.as_ptr());
if result.is_null() {
return None;
} else {
return Some(result);
}
}
}
/// # Close TIFF File
pub fn close(tiff_ptr: *mut TIFF) {
unsafe {
TIFFClose(tiff_ptr);
}
}
pub fn get_image_width(tiff_ptr: *mut TIFF) -> usize {
let mut width: u32 = 0;
unsafe {
let status = TIFFGetField(tiff_ptr, TIFFTAG_IMAGEWIDTH, &mut width as *mut u32);
}
return width as usize;
}
pub fn get_image_height(tiff_ptr: *mut TIFF) -> usize {
let mut height: u32 = 0;
unsafe {
let status = TIFFGetField(tiff_ptr, TIFFTAG_IMAGEHEIGHT, &mut height as *mut u32);
}
return height as usize;
}
pub fn get_image_channels(tiff_ptr: *mut TIFF) -> usize {
let strip_size = get_strip_size(tiff_ptr);
let strip_count = get_strip_count(tiff_ptr);
let width = get_image_width(tiff_ptr);
let height = get_image_height(tiff_ptr);
return (strip_size * strip_count) / (width * height);
}
fn get_strip_size(tiff_ptr: *mut TIFF) -> usize {
unsafe {
TIFFStripSize(tiff_ptr) as usize
}
}
fn get_strip_count(tiff_ptr: *mut TIFF) -> usize {
unsafe {
TIFFNumberOfStrips(tiff_ptr) as usize
}
}
fn read_strip(tiff_ptr: *mut TIFF, strip: u32) -> Vec<u8> {
let strip_size = get_strip_size(tiff_ptr);
assert!(strip_size>0);
let mut buf: Vec<u8> = vec![0u8; strip_size as usize];
unsafe {
TIFFReadRawStrip(tiff_ptr, strip, buf.as_mut_ptr() as *mut c_void, strip_size as c_longlong);
}
buf
}
pub fn read(tiff_ptr: *mut TIFF) -> Vec<u8> {
let strip_size = get_strip_size(tiff_ptr);
let strip_count = get_strip_count(tiff_ptr);
let mut total_buf: Vec<u8> = vec![0u8; (strip_size * strip_count) as usize];
for strip_index in 0..strip_count {
let sub_buffer: Vec<u8> = read_strip(tiff_ptr, strip_index as u32);
let base_index = strip_index * strip_size;
for data_index in 0..strip_size {
let total_index = base_index + data_index;
let data = sub_buffer[data_index as usize];
total_buf[total_index as usize] = data;
}
}
total_buf
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn tiff_strip_size() {
ignore_warnings();
if let Some(t_handle) = open(crate::TEST_IMAGE_PATH) {
let strip_size = get_strip_size(t_handle);
assert!(strip_size > 0);
close(t_handle);
} else {
assert!(false);
}
}
#[test]
fn tiff_strip_count() {
ignore_warnings();
if let Some(t_handle) = open(crate::TEST_IMAGE_PATH) {
let strip_count = get_strip_count(t_handle);
assert!(strip_count > 0);
close(t_handle);
} else {
assert!(false);
}
}
#[test]
fn tiff_strip_read() {
ignore_warnings();
if let Some(t_handle) = open(crate::TEST_IMAGE_PATH) {
let strip = read_strip(t_handle, 0);
close(t_handle);
} else {
assert!(false);
}
}
#[test]
fn tiff_data_depth() {
ignore_warnings();
if let Some(t_handle) = open(crate::TEST_IMAGE_PATH) {
let strip_size = get_strip_size(t_handle);
let strip_count = get_strip_count(t_handle);
let strip_depth = strip_size * strip_count;
assert!(strip_depth > 0);
let image_width = get_image_width(t_handle);
let image_height = get_image_height(t_handle);
let image_depth = image_width * image_height;
assert!(image_depth > 0);
let strip_depth = strip_depth as f64;
let image_depth = image_depth as f64;
close(t_handle);
} else {
assert!(false);
}
}
}
|