flif/maniac/
mod.rs

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    /// Denotes a property node, property nodes are nodes that currently act as leaf nodes but will become inner nodes when their counter reaches zero
335    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 nodes are property nodes whose counters have reached zero. They no longer have a context associated with them.
351    Inner {
352        id: isize,
353        value: i16,
354        left: usize,
355        right: usize,
356    },
357    /// Leaf nodes are nodes that can never become inner nodes
358    Leaf(ChanceTable<'a>),
359    InactiveLeaf,
360}
361
362impl<'a> ManiacNode<'a> {
363    // return type is temporary, will be some reasonable pixel value
364    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}