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
use crate::config::Config;
use crate::processing::process_maybe_parallel_for_each;

#[cfg(test)]
mod test;

pub fn quantize(image: &mut [&mut [i16]], mut quality: i32, min_quality: i32, max_quality: i32) {
    let mut skip = 1;
    let hint_do_parallel =
        image.len() * image[0].len() > Config::multithreading_factors().quantization;

    while skip < image.len() && skip < image[0].len() {
        let q = min_quality.max(1).max(quality);

        if q >= max_quality {
            break;
        }

        process_maybe_parallel_for_each(
            image.iter_mut().enumerate().step_by(skip),
            |(y, column)| {
                let x_step = if (y & skip) != 0 { skip } else { 2 * skip };
                for x in column.iter_mut().skip(x_step - skip).step_by(x_step) {
                    *x = (i32::from(*x) * q).wrapping_div(max_quality) as i16;
                }
            },
            hint_do_parallel,
        );

        skip *= 2;
        quality = max_quality.min(2 * quality);
    }
}

pub fn dequantize(image: &mut [&mut [i16]], mut quality: i32, min_quality: i32, max_quality: i32) {
    let mut skip = 1;
    let hint_do_parallel =
        image.len() * image[0].len() > Config::multithreading_factors().quantization;

    while skip < image.len() && skip < image[0].len() {
        let q = min_quality.max(1).max(quality);

        if q >= max_quality {
            break;
        }

        process_maybe_parallel_for_each(
            image.iter_mut().enumerate().step_by(skip),
            |(y, column)| {
                let x_step = if (y & skip) != 0 { skip } else { 2 * skip };
                for x in column.iter_mut().skip(x_step - skip).step_by(x_step) {
                    *x = if *x < 0 {
                        (i32::from(*x) * max_quality - (max_quality / 2)).wrapping_div(q) as i16
                    } else if *x > 0 {
                        (i32::from(*x) * max_quality + (max_quality / 2)).wrapping_div(q) as i16
                    } else {
                        (i32::from(*x) * max_quality).wrapping_div(q) as i16
                    }
                }
            },
            hint_do_parallel,
        );

        skip *= 2;
        quality = max_quality.min(2 * quality);
    }
}