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
use log::{error, info};
use std::{collections::BTreeMap, fs, time::Instant};
use tiff2::{decoder::Decoder, error::TiffResult};
mod common;
use common::{img_print, TokioFile};
#[tokio::main]
async fn main() -> TiffResult<()> {
env_logger::init();
let mut m = BTreeMap::new();
let mut prev = Instant::now();
for p in fs::read_dir("./tests/img/gdal/out").unwrap() {
let path = p.unwrap().path();
if !path.is_file() {
continue;
}
if let Some(ex) = path.extension() {
if ex != "tif" && ex != "tiff" {
continue;
}
} else {
continue;
}
let fname = path.file_name().unwrap().to_str().unwrap().to_owned();
//
if !fname.contains("RGBA") {
continue;
}
if !fname.contains("PIXEL") {
continue;
}
// if !fname.contains("YES") {
// continue;
// }
// if !fname.contains("RGB_") {continue;}
// if fname.contains("Byte") {
// continue;
// }
// if fname.contains("UI") {
// continue;
// }
// if fname.contains("Float") {
// continue;
// }
// if fname.contains("JPEG") {
// continue;
// }
// if fname.contains("pred2") {
// continue;
// }
info!("testing {path:?}");
#[allow(unused)]
let t = fname.split_once('_').unwrap().0;
let f = TokioFile::new(path).unwrap();
info!("testing {:42}: type: {:?}", f.0.to_str().unwrap(), fname);
let mut d = Decoder::new(f).await.expect("Could not make decoder");
d.scan_ifds().await.expect("can scan ifds");
d.read_image_ifds().await.expect("can read images");
match d.decode_image(0).await {
#[allow(unused)]
Ok(res) => img_print(res, &d.get_overview(0)?.chunk_opts),
Err(e) => error!("help! {e}"),
}
// image ordering in case of planar configuration:
// > The components are stored in separate “component planes.” The
// > values in StripOffsets and StripByteCounts are then arranged as a 2-dimensional
// > array, with SamplesPerPixel rows and StripsPerImage columns. (All of the col-
// > umns for row 0 are stored first, followed by the columns of row 1, and so on.)
// > PhotometricInterpretation describes the type of data stored in each component
// > plane. For example, RGB data is stored with the Red components in one compo-
// > nent plane, the Green in another, and the Blue in another.
// so:
// spp
// ^
// |
// +--> chunks
// ___col0___________col2_______________colN______
// row1 | Chunk1[RED] , Chunk2[RED] , ... ChunkN[RED]
// row2 | Chunk1[GREEN], Chunk2[GREEN], ... ChunkN[GREEN]
// row3 | Chunk1[BLUE] , Chunk2[BLUE] , ... ChunkN[BLUE]
// "in memory": [Chunk1[RED],Chunk2[RED],...ChunkN[RED],Chunk1[GREEN]...]
// give the chunks to expand_chunk
let n = Instant::now();
m.insert(n - prev, fname.clone());
info!("decoding {:?} cost {:?}", &m[&(n - prev)], n - prev);
// sleep(Duration::from_millis(2000).saturating_sub(n-prev)).await;
prev = n;
}
for (k, v) in m.iter().rev().take(10) {
println!("{v:32} took {k:?}",);
}
Ok(())
}
#[test]
fn test_image_grouping() {
let width: usize = 13;
let height: usize = 13;
let chwidth: usize = 3;
let chheight: usize = 3;
let chunks_down: usize = height.div_ceil(chheight);
let chunks_across: usize = width.div_ceil(chwidth);
let mut data: Vec<_> = (0..width * height).collect();
println!("OG:");
for (i, row) in data.chunks(width).enumerate() {
for chslice in row.chunks(chwidth) {
print!("{chslice:2?} ");
}
println!("");
if (i % chheight) == chheight - 1 {
println!("");
}
}
let row_groups: Vec<_> = data
.chunks_mut(width * chheight)
.enumerate()
.map(|(rg_i, rg)| {
let c_height = if rg_i + 1 == chunks_down {
height % chheight
} else {
chheight
};
let mut chunked = rg
.chunks_mut(width)
.map(|row| row.chunks_mut(chwidth).collect::<Vec<_>>())
.flatten()
.map(|c| Some(c))
.collect::<Vec<_>>();
let mut rearranged =
row_major_to_col_major(&mut chunked, chunks_across, c_height).unwrap();
// rearranged//.chunks_mut(c_height).flatten().collect::Vec<_>()
// rearranged.collect::<Vec<_>>().chunks_mut(c_height).collect::<Vec<_>>()
for (i, ch) in rearranged.chunks_mut(c_height).enumerate() {
let index = i + rg_i * chunks_across;
println!("chunk {index}");
println!("{ch:?}");
}
})
// .enumerate()
// .map(|(i, mut rg)| {
// let c_height = if i+1 == chunks_down { height % chheight } else {chheight};
// rg.chunks_mut(c_height).collect::<Vec<_>>()
// })
// .flatten()
// .flatten()
// .map(|c| Some(c))
.collect::<Vec<_>>();
println!("reorganized:");
for rg in row_groups {
println!("{rg:?}");
}
panic!()
}