Coverage Report

Created: 2025-12-11 07:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/zune-jpeg-0.5.6/src/upsampler/scalar.rs
Line
Count
Source
1
/*
2
 * Copyright (c) 2023.
3
 *
4
 * This software is free software;
5
 *
6
 * You can redistribute it or modify it under terms of the MIT, Apache License or Zlib license
7
 */
8
9
3.32M
pub fn upsample_horizontal(
10
3.32M
    input: &[i16], _ref: &[i16], _in_near: &[i16], _scratch: &mut [i16], output: &mut [i16]
11
3.32M
) {
12
3.32M
    assert_eq!(
13
3.32M
        input.len() * 2,
14
3.32M
        output.len(),
15
0
        "Input length is not half the size of the output length"
16
    );
17
3.32M
    assert!(
18
3.32M
        output.len() > 4 && input.len() > 2,
19
0
        "Too Short of a vector, cannot upsample"
20
    );
21
22
3.32M
    output[0] = input[0];
23
3.32M
    output[1] = (input[0] * 3 + input[1] + 2) >> 2;
24
25
    // This code is written for speed and not readability
26
    //
27
    // The readable code is
28
    //
29
    //      for i in 1..input.len() - 1{
30
    //         let sample = 3 * input[i] + 2;
31
    //         out[i * 2] = (sample + input[i - 1]) >> 2;
32
    //         out[i * 2 + 1] = (sample + input[i + 1]) >> 2;
33
    //     }
34
    //
35
    // The output of a pixel is determined by it's surrounding neighbours but we attach more weight to it's nearest
36
    // neighbour (input[i]) than to the next nearest neighbour.
37
38
4.39G
    for (output_window, input_window) in output[2..].chunks_exact_mut(2).zip(input.windows(3)) {
39
4.39G
        let sample = 3 * input_window[1] + 2;
40
4.39G
41
4.39G
        output_window[0] = (sample + input_window[0]) >> 2;
42
4.39G
        output_window[1] = (sample + input_window[2]) >> 2;
43
4.39G
    }
44
    // Get lengths
45
3.32M
    let out_len = output.len() - 2;
46
3.32M
    let input_len = input.len() - 2;
47
48
    // slice the output vector
49
3.32M
    let f_out = &mut output[out_len..];
50
3.32M
    let i_last = &input[input_len..];
51
52
    // write out manually..
53
3.32M
    f_out[0] = (3 * i_last[1] + i_last[0] + 2) >> 2;
54
3.32M
    f_out[1] = i_last[1];
55
3.32M
}
56
2.06M
pub fn upsample_vertical(
57
2.06M
    input: &[i16], in_near: &[i16], in_far: &[i16], _scratch_space: &mut [i16], output: &mut [i16]
58
2.06M
) {
59
2.06M
    assert_eq!(input.len() * 2, output.len());
60
2.06M
    assert_eq!(in_near.len(), input.len());
61
2.06M
    assert_eq!(in_far.len(), input.len());
62
63
2.06M
    let middle = output.len() / 2;
64
65
2.06M
    let (out_top, out_bottom) = output.split_at_mut(middle);
66
67
    // for the first row, closest row is in_near
68
4.34G
    for ((near, far), x) in input.iter().zip(in_near.iter()).zip(out_top) {
69
4.34G
        *x = (((3 * near) + 2) + far) >> 2;
70
4.34G
    }
71
    // for the second row, the closest row to input is in_far
72
4.34G
    for ((near, far), x) in input.iter().zip(in_far.iter()).zip(out_bottom) {
73
4.34G
        *x = (((3 * near) + 2) + far) >> 2;
74
4.34G
    }
75
2.06M
}
76
77
1.04M
pub fn upsample_hv(
78
1.04M
    input: &[i16], in_near: &[i16], in_far: &[i16], scratch_space: &mut [i16], output: &mut [i16]
79
1.04M
) {
80
81
1.04M
    assert_eq!(input.len() * 4, output.len());
82
1.04M
    assert_eq!(input.len() * 2, scratch_space.len());
83
84
1.04M
    let mut t = [0];
85
1.04M
    upsample_vertical(input, in_near, in_far, &mut t, scratch_space);
86
    // horizontal upsampling must be done separate for every line
87
    // Otherwise it introduces artifacts that may cause the edge colors
88
    // to appear on the other line.
89
90
    // Since this is called for two scanlines/widths currently
91
    // splitting the inputs and outputs into half ensures we only handle
92
    // one scanline per iteration
93
1.04M
    let scratch_half = scratch_space.len() / 2;
94
95
1.04M
    let output_half = output.len() / 2;
96
97
1.04M
    upsample_horizontal(
98
1.04M
        &scratch_space[..scratch_half],
99
1.04M
        &[],
100
1.04M
        &[],
101
1.04M
        &mut t,
102
1.04M
        &mut output[..output_half]
103
    );
104
105
1.04M
    upsample_horizontal(
106
1.04M
        &scratch_space[scratch_half..],
107
1.04M
        &[],
108
1.04M
        &[],
109
1.04M
        &mut t,
110
1.04M
        &mut output[output_half..]
111
    );
112
1.04M
}
113
114
57.2k
pub fn upsample_generic(
115
57.2k
    input: &[i16], _in_near: &[i16], _in_far: &[i16], _scratch_space: &mut [i16],
116
57.2k
    output: &mut [i16]
117
57.2k
) {
118
    // use nearest sample
119
57.2k
    let difference = output.len() / input.len();
120
57.2k
    if difference > 0 {
121
        // nearest neighbour
122
218M
        for (input, chunk_output) in input.iter().zip(output.chunks_exact_mut(difference)) {
123
219M
            chunk_output.iter_mut().for_each(|x| *x = *input);
124
        }
125
0
    }
126
57.2k
}