1#![allow(unused)]
2
3use std::io::Read;
4
5use crate::components::transformations::ColorRange;
6use crate::components::transformations::Transform;
7use crate::error::*;
8use crate::numbers::chances::{ChanceTable, UpdateTable};
9use crate::numbers::near_zero::NearZeroCoder;
10use crate::numbers::rac::{Rac, RacRead};
11use crate::pixels::{ColorSpace, ColorValue, RgbaChannels};
12use crate::DecodingImage;
13use crate::FlifInfo;
14use crate::Limits;
15
16mod pvec;
17pub(crate) use self::pvec::{core_pvec, edge_pvec};
18
19pub struct ManiacTree<'a> {
20 nodes: Vec<ManiacNode<'a>>,
21}
22
23impl<'a> ManiacTree<'a> {
24 pub fn new<R: Read>(
25 rac: &mut Rac<R>,
26 channel: RgbaChannels,
27 info: &FlifInfo,
28 update_table: &'a UpdateTable,
29 limits: &Limits,
30 ) -> Result<ManiacTree<'a>> {
31 let context_a = ChanceTable::new(update_table);
32 let context_b = ChanceTable::new(update_table);
33 let context_c = ChanceTable::new(update_table);
34
35 let prange = Self::build_prange_vec(channel, info);
36 let nodes = Self::create_nodes(
37 rac,
38 &mut [context_a, context_b, context_c],
39 update_table,
40 prange,
41 limits,
42 )?;
43
44 Ok(ManiacTree { nodes })
45 }
46
47 pub fn size(&self) -> usize {
48 return self.nodes.len();
49 }
50
51 pub fn depth(&self) -> usize {
52 use self::ManiacNode::*;
53
54 let mut largest_depth = 0;
55
56 let mut stack = vec![(0, 1)];
57 loop {
58 let (index, depth) = match stack.pop() {
59 Some(index) => index,
60 None => break largest_depth,
61 };
62
63 largest_depth = ::std::cmp::max(largest_depth, depth);
64
65 match self.nodes[index] {
66 Property { left, right, .. }
67 | InactiveProperty { left, right, .. }
68 | Inner { left, right, .. } => {
69 stack.push((right, depth + 1));
70 stack.push((left, depth + 1));
71 }
72 _ => {
73 continue;
74 }
75 };
76 }
77 }
78
79 pub fn process<R: Read>(
80 &mut self,
81 rac: &mut Rac<R>,
82 pvec: &[ColorValue],
83 guess: ColorValue,
84 min: ColorValue,
85 max: ColorValue,
86 ) -> Result<ColorValue> {
87 if min == max {
88 return Ok(min);
89 }
90
91 let val = self.apply(rac, pvec, min - guess, max - guess)?;
92 Ok(val + guess)
93 }
94
95 fn create_nodes<R: Read>(
96 rac: &mut Rac<R>,
97 context: &mut [ChanceTable; 3],
98 update_table: &'a UpdateTable,
99 prange: Vec<ColorRange>,
100 limits: &Limits,
101 ) -> Result<Vec<ManiacNode<'a>>> {
102 use self::ManiacNode::*;
103
104 let mut result_vec = vec![ManiacNode::InactiveLeaf];
105 let mut process_stack = vec![(0, prange)];
106 loop {
107 let (index, prange) = match process_stack.pop() {
108 Some(process) => process,
109 _ => break,
110 };
111
112 if result_vec.len() > limits.maniac_nodes as usize {
113 Err(Error::LimitViolation(format!(
114 "number of maniac nodes exceeds limit"
115 )))?;
116 }
117
118 let child_start = result_vec.len();
119 let node = if index == 0 {
120 Self::create_node(child_start, rac, context, update_table, &prange)?
121 } else {
122 Self::create_inner_node(child_start, rac, context, &prange)?
123 };
124
125 let (property, test_value) = match node {
126 Property { id, value, .. }
127 | InactiveProperty { id, value, .. }
128 | Inner { id, value, .. } => {
129 if child_start >= result_vec.len() {
130 result_vec.resize(child_start + 2, ManiacNode::InactiveLeaf);
131 }
132 (id, value)
133 }
134 _ => {
135 result_vec[index] = node;
136 continue;
137 }
138 };
139
140 let mut left_prange = prange.clone();
141 left_prange[property as usize].min = test_value + 1;
142
143 let mut right_prange = prange;
144 right_prange[property as usize].max = test_value;
145
146 process_stack.push((child_start + 1, right_prange));
147 process_stack.push((child_start, left_prange));
148 result_vec[index] = node;
149 }
150
151 Ok(result_vec)
152 }
153
154 fn create_node<R: Read>(
155 child_start: usize,
156 rac: &mut Rac<R>,
157 context: &mut [ChanceTable; 3],
158 update_table: &'a UpdateTable,
159 prange: &[ColorRange],
160 ) -> Result<ManiacNode<'a>> {
161 let chance_table = ChanceTable::new(update_table);
162 let mut property = rac.read_near_zero(0, prange.len() as isize, &mut context[0])?;
163
164 if property == 0 {
165 return Ok(ManiacNode::Leaf(chance_table));
166 }
167 property -= 1;
168
169 if prange[property as usize].min >= prange[property as usize].max {
170 Err(Error::InvalidOperation(format!("Invalid maniac tree")))?
171 }
172
173 let counter = rac.read_near_zero(1 as i32, 512 as i32, &mut context[1])?;
174 let test_value = rac.read_near_zero(
175 prange[property as usize].min,
176 prange[property as usize].max - 1,
177 &mut context[2],
178 )?;
179
180 Ok(ManiacNode::Property {
181 id: property,
182 table: chance_table,
183 value: test_value,
184 counter: counter as u32,
185 left: child_start,
186 right: child_start + 1,
187 })
188 }
189
190 fn create_inner_node<R: Read>(
191 child_start: usize,
192 rac: &mut Rac<R>,
193 context: &mut [ChanceTable; 3],
194 prange: &[ColorRange],
195 ) -> Result<ManiacNode<'a>> {
196 let mut property = rac.read_near_zero(0, prange.len() as isize, &mut context[0])?;
197
198 if property == 0 {
199 return Ok(ManiacNode::InactiveLeaf);
200 }
201 property -= 1;
202
203 if prange[property as usize].min >= prange[property as usize].max {
204 Err(Error::InvalidOperation(format!("Invalid maniac tree")))?
205 }
206
207 let counter = rac.read_near_zero(1 as i32, 512 as i32, &mut context[1])?;
208 let test_value = rac.read_near_zero(
209 prange[property as usize].min,
210 prange[property as usize].max - 1,
211 &mut context[2],
212 )?;
213
214 Ok(ManiacNode::InactiveProperty {
215 id: property,
216 value: test_value,
217 counter: counter as u32,
218 left: child_start,
219 right: child_start + 1,
220 })
221 }
222
223 pub fn apply<R: Read>(
224 &mut self,
225 rac: &mut Rac<R>,
226 pvec: &[ColorValue],
227 min: ColorValue,
228 max: ColorValue,
229 ) -> Result<ColorValue> {
230 use self::ManiacNode::*;
231 let mut node_index = 0;
232 loop {
233 let (lnodes, rnodes) = &mut self.nodes.split_at_mut(node_index + 1);
234 let node = &mut lnodes[node_index];
235 match node {
236 Inner {
237 id,
238 value,
239 left,
240 right,
241 } => {
242 if pvec[*id as usize] > *value {
243 node_index = *left;
244 } else {
245 node_index = *right;
246 }
247 }
248 Leaf(table) => {
249 return rac.read_near_zero(min, max, table);
250 }
251 node => {
252 let (val, new_node) = match node {
253 Property {
254 id,
255 value,
256 counter: 0,
257 table,
258 left,
259 right,
260 } => {
261 let mut left_table = table.clone();
262 let mut right_table = table.clone();
263
264 let val = if pvec[*id as usize] > *value {
265 rac.read_near_zero(min, max, &mut left_table)?
266 } else {
267 rac.read_near_zero(min, max, &mut right_table)?
268 };
269
270 rnodes[*left - node_index - 1].activate(left_table);
271 rnodes[*right - node_index - 1].activate(right_table);
272 (
273 val,
274 Inner {
275 id: *id,
276 value: *value,
277 left: *left,
278 right: *right,
279 },
280 )
281 }
282 Property { counter, table, .. } => {
283 *counter -= 1;
284 return rac.read_near_zero(min, max, table);
285 }
286 _ => panic!(
287 "improperly constructed tree, \
288 inactive node reached during traversal"
289 ),
290 };
291 *node = new_node;
292 return Ok(val);
293 }
294 }
295 }
296 }
297
298 fn build_prange_vec(channel: RgbaChannels, info: &FlifInfo) -> Vec<ColorRange> {
299 let mut prange = Vec::new();
300
301 let transform = &info.transform;
302
303 if channel == RgbaChannels::Green || channel == RgbaChannels::Blue {
304 prange.push(transform.range(RgbaChannels::Red));
305 }
306
307 if channel == RgbaChannels::Blue {
308 prange.push(transform.range(RgbaChannels::Green));
309 }
310
311 if channel != RgbaChannels::Alpha && info.header.channels == ColorSpace::RGBA {
312 prange.push(transform.range(RgbaChannels::Alpha));
313 }
314
315 prange.push(transform.range(channel));
316 prange.push(ColorRange { min: 0, max: 2 });
317
318 let maxdiff = ColorRange {
319 min: transform.range(channel).min - transform.range(channel).max,
320 max: transform.range(channel).max - transform.range(channel).min,
321 };
322 prange.push(maxdiff);
323 prange.push(maxdiff);
324 prange.push(maxdiff);
325 prange.push(maxdiff);
326 prange.push(maxdiff);
327
328 prange
329 }
330}
331
332#[derive(Clone)]
333enum ManiacNode<'a> {
334 Property {
336 id: isize,
337 value: i16,
338 table: ChanceTable<'a>,
339 counter: u32,
340 left: usize,
341 right: usize,
342 },
343 InactiveProperty {
344 id: isize,
345 value: i16,
346 counter: u32,
347 left: usize,
348 right: usize,
349 },
350 Inner {
352 id: isize,
353 value: i16,
354 left: usize,
355 right: usize,
356 },
357 Leaf(ChanceTable<'a>),
359 InactiveLeaf,
360}
361
362impl<'a> ManiacNode<'a> {
363 pub fn activate(&mut self, table: ChanceTable<'a>) {
365 use self::ManiacNode::*;
366 *self = match self {
367 InactiveLeaf => Leaf(table),
368 InactiveProperty {
369 id,
370 value,
371 counter,
372 left,
373 right,
374 } => Property {
375 id: *id,
376 value: *value,
377 counter: *counter,
378 table: table,
379 left: *left,
380 right: *right,
381 },
382 _ => return,
383 }
384 }
385}