image/codecs/jpeg/
transform.rs

1/*
2fdct is a Rust translation of jfdctint.c from the
3Independent JPEG Group's libjpeg version 9a
4obtained from http://www.ijg.org/files/jpegsr9a.zip
5It comes with the following conditions of distribution and use:
6
7    In plain English:
8
9    1. We don't promise that this software works.  (But if you find any bugs,
10        please let us know!)
11    2. You can use this software for whatever you want.  You don't have to pay us.
12    3. You may not pretend that you wrote this software.  If you use it in a
13       program, you must acknowledge somewhere in your documentation that
14       you've used the IJG code.
15
16    In legalese:
17
18    The authors make NO WARRANTY or representation, either express or implied,
19    with respect to this software, its quality, accuracy, merchantability, or
20    fitness for a particular purpose.  This software is provided "AS IS", and you,
21    its user, assume the entire risk as to its quality and accuracy.
22
23    This software is copyright (C) 1991-2014, Thomas G. Lane, Guido Vollbeding.
24    All Rights Reserved except as specified below.
25
26    Permission is hereby granted to use, copy, modify, and distribute this
27    software (or portions thereof) for any purpose, without fee, subject to these
28    conditions:
29    (1) If any part of the source code for this software is distributed, then this
30    README file must be included, with this copyright and no-warranty notice
31    unaltered; and any additions, deletions, or changes to the original files
32    must be clearly indicated in accompanying documentation.
33    (2) If only executable code is distributed, then the accompanying
34    documentation must state that "this software is based in part on the work of
35    the Independent JPEG Group".
36    (3) Permission for use of this software is granted only if the user accepts
37    full responsibility for any undesirable consequences; the authors accept
38    NO LIABILITY for damages of any kind.
39
40    These conditions apply to any software derived from or based on the IJG code,
41    not just to the unmodified library.  If you use our work, you ought to
42    acknowledge us.
43
44    Permission is NOT granted for the use of any IJG author's name or company name
45    in advertising or publicity relating to this software or products derived from
46    it.  This software may be referred to only as "the Independent JPEG Group's
47    software".
48
49    We specifically permit and encourage the use of this software as the basis of
50    commercial products, provided that all warranty or liability claims are
51    assumed by the product vendor.
52*/
53
54static CONST_BITS: i32 = 13;
55static PASS1_BITS: i32 = 2;
56
57static FIX_0_298631336: i32 = 2446;
58static FIX_0_390180644: i32 = 3196;
59static FIX_0_541196100: i32 = 4433;
60static FIX_0_765366865: i32 = 6270;
61static FIX_0_899976223: i32 = 7373;
62static FIX_1_175875602: i32 = 9633;
63static FIX_1_501321110: i32 = 12_299;
64static FIX_1_847759065: i32 = 15_137;
65static FIX_1_961570560: i32 = 16_069;
66static FIX_2_053119869: i32 = 16_819;
67static FIX_2_562915447: i32 = 20_995;
68static FIX_3_072711026: i32 = 25_172;
69
70pub(crate) fn fdct(samples: &[u8; 64], coeffs: &mut [i32; 64]) {
71    // Pass 1: process rows.
72    // Results are scaled by sqrt(8) compared to a true DCT
73    // furthermore we scale the results by 2**PASS1_BITS
74    for y in 0usize..8 {
75        let y0 = y * 8;
76
77        // Even part
78        let t0 = i32::from(samples[y0]) + i32::from(samples[y0 + 7]);
79        let t1 = i32::from(samples[y0 + 1]) + i32::from(samples[y0 + 6]);
80        let t2 = i32::from(samples[y0 + 2]) + i32::from(samples[y0 + 5]);
81        let t3 = i32::from(samples[y0 + 3]) + i32::from(samples[y0 + 4]);
82
83        let t10 = t0 + t3;
84        let t12 = t0 - t3;
85        let t11 = t1 + t2;
86        let t13 = t1 - t2;
87
88        let t0 = i32::from(samples[y0]) - i32::from(samples[y0 + 7]);
89        let t1 = i32::from(samples[y0 + 1]) - i32::from(samples[y0 + 6]);
90        let t2 = i32::from(samples[y0 + 2]) - i32::from(samples[y0 + 5]);
91        let t3 = i32::from(samples[y0 + 3]) - i32::from(samples[y0 + 4]);
92
93        // Apply unsigned -> signed conversion
94        coeffs[y0] = (t10 + t11 - 8 * 128) << PASS1_BITS as usize;
95        coeffs[y0 + 4] = (t10 - t11) << PASS1_BITS as usize;
96
97        let mut z1 = (t12 + t13) * FIX_0_541196100;
98        // Add fudge factor here for final descale
99        z1 += 1 << (CONST_BITS - PASS1_BITS - 1) as usize;
100
101        coeffs[y0 + 2] = (z1 + t12 * FIX_0_765366865) >> (CONST_BITS - PASS1_BITS) as usize;
102        coeffs[y0 + 6] = (z1 - t13 * FIX_1_847759065) >> (CONST_BITS - PASS1_BITS) as usize;
103
104        // Odd part
105        let t12 = t0 + t2;
106        let t13 = t1 + t3;
107
108        let mut z1 = (t12 + t13) * FIX_1_175875602;
109        // Add fudge factor here for final descale
110        z1 += 1 << (CONST_BITS - PASS1_BITS - 1) as usize;
111
112        let mut t12 = t12 * (-FIX_0_390180644);
113        let mut t13 = t13 * (-FIX_1_961570560);
114        t12 += z1;
115        t13 += z1;
116
117        let z1 = (t0 + t3) * (-FIX_0_899976223);
118        let mut t0 = t0 * FIX_1_501321110;
119        let mut t3 = t3 * FIX_0_298631336;
120        t0 += z1 + t12;
121        t3 += z1 + t13;
122
123        let z1 = (t1 + t2) * (-FIX_2_562915447);
124        let mut t1 = t1 * FIX_3_072711026;
125        let mut t2 = t2 * FIX_2_053119869;
126        t1 += z1 + t13;
127        t2 += z1 + t12;
128
129        coeffs[y0 + 1] = t0 >> (CONST_BITS - PASS1_BITS) as usize;
130        coeffs[y0 + 3] = t1 >> (CONST_BITS - PASS1_BITS) as usize;
131        coeffs[y0 + 5] = t2 >> (CONST_BITS - PASS1_BITS) as usize;
132        coeffs[y0 + 7] = t3 >> (CONST_BITS - PASS1_BITS) as usize;
133    }
134
135    // Pass 2: process columns
136    // We remove the PASS1_BITS scaling but leave the results scaled up an
137    // overall factor of 8
138    for x in (0usize..8).rev() {
139        // Even part
140        let t0 = coeffs[x] + coeffs[x + 8 * 7];
141        let t1 = coeffs[x + 8] + coeffs[x + 8 * 6];
142        let t2 = coeffs[x + 8 * 2] + coeffs[x + 8 * 5];
143        let t3 = coeffs[x + 8 * 3] + coeffs[x + 8 * 4];
144
145        // Add fudge factor here for final descale
146        let t10 = t0 + t3 + (1 << (PASS1_BITS - 1) as usize);
147        let t12 = t0 - t3;
148        let t11 = t1 + t2;
149        let t13 = t1 - t2;
150
151        let t0 = coeffs[x] - coeffs[x + 8 * 7];
152        let t1 = coeffs[x + 8] - coeffs[x + 8 * 6];
153        let t2 = coeffs[x + 8 * 2] - coeffs[x + 8 * 5];
154        let t3 = coeffs[x + 8 * 3] - coeffs[x + 8 * 4];
155
156        coeffs[x] = (t10 + t11) >> PASS1_BITS as usize;
157        coeffs[x + 8 * 4] = (t10 - t11) >> PASS1_BITS as usize;
158
159        let mut z1 = (t12 + t13) * FIX_0_541196100;
160        // Add fudge factor here for final descale
161        z1 += 1 << (CONST_BITS + PASS1_BITS - 1) as usize;
162
163        coeffs[x + 8 * 2] = (z1 + t12 * FIX_0_765366865) >> (CONST_BITS + PASS1_BITS) as usize;
164        coeffs[x + 8 * 6] = (z1 - t13 * FIX_1_847759065) >> (CONST_BITS + PASS1_BITS) as usize;
165
166        // Odd part
167        let t12 = t0 + t2;
168        let t13 = t1 + t3;
169
170        let mut z1 = (t12 + t13) * FIX_1_175875602;
171        // Add fudge factor here for final descale
172        z1 += 1 << (CONST_BITS - PASS1_BITS - 1) as usize;
173
174        let mut t12 = t12 * (-FIX_0_390180644);
175        let mut t13 = t13 * (-FIX_1_961570560);
176        t12 += z1;
177        t13 += z1;
178
179        let z1 = (t0 + t3) * (-FIX_0_899976223);
180        let mut t0 = t0 * FIX_1_501321110;
181        let mut t3 = t3 * FIX_0_298631336;
182        t0 += z1 + t12;
183        t3 += z1 + t13;
184
185        let z1 = (t1 + t2) * (-FIX_2_562915447);
186        let mut t1 = t1 * FIX_3_072711026;
187        let mut t2 = t2 * FIX_2_053119869;
188        t1 += z1 + t13;
189        t2 += z1 + t12;
190
191        coeffs[x + 8] = t0 >> (CONST_BITS + PASS1_BITS) as usize;
192        coeffs[x + 8 * 3] = t1 >> (CONST_BITS + PASS1_BITS) as usize;
193        coeffs[x + 8 * 5] = t2 >> (CONST_BITS + PASS1_BITS) as usize;
194        coeffs[x + 8 * 7] = t3 >> (CONST_BITS + PASS1_BITS) as usize;
195    }
196}