Skip to content

Commit 355ecc8

Browse files
authored
Merge pull request #313 from image-rs/decode-planar-data
Implement support for planar data
2 parents 985f382 + 2d90179 commit 355ecc8

File tree

7 files changed

+946
-343
lines changed

7 files changed

+946
-343
lines changed

examples/decode.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
use tiff::decoder::{BufferLayoutPreference, Decoder, DecodingBuffer, DecodingResult};
2+
3+
fn main() -> Result<(), Box<dyn std::error::Error>> {
4+
let Some(image) = std::env::args_os().nth(1) else {
5+
eprintln!("Usage: decode FILE");
6+
return Ok(());
7+
};
8+
9+
let file = std::fs::File::open(image)?;
10+
let io = std::io::BufReader::new(file);
11+
let mut reader = Decoder::new(io)?;
12+
13+
let mut data = DecodingResult::I8(vec![]);
14+
15+
for i in 0u32.. {
16+
let colortype = reader.colortype()?;
17+
let dimensions = reader.dimensions()?;
18+
let layout = reader.read_image_to_buffer(&mut data)?;
19+
20+
debug_planes(i, &mut data, &layout, &colortype, dimensions);
21+
22+
if !reader.more_images() {
23+
break;
24+
}
25+
26+
reader.next_image()?
27+
}
28+
29+
Ok(())
30+
}
31+
32+
fn debug_planes(
33+
index: u32,
34+
data: &mut DecodingResult,
35+
layout: &BufferLayoutPreference,
36+
colortype: &tiff::ColorType,
37+
(width, height): (u32, u32),
38+
) {
39+
let (depth, mut tupltype) = match colortype {
40+
tiff::ColorType::Gray(_) => (1, "GRAYSCALE"),
41+
tiff::ColorType::RGB(_) => (3, "RGB"),
42+
tiff::ColorType::RGBA(_) => (4, "RGB_ALPHA"),
43+
tiff::ColorType::Palette(_) => (1, "PALETTE"),
44+
tiff::ColorType::CMYK(_) => (4, "CMYK"),
45+
tiff::ColorType::Multiband { num_samples: 2, .. } => (2, "GRAYSCALE_ALPHA"),
46+
_ => {
47+
eprintln!("Unsupported color type for PAM output: {:?}", colortype);
48+
return;
49+
}
50+
};
51+
52+
let maxval = match data.as_buffer(0) {
53+
DecodingBuffer::U8(_) => u64::from(u8::MAX),
54+
DecodingBuffer::U16(_) => u64::from(u16::MAX),
55+
DecodingBuffer::U32(_) => u64::from(u32::MAX),
56+
DecodingBuffer::U64(_) => u64::MAX,
57+
// Eh, this is a good effort I guess.
58+
DecodingBuffer::I8(items) => {
59+
items.iter_mut().for_each(|v| *v = 0.max(*v));
60+
u64::from(i8::MAX as u8)
61+
}
62+
DecodingBuffer::I16(items) => {
63+
items.iter_mut().for_each(|v| *v = 0.max(*v));
64+
u64::from(i16::MAX as u16)
65+
}
66+
DecodingBuffer::I32(items) => {
67+
items.iter_mut().for_each(|v| *v = 0.max(*v));
68+
u64::from(i32::MAX as u32)
69+
}
70+
DecodingBuffer::I64(items) => {
71+
items.iter_mut().for_each(|v| *v = 0.max(*v));
72+
i64::MAX as u64
73+
}
74+
// Not supported by PAM.
75+
DecodingBuffer::F16(_) | DecodingBuffer::F32(_) | DecodingBuffer::F64(_) => return,
76+
};
77+
78+
let byte_len = if layout.planes > 1 {
79+
tupltype = "GRAYSCALE";
80+
layout.plane_stride.unwrap().get()
81+
} else {
82+
data.as_buffer(0).byte_len()
83+
};
84+
85+
// Write out this image's planes to PAM files.
86+
let header = format!("P7\nWIDTH {width}\nHEIGHT {height}\nDEPTH {depth}\nMAXVAL {maxval}\nTUPLTYPE {tupltype}\nENDHDR\n");
87+
88+
for (plane, plane_data) in data
89+
.as_buffer(0)
90+
.as_bytes_mut()
91+
.chunks_exact(byte_len)
92+
.enumerate()
93+
{
94+
let filename = format!("image_{index:03}_plane_{plane:03}.pam");
95+
let mut file = std::fs::File::create(filename).expect("Failed to create output file");
96+
97+
use std::io::Write;
98+
file.write_all(header.as_bytes())
99+
.expect("Failed to write PAM header");
100+
file.write_all(plane_data)
101+
.expect("Failed to write PAM data");
102+
}
103+
}

0 commit comments

Comments
 (0)