1*dfc6aa5cSAndroid Build Coastguard Worker /*
2*dfc6aa5cSAndroid Build Coastguard Worker * jcdctmgr.c
3*dfc6aa5cSAndroid Build Coastguard Worker *
4*dfc6aa5cSAndroid Build Coastguard Worker * This file was part of the Independent JPEG Group's software:
5*dfc6aa5cSAndroid Build Coastguard Worker * Copyright (C) 1994-1996, Thomas G. Lane.
6*dfc6aa5cSAndroid Build Coastguard Worker * libjpeg-turbo Modifications:
7*dfc6aa5cSAndroid Build Coastguard Worker * Copyright (C) 1999-2006, MIYASAKA Masaru.
8*dfc6aa5cSAndroid Build Coastguard Worker * Copyright 2009 Pierre Ossman <[email protected]> for Cendio AB
9*dfc6aa5cSAndroid Build Coastguard Worker * Copyright (C) 2011, 2014-2015, D. R. Commander.
10*dfc6aa5cSAndroid Build Coastguard Worker * For conditions of distribution and use, see the accompanying README.ijg
11*dfc6aa5cSAndroid Build Coastguard Worker * file.
12*dfc6aa5cSAndroid Build Coastguard Worker *
13*dfc6aa5cSAndroid Build Coastguard Worker * This file contains the forward-DCT management logic.
14*dfc6aa5cSAndroid Build Coastguard Worker * This code selects a particular DCT implementation to be used,
15*dfc6aa5cSAndroid Build Coastguard Worker * and it performs related housekeeping chores including coefficient
16*dfc6aa5cSAndroid Build Coastguard Worker * quantization.
17*dfc6aa5cSAndroid Build Coastguard Worker */
18*dfc6aa5cSAndroid Build Coastguard Worker
19*dfc6aa5cSAndroid Build Coastguard Worker #define JPEG_INTERNALS
20*dfc6aa5cSAndroid Build Coastguard Worker #include "jinclude.h"
21*dfc6aa5cSAndroid Build Coastguard Worker #include "jpeglib.h"
22*dfc6aa5cSAndroid Build Coastguard Worker #include "jdct.h" /* Private declarations for DCT subsystem */
23*dfc6aa5cSAndroid Build Coastguard Worker #include "jsimddct.h"
24*dfc6aa5cSAndroid Build Coastguard Worker
25*dfc6aa5cSAndroid Build Coastguard Worker
26*dfc6aa5cSAndroid Build Coastguard Worker /* Private subobject for this module */
27*dfc6aa5cSAndroid Build Coastguard Worker
28*dfc6aa5cSAndroid Build Coastguard Worker typedef void (*forward_DCT_method_ptr) (DCTELEM *data);
29*dfc6aa5cSAndroid Build Coastguard Worker typedef void (*float_DCT_method_ptr) (FAST_FLOAT *data);
30*dfc6aa5cSAndroid Build Coastguard Worker
31*dfc6aa5cSAndroid Build Coastguard Worker typedef void (*convsamp_method_ptr) (JSAMPARRAY sample_data,
32*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION start_col,
33*dfc6aa5cSAndroid Build Coastguard Worker DCTELEM *workspace);
34*dfc6aa5cSAndroid Build Coastguard Worker typedef void (*float_convsamp_method_ptr) (JSAMPARRAY sample_data,
35*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION start_col,
36*dfc6aa5cSAndroid Build Coastguard Worker FAST_FLOAT *workspace);
37*dfc6aa5cSAndroid Build Coastguard Worker
38*dfc6aa5cSAndroid Build Coastguard Worker typedef void (*quantize_method_ptr) (JCOEFPTR coef_block, DCTELEM *divisors,
39*dfc6aa5cSAndroid Build Coastguard Worker DCTELEM *workspace);
40*dfc6aa5cSAndroid Build Coastguard Worker typedef void (*float_quantize_method_ptr) (JCOEFPTR coef_block,
41*dfc6aa5cSAndroid Build Coastguard Worker FAST_FLOAT *divisors,
42*dfc6aa5cSAndroid Build Coastguard Worker FAST_FLOAT *workspace);
43*dfc6aa5cSAndroid Build Coastguard Worker
44*dfc6aa5cSAndroid Build Coastguard Worker METHODDEF(void) quantize(JCOEFPTR, DCTELEM *, DCTELEM *);
45*dfc6aa5cSAndroid Build Coastguard Worker
46*dfc6aa5cSAndroid Build Coastguard Worker typedef struct {
47*dfc6aa5cSAndroid Build Coastguard Worker struct jpeg_forward_dct pub; /* public fields */
48*dfc6aa5cSAndroid Build Coastguard Worker
49*dfc6aa5cSAndroid Build Coastguard Worker /* Pointer to the DCT routine actually in use */
50*dfc6aa5cSAndroid Build Coastguard Worker forward_DCT_method_ptr dct;
51*dfc6aa5cSAndroid Build Coastguard Worker convsamp_method_ptr convsamp;
52*dfc6aa5cSAndroid Build Coastguard Worker quantize_method_ptr quantize;
53*dfc6aa5cSAndroid Build Coastguard Worker
54*dfc6aa5cSAndroid Build Coastguard Worker /* The actual post-DCT divisors --- not identical to the quant table
55*dfc6aa5cSAndroid Build Coastguard Worker * entries, because of scaling (especially for an unnormalized DCT).
56*dfc6aa5cSAndroid Build Coastguard Worker * Each table is given in normal array order.
57*dfc6aa5cSAndroid Build Coastguard Worker */
58*dfc6aa5cSAndroid Build Coastguard Worker DCTELEM *divisors[NUM_QUANT_TBLS];
59*dfc6aa5cSAndroid Build Coastguard Worker
60*dfc6aa5cSAndroid Build Coastguard Worker /* work area for FDCT subroutine */
61*dfc6aa5cSAndroid Build Coastguard Worker DCTELEM *workspace;
62*dfc6aa5cSAndroid Build Coastguard Worker
63*dfc6aa5cSAndroid Build Coastguard Worker #ifdef DCT_FLOAT_SUPPORTED
64*dfc6aa5cSAndroid Build Coastguard Worker /* Same as above for the floating-point case. */
65*dfc6aa5cSAndroid Build Coastguard Worker float_DCT_method_ptr float_dct;
66*dfc6aa5cSAndroid Build Coastguard Worker float_convsamp_method_ptr float_convsamp;
67*dfc6aa5cSAndroid Build Coastguard Worker float_quantize_method_ptr float_quantize;
68*dfc6aa5cSAndroid Build Coastguard Worker FAST_FLOAT *float_divisors[NUM_QUANT_TBLS];
69*dfc6aa5cSAndroid Build Coastguard Worker FAST_FLOAT *float_workspace;
70*dfc6aa5cSAndroid Build Coastguard Worker #endif
71*dfc6aa5cSAndroid Build Coastguard Worker } my_fdct_controller;
72*dfc6aa5cSAndroid Build Coastguard Worker
73*dfc6aa5cSAndroid Build Coastguard Worker typedef my_fdct_controller *my_fdct_ptr;
74*dfc6aa5cSAndroid Build Coastguard Worker
75*dfc6aa5cSAndroid Build Coastguard Worker
76*dfc6aa5cSAndroid Build Coastguard Worker #if BITS_IN_JSAMPLE == 8
77*dfc6aa5cSAndroid Build Coastguard Worker
78*dfc6aa5cSAndroid Build Coastguard Worker /*
79*dfc6aa5cSAndroid Build Coastguard Worker * Find the highest bit in an integer through binary search.
80*dfc6aa5cSAndroid Build Coastguard Worker */
81*dfc6aa5cSAndroid Build Coastguard Worker
82*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(int)
flss(UINT16 val)83*dfc6aa5cSAndroid Build Coastguard Worker flss(UINT16 val)
84*dfc6aa5cSAndroid Build Coastguard Worker {
85*dfc6aa5cSAndroid Build Coastguard Worker int bit;
86*dfc6aa5cSAndroid Build Coastguard Worker
87*dfc6aa5cSAndroid Build Coastguard Worker bit = 16;
88*dfc6aa5cSAndroid Build Coastguard Worker
89*dfc6aa5cSAndroid Build Coastguard Worker if (!val)
90*dfc6aa5cSAndroid Build Coastguard Worker return 0;
91*dfc6aa5cSAndroid Build Coastguard Worker
92*dfc6aa5cSAndroid Build Coastguard Worker if (!(val & 0xff00)) {
93*dfc6aa5cSAndroid Build Coastguard Worker bit -= 8;
94*dfc6aa5cSAndroid Build Coastguard Worker val <<= 8;
95*dfc6aa5cSAndroid Build Coastguard Worker }
96*dfc6aa5cSAndroid Build Coastguard Worker if (!(val & 0xf000)) {
97*dfc6aa5cSAndroid Build Coastguard Worker bit -= 4;
98*dfc6aa5cSAndroid Build Coastguard Worker val <<= 4;
99*dfc6aa5cSAndroid Build Coastguard Worker }
100*dfc6aa5cSAndroid Build Coastguard Worker if (!(val & 0xc000)) {
101*dfc6aa5cSAndroid Build Coastguard Worker bit -= 2;
102*dfc6aa5cSAndroid Build Coastguard Worker val <<= 2;
103*dfc6aa5cSAndroid Build Coastguard Worker }
104*dfc6aa5cSAndroid Build Coastguard Worker if (!(val & 0x8000)) {
105*dfc6aa5cSAndroid Build Coastguard Worker bit -= 1;
106*dfc6aa5cSAndroid Build Coastguard Worker val <<= 1;
107*dfc6aa5cSAndroid Build Coastguard Worker }
108*dfc6aa5cSAndroid Build Coastguard Worker
109*dfc6aa5cSAndroid Build Coastguard Worker return bit;
110*dfc6aa5cSAndroid Build Coastguard Worker }
111*dfc6aa5cSAndroid Build Coastguard Worker
112*dfc6aa5cSAndroid Build Coastguard Worker
113*dfc6aa5cSAndroid Build Coastguard Worker /*
114*dfc6aa5cSAndroid Build Coastguard Worker * Compute values to do a division using reciprocal.
115*dfc6aa5cSAndroid Build Coastguard Worker *
116*dfc6aa5cSAndroid Build Coastguard Worker * This implementation is based on an algorithm described in
117*dfc6aa5cSAndroid Build Coastguard Worker * "How to optimize for the Pentium family of microprocessors"
118*dfc6aa5cSAndroid Build Coastguard Worker * (http://www.agner.org/assem/).
119*dfc6aa5cSAndroid Build Coastguard Worker * More information about the basic algorithm can be found in
120*dfc6aa5cSAndroid Build Coastguard Worker * the paper "Integer Division Using Reciprocals" by Robert Alverson.
121*dfc6aa5cSAndroid Build Coastguard Worker *
122*dfc6aa5cSAndroid Build Coastguard Worker * The basic idea is to replace x/d by x * d^-1. In order to store
123*dfc6aa5cSAndroid Build Coastguard Worker * d^-1 with enough precision we shift it left a few places. It turns
124*dfc6aa5cSAndroid Build Coastguard Worker * out that this algoright gives just enough precision, and also fits
125*dfc6aa5cSAndroid Build Coastguard Worker * into DCTELEM:
126*dfc6aa5cSAndroid Build Coastguard Worker *
127*dfc6aa5cSAndroid Build Coastguard Worker * b = (the number of significant bits in divisor) - 1
128*dfc6aa5cSAndroid Build Coastguard Worker * r = (word size) + b
129*dfc6aa5cSAndroid Build Coastguard Worker * f = 2^r / divisor
130*dfc6aa5cSAndroid Build Coastguard Worker *
131*dfc6aa5cSAndroid Build Coastguard Worker * f will not be an integer for most cases, so we need to compensate
132*dfc6aa5cSAndroid Build Coastguard Worker * for the rounding error introduced:
133*dfc6aa5cSAndroid Build Coastguard Worker *
134*dfc6aa5cSAndroid Build Coastguard Worker * no fractional part:
135*dfc6aa5cSAndroid Build Coastguard Worker *
136*dfc6aa5cSAndroid Build Coastguard Worker * result = input >> r
137*dfc6aa5cSAndroid Build Coastguard Worker *
138*dfc6aa5cSAndroid Build Coastguard Worker * fractional part of f < 0.5:
139*dfc6aa5cSAndroid Build Coastguard Worker *
140*dfc6aa5cSAndroid Build Coastguard Worker * round f down to nearest integer
141*dfc6aa5cSAndroid Build Coastguard Worker * result = ((input + 1) * f) >> r
142*dfc6aa5cSAndroid Build Coastguard Worker *
143*dfc6aa5cSAndroid Build Coastguard Worker * fractional part of f > 0.5:
144*dfc6aa5cSAndroid Build Coastguard Worker *
145*dfc6aa5cSAndroid Build Coastguard Worker * round f up to nearest integer
146*dfc6aa5cSAndroid Build Coastguard Worker * result = (input * f) >> r
147*dfc6aa5cSAndroid Build Coastguard Worker *
148*dfc6aa5cSAndroid Build Coastguard Worker * This is the original algorithm that gives truncated results. But we
149*dfc6aa5cSAndroid Build Coastguard Worker * want properly rounded results, so we replace "input" with
150*dfc6aa5cSAndroid Build Coastguard Worker * "input + divisor/2".
151*dfc6aa5cSAndroid Build Coastguard Worker *
152*dfc6aa5cSAndroid Build Coastguard Worker * In order to allow SIMD implementations we also tweak the values to
153*dfc6aa5cSAndroid Build Coastguard Worker * allow the same calculation to be made at all times:
154*dfc6aa5cSAndroid Build Coastguard Worker *
155*dfc6aa5cSAndroid Build Coastguard Worker * dctbl[0] = f rounded to nearest integer
156*dfc6aa5cSAndroid Build Coastguard Worker * dctbl[1] = divisor / 2 (+ 1 if fractional part of f < 0.5)
157*dfc6aa5cSAndroid Build Coastguard Worker * dctbl[2] = 1 << ((word size) * 2 - r)
158*dfc6aa5cSAndroid Build Coastguard Worker * dctbl[3] = r - (word size)
159*dfc6aa5cSAndroid Build Coastguard Worker *
160*dfc6aa5cSAndroid Build Coastguard Worker * dctbl[2] is for stupid instruction sets where the shift operation
161*dfc6aa5cSAndroid Build Coastguard Worker * isn't member wise (e.g. MMX).
162*dfc6aa5cSAndroid Build Coastguard Worker *
163*dfc6aa5cSAndroid Build Coastguard Worker * The reason dctbl[2] and dctbl[3] reduce the shift with (word size)
164*dfc6aa5cSAndroid Build Coastguard Worker * is that most SIMD implementations have a "multiply and store top
165*dfc6aa5cSAndroid Build Coastguard Worker * half" operation.
166*dfc6aa5cSAndroid Build Coastguard Worker *
167*dfc6aa5cSAndroid Build Coastguard Worker * Lastly, we store each of the values in their own table instead
168*dfc6aa5cSAndroid Build Coastguard Worker * of in a consecutive manner, yet again in order to allow SIMD
169*dfc6aa5cSAndroid Build Coastguard Worker * routines.
170*dfc6aa5cSAndroid Build Coastguard Worker */
171*dfc6aa5cSAndroid Build Coastguard Worker
172*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(int)
compute_reciprocal(UINT16 divisor,DCTELEM * dtbl)173*dfc6aa5cSAndroid Build Coastguard Worker compute_reciprocal(UINT16 divisor, DCTELEM *dtbl)
174*dfc6aa5cSAndroid Build Coastguard Worker {
175*dfc6aa5cSAndroid Build Coastguard Worker UDCTELEM2 fq, fr;
176*dfc6aa5cSAndroid Build Coastguard Worker UDCTELEM c;
177*dfc6aa5cSAndroid Build Coastguard Worker int b, r;
178*dfc6aa5cSAndroid Build Coastguard Worker
179*dfc6aa5cSAndroid Build Coastguard Worker if (divisor == 1) {
180*dfc6aa5cSAndroid Build Coastguard Worker /* divisor == 1 means unquantized, so these reciprocal/correction/shift
181*dfc6aa5cSAndroid Build Coastguard Worker * values will cause the C quantization algorithm to act like the
182*dfc6aa5cSAndroid Build Coastguard Worker * identity function. Since only the C quantization algorithm is used in
183*dfc6aa5cSAndroid Build Coastguard Worker * these cases, the scale value is irrelevant.
184*dfc6aa5cSAndroid Build Coastguard Worker */
185*dfc6aa5cSAndroid Build Coastguard Worker dtbl[DCTSIZE2 * 0] = (DCTELEM)1; /* reciprocal */
186*dfc6aa5cSAndroid Build Coastguard Worker dtbl[DCTSIZE2 * 1] = (DCTELEM)0; /* correction */
187*dfc6aa5cSAndroid Build Coastguard Worker dtbl[DCTSIZE2 * 2] = (DCTELEM)1; /* scale */
188*dfc6aa5cSAndroid Build Coastguard Worker dtbl[DCTSIZE2 * 3] = -(DCTELEM)(sizeof(DCTELEM) * 8); /* shift */
189*dfc6aa5cSAndroid Build Coastguard Worker return 0;
190*dfc6aa5cSAndroid Build Coastguard Worker }
191*dfc6aa5cSAndroid Build Coastguard Worker
192*dfc6aa5cSAndroid Build Coastguard Worker b = flss(divisor) - 1;
193*dfc6aa5cSAndroid Build Coastguard Worker r = sizeof(DCTELEM) * 8 + b;
194*dfc6aa5cSAndroid Build Coastguard Worker
195*dfc6aa5cSAndroid Build Coastguard Worker fq = ((UDCTELEM2)1 << r) / divisor;
196*dfc6aa5cSAndroid Build Coastguard Worker fr = ((UDCTELEM2)1 << r) % divisor;
197*dfc6aa5cSAndroid Build Coastguard Worker
198*dfc6aa5cSAndroid Build Coastguard Worker c = divisor / 2; /* for rounding */
199*dfc6aa5cSAndroid Build Coastguard Worker
200*dfc6aa5cSAndroid Build Coastguard Worker if (fr == 0) { /* divisor is power of two */
201*dfc6aa5cSAndroid Build Coastguard Worker /* fq will be one bit too large to fit in DCTELEM, so adjust */
202*dfc6aa5cSAndroid Build Coastguard Worker fq >>= 1;
203*dfc6aa5cSAndroid Build Coastguard Worker r--;
204*dfc6aa5cSAndroid Build Coastguard Worker } else if (fr <= (divisor / 2U)) { /* fractional part is < 0.5 */
205*dfc6aa5cSAndroid Build Coastguard Worker c++;
206*dfc6aa5cSAndroid Build Coastguard Worker } else { /* fractional part is > 0.5 */
207*dfc6aa5cSAndroid Build Coastguard Worker fq++;
208*dfc6aa5cSAndroid Build Coastguard Worker }
209*dfc6aa5cSAndroid Build Coastguard Worker
210*dfc6aa5cSAndroid Build Coastguard Worker dtbl[DCTSIZE2 * 0] = (DCTELEM)fq; /* reciprocal */
211*dfc6aa5cSAndroid Build Coastguard Worker dtbl[DCTSIZE2 * 1] = (DCTELEM)c; /* correction + roundfactor */
212*dfc6aa5cSAndroid Build Coastguard Worker #ifdef WITH_SIMD
213*dfc6aa5cSAndroid Build Coastguard Worker dtbl[DCTSIZE2 * 2] = (DCTELEM)(1 << (sizeof(DCTELEM) * 8 * 2 - r)); /* scale */
214*dfc6aa5cSAndroid Build Coastguard Worker #else
215*dfc6aa5cSAndroid Build Coastguard Worker dtbl[DCTSIZE2 * 2] = 1;
216*dfc6aa5cSAndroid Build Coastguard Worker #endif
217*dfc6aa5cSAndroid Build Coastguard Worker dtbl[DCTSIZE2 * 3] = (DCTELEM)r - sizeof(DCTELEM) * 8; /* shift */
218*dfc6aa5cSAndroid Build Coastguard Worker
219*dfc6aa5cSAndroid Build Coastguard Worker if (r <= 16) return 0;
220*dfc6aa5cSAndroid Build Coastguard Worker else return 1;
221*dfc6aa5cSAndroid Build Coastguard Worker }
222*dfc6aa5cSAndroid Build Coastguard Worker
223*dfc6aa5cSAndroid Build Coastguard Worker #endif
224*dfc6aa5cSAndroid Build Coastguard Worker
225*dfc6aa5cSAndroid Build Coastguard Worker
226*dfc6aa5cSAndroid Build Coastguard Worker /*
227*dfc6aa5cSAndroid Build Coastguard Worker * Initialize for a processing pass.
228*dfc6aa5cSAndroid Build Coastguard Worker * Verify that all referenced Q-tables are present, and set up
229*dfc6aa5cSAndroid Build Coastguard Worker * the divisor table for each one.
230*dfc6aa5cSAndroid Build Coastguard Worker * In the current implementation, DCT of all components is done during
231*dfc6aa5cSAndroid Build Coastguard Worker * the first pass, even if only some components will be output in the
232*dfc6aa5cSAndroid Build Coastguard Worker * first scan. Hence all components should be examined here.
233*dfc6aa5cSAndroid Build Coastguard Worker */
234*dfc6aa5cSAndroid Build Coastguard Worker
235*dfc6aa5cSAndroid Build Coastguard Worker METHODDEF(void)
start_pass_fdctmgr(j_compress_ptr cinfo)236*dfc6aa5cSAndroid Build Coastguard Worker start_pass_fdctmgr(j_compress_ptr cinfo)
237*dfc6aa5cSAndroid Build Coastguard Worker {
238*dfc6aa5cSAndroid Build Coastguard Worker my_fdct_ptr fdct = (my_fdct_ptr)cinfo->fdct;
239*dfc6aa5cSAndroid Build Coastguard Worker int ci, qtblno, i;
240*dfc6aa5cSAndroid Build Coastguard Worker jpeg_component_info *compptr;
241*dfc6aa5cSAndroid Build Coastguard Worker JQUANT_TBL *qtbl;
242*dfc6aa5cSAndroid Build Coastguard Worker DCTELEM *dtbl;
243*dfc6aa5cSAndroid Build Coastguard Worker
244*dfc6aa5cSAndroid Build Coastguard Worker for (ci = 0, compptr = cinfo->comp_info; ci < cinfo->num_components;
245*dfc6aa5cSAndroid Build Coastguard Worker ci++, compptr++) {
246*dfc6aa5cSAndroid Build Coastguard Worker qtblno = compptr->quant_tbl_no;
247*dfc6aa5cSAndroid Build Coastguard Worker /* Make sure specified quantization table is present */
248*dfc6aa5cSAndroid Build Coastguard Worker if (qtblno < 0 || qtblno >= NUM_QUANT_TBLS ||
249*dfc6aa5cSAndroid Build Coastguard Worker cinfo->quant_tbl_ptrs[qtblno] == NULL)
250*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT1(cinfo, JERR_NO_QUANT_TABLE, qtblno);
251*dfc6aa5cSAndroid Build Coastguard Worker qtbl = cinfo->quant_tbl_ptrs[qtblno];
252*dfc6aa5cSAndroid Build Coastguard Worker /* Compute divisors for this quant table */
253*dfc6aa5cSAndroid Build Coastguard Worker /* We may do this more than once for same table, but it's not a big deal */
254*dfc6aa5cSAndroid Build Coastguard Worker switch (cinfo->dct_method) {
255*dfc6aa5cSAndroid Build Coastguard Worker #ifdef DCT_ISLOW_SUPPORTED
256*dfc6aa5cSAndroid Build Coastguard Worker case JDCT_ISLOW:
257*dfc6aa5cSAndroid Build Coastguard Worker /* For LL&M IDCT method, divisors are equal to raw quantization
258*dfc6aa5cSAndroid Build Coastguard Worker * coefficients multiplied by 8 (to counteract scaling).
259*dfc6aa5cSAndroid Build Coastguard Worker */
260*dfc6aa5cSAndroid Build Coastguard Worker if (fdct->divisors[qtblno] == NULL) {
261*dfc6aa5cSAndroid Build Coastguard Worker fdct->divisors[qtblno] = (DCTELEM *)
262*dfc6aa5cSAndroid Build Coastguard Worker (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
263*dfc6aa5cSAndroid Build Coastguard Worker (DCTSIZE2 * 4) * sizeof(DCTELEM));
264*dfc6aa5cSAndroid Build Coastguard Worker }
265*dfc6aa5cSAndroid Build Coastguard Worker dtbl = fdct->divisors[qtblno];
266*dfc6aa5cSAndroid Build Coastguard Worker for (i = 0; i < DCTSIZE2; i++) {
267*dfc6aa5cSAndroid Build Coastguard Worker #if BITS_IN_JSAMPLE == 8
268*dfc6aa5cSAndroid Build Coastguard Worker if (!compute_reciprocal(qtbl->quantval[i] << 3, &dtbl[i]) &&
269*dfc6aa5cSAndroid Build Coastguard Worker fdct->quantize == jsimd_quantize)
270*dfc6aa5cSAndroid Build Coastguard Worker fdct->quantize = quantize;
271*dfc6aa5cSAndroid Build Coastguard Worker #else
272*dfc6aa5cSAndroid Build Coastguard Worker dtbl[i] = ((DCTELEM)qtbl->quantval[i]) << 3;
273*dfc6aa5cSAndroid Build Coastguard Worker #endif
274*dfc6aa5cSAndroid Build Coastguard Worker }
275*dfc6aa5cSAndroid Build Coastguard Worker break;
276*dfc6aa5cSAndroid Build Coastguard Worker #endif
277*dfc6aa5cSAndroid Build Coastguard Worker #ifdef DCT_IFAST_SUPPORTED
278*dfc6aa5cSAndroid Build Coastguard Worker case JDCT_IFAST:
279*dfc6aa5cSAndroid Build Coastguard Worker {
280*dfc6aa5cSAndroid Build Coastguard Worker /* For AA&N IDCT method, divisors are equal to quantization
281*dfc6aa5cSAndroid Build Coastguard Worker * coefficients scaled by scalefactor[row]*scalefactor[col], where
282*dfc6aa5cSAndroid Build Coastguard Worker * scalefactor[0] = 1
283*dfc6aa5cSAndroid Build Coastguard Worker * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
284*dfc6aa5cSAndroid Build Coastguard Worker * We apply a further scale factor of 8.
285*dfc6aa5cSAndroid Build Coastguard Worker */
286*dfc6aa5cSAndroid Build Coastguard Worker #define CONST_BITS 14
287*dfc6aa5cSAndroid Build Coastguard Worker static const INT16 aanscales[DCTSIZE2] = {
288*dfc6aa5cSAndroid Build Coastguard Worker /* precomputed values scaled up by 14 bits */
289*dfc6aa5cSAndroid Build Coastguard Worker 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
290*dfc6aa5cSAndroid Build Coastguard Worker 22725, 31521, 29692, 26722, 22725, 17855, 12299, 6270,
291*dfc6aa5cSAndroid Build Coastguard Worker 21407, 29692, 27969, 25172, 21407, 16819, 11585, 5906,
292*dfc6aa5cSAndroid Build Coastguard Worker 19266, 26722, 25172, 22654, 19266, 15137, 10426, 5315,
293*dfc6aa5cSAndroid Build Coastguard Worker 16384, 22725, 21407, 19266, 16384, 12873, 8867, 4520,
294*dfc6aa5cSAndroid Build Coastguard Worker 12873, 17855, 16819, 15137, 12873, 10114, 6967, 3552,
295*dfc6aa5cSAndroid Build Coastguard Worker 8867, 12299, 11585, 10426, 8867, 6967, 4799, 2446,
296*dfc6aa5cSAndroid Build Coastguard Worker 4520, 6270, 5906, 5315, 4520, 3552, 2446, 1247
297*dfc6aa5cSAndroid Build Coastguard Worker };
298*dfc6aa5cSAndroid Build Coastguard Worker SHIFT_TEMPS
299*dfc6aa5cSAndroid Build Coastguard Worker
300*dfc6aa5cSAndroid Build Coastguard Worker if (fdct->divisors[qtblno] == NULL) {
301*dfc6aa5cSAndroid Build Coastguard Worker fdct->divisors[qtblno] = (DCTELEM *)
302*dfc6aa5cSAndroid Build Coastguard Worker (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
303*dfc6aa5cSAndroid Build Coastguard Worker (DCTSIZE2 * 4) * sizeof(DCTELEM));
304*dfc6aa5cSAndroid Build Coastguard Worker }
305*dfc6aa5cSAndroid Build Coastguard Worker dtbl = fdct->divisors[qtblno];
306*dfc6aa5cSAndroid Build Coastguard Worker for (i = 0; i < DCTSIZE2; i++) {
307*dfc6aa5cSAndroid Build Coastguard Worker #if BITS_IN_JSAMPLE == 8
308*dfc6aa5cSAndroid Build Coastguard Worker if (!compute_reciprocal(
309*dfc6aa5cSAndroid Build Coastguard Worker DESCALE(MULTIPLY16V16((JLONG)qtbl->quantval[i],
310*dfc6aa5cSAndroid Build Coastguard Worker (JLONG)aanscales[i]),
311*dfc6aa5cSAndroid Build Coastguard Worker CONST_BITS - 3), &dtbl[i]) &&
312*dfc6aa5cSAndroid Build Coastguard Worker fdct->quantize == jsimd_quantize)
313*dfc6aa5cSAndroid Build Coastguard Worker fdct->quantize = quantize;
314*dfc6aa5cSAndroid Build Coastguard Worker #else
315*dfc6aa5cSAndroid Build Coastguard Worker dtbl[i] = (DCTELEM)
316*dfc6aa5cSAndroid Build Coastguard Worker DESCALE(MULTIPLY16V16((JLONG)qtbl->quantval[i],
317*dfc6aa5cSAndroid Build Coastguard Worker (JLONG)aanscales[i]),
318*dfc6aa5cSAndroid Build Coastguard Worker CONST_BITS - 3);
319*dfc6aa5cSAndroid Build Coastguard Worker #endif
320*dfc6aa5cSAndroid Build Coastguard Worker }
321*dfc6aa5cSAndroid Build Coastguard Worker }
322*dfc6aa5cSAndroid Build Coastguard Worker break;
323*dfc6aa5cSAndroid Build Coastguard Worker #endif
324*dfc6aa5cSAndroid Build Coastguard Worker #ifdef DCT_FLOAT_SUPPORTED
325*dfc6aa5cSAndroid Build Coastguard Worker case JDCT_FLOAT:
326*dfc6aa5cSAndroid Build Coastguard Worker {
327*dfc6aa5cSAndroid Build Coastguard Worker /* For float AA&N IDCT method, divisors are equal to quantization
328*dfc6aa5cSAndroid Build Coastguard Worker * coefficients scaled by scalefactor[row]*scalefactor[col], where
329*dfc6aa5cSAndroid Build Coastguard Worker * scalefactor[0] = 1
330*dfc6aa5cSAndroid Build Coastguard Worker * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7
331*dfc6aa5cSAndroid Build Coastguard Worker * We apply a further scale factor of 8.
332*dfc6aa5cSAndroid Build Coastguard Worker * What's actually stored is 1/divisor so that the inner loop can
333*dfc6aa5cSAndroid Build Coastguard Worker * use a multiplication rather than a division.
334*dfc6aa5cSAndroid Build Coastguard Worker */
335*dfc6aa5cSAndroid Build Coastguard Worker FAST_FLOAT *fdtbl;
336*dfc6aa5cSAndroid Build Coastguard Worker int row, col;
337*dfc6aa5cSAndroid Build Coastguard Worker static const double aanscalefactor[DCTSIZE] = {
338*dfc6aa5cSAndroid Build Coastguard Worker 1.0, 1.387039845, 1.306562965, 1.175875602,
339*dfc6aa5cSAndroid Build Coastguard Worker 1.0, 0.785694958, 0.541196100, 0.275899379
340*dfc6aa5cSAndroid Build Coastguard Worker };
341*dfc6aa5cSAndroid Build Coastguard Worker
342*dfc6aa5cSAndroid Build Coastguard Worker if (fdct->float_divisors[qtblno] == NULL) {
343*dfc6aa5cSAndroid Build Coastguard Worker fdct->float_divisors[qtblno] = (FAST_FLOAT *)
344*dfc6aa5cSAndroid Build Coastguard Worker (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
345*dfc6aa5cSAndroid Build Coastguard Worker DCTSIZE2 * sizeof(FAST_FLOAT));
346*dfc6aa5cSAndroid Build Coastguard Worker }
347*dfc6aa5cSAndroid Build Coastguard Worker fdtbl = fdct->float_divisors[qtblno];
348*dfc6aa5cSAndroid Build Coastguard Worker i = 0;
349*dfc6aa5cSAndroid Build Coastguard Worker for (row = 0; row < DCTSIZE; row++) {
350*dfc6aa5cSAndroid Build Coastguard Worker for (col = 0; col < DCTSIZE; col++) {
351*dfc6aa5cSAndroid Build Coastguard Worker fdtbl[i] = (FAST_FLOAT)
352*dfc6aa5cSAndroid Build Coastguard Worker (1.0 / (((double)qtbl->quantval[i] *
353*dfc6aa5cSAndroid Build Coastguard Worker aanscalefactor[row] * aanscalefactor[col] * 8.0)));
354*dfc6aa5cSAndroid Build Coastguard Worker i++;
355*dfc6aa5cSAndroid Build Coastguard Worker }
356*dfc6aa5cSAndroid Build Coastguard Worker }
357*dfc6aa5cSAndroid Build Coastguard Worker }
358*dfc6aa5cSAndroid Build Coastguard Worker break;
359*dfc6aa5cSAndroid Build Coastguard Worker #endif
360*dfc6aa5cSAndroid Build Coastguard Worker default:
361*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT(cinfo, JERR_NOT_COMPILED);
362*dfc6aa5cSAndroid Build Coastguard Worker break;
363*dfc6aa5cSAndroid Build Coastguard Worker }
364*dfc6aa5cSAndroid Build Coastguard Worker }
365*dfc6aa5cSAndroid Build Coastguard Worker }
366*dfc6aa5cSAndroid Build Coastguard Worker
367*dfc6aa5cSAndroid Build Coastguard Worker
368*dfc6aa5cSAndroid Build Coastguard Worker /*
369*dfc6aa5cSAndroid Build Coastguard Worker * Load data into workspace, applying unsigned->signed conversion.
370*dfc6aa5cSAndroid Build Coastguard Worker */
371*dfc6aa5cSAndroid Build Coastguard Worker
372*dfc6aa5cSAndroid Build Coastguard Worker METHODDEF(void)
convsamp(JSAMPARRAY sample_data,JDIMENSION start_col,DCTELEM * workspace)373*dfc6aa5cSAndroid Build Coastguard Worker convsamp(JSAMPARRAY sample_data, JDIMENSION start_col, DCTELEM *workspace)
374*dfc6aa5cSAndroid Build Coastguard Worker {
375*dfc6aa5cSAndroid Build Coastguard Worker register DCTELEM *workspaceptr;
376*dfc6aa5cSAndroid Build Coastguard Worker register JSAMPROW elemptr;
377*dfc6aa5cSAndroid Build Coastguard Worker register int elemr;
378*dfc6aa5cSAndroid Build Coastguard Worker
379*dfc6aa5cSAndroid Build Coastguard Worker workspaceptr = workspace;
380*dfc6aa5cSAndroid Build Coastguard Worker for (elemr = 0; elemr < DCTSIZE; elemr++) {
381*dfc6aa5cSAndroid Build Coastguard Worker elemptr = sample_data[elemr] + start_col;
382*dfc6aa5cSAndroid Build Coastguard Worker
383*dfc6aa5cSAndroid Build Coastguard Worker #if DCTSIZE == 8 /* unroll the inner loop */
384*dfc6aa5cSAndroid Build Coastguard Worker *workspaceptr++ = (*elemptr++) - CENTERJSAMPLE;
385*dfc6aa5cSAndroid Build Coastguard Worker *workspaceptr++ = (*elemptr++) - CENTERJSAMPLE;
386*dfc6aa5cSAndroid Build Coastguard Worker *workspaceptr++ = (*elemptr++) - CENTERJSAMPLE;
387*dfc6aa5cSAndroid Build Coastguard Worker *workspaceptr++ = (*elemptr++) - CENTERJSAMPLE;
388*dfc6aa5cSAndroid Build Coastguard Worker *workspaceptr++ = (*elemptr++) - CENTERJSAMPLE;
389*dfc6aa5cSAndroid Build Coastguard Worker *workspaceptr++ = (*elemptr++) - CENTERJSAMPLE;
390*dfc6aa5cSAndroid Build Coastguard Worker *workspaceptr++ = (*elemptr++) - CENTERJSAMPLE;
391*dfc6aa5cSAndroid Build Coastguard Worker *workspaceptr++ = (*elemptr++) - CENTERJSAMPLE;
392*dfc6aa5cSAndroid Build Coastguard Worker #else
393*dfc6aa5cSAndroid Build Coastguard Worker {
394*dfc6aa5cSAndroid Build Coastguard Worker register int elemc;
395*dfc6aa5cSAndroid Build Coastguard Worker for (elemc = DCTSIZE; elemc > 0; elemc--)
396*dfc6aa5cSAndroid Build Coastguard Worker *workspaceptr++ = (*elemptr++) - CENTERJSAMPLE;
397*dfc6aa5cSAndroid Build Coastguard Worker }
398*dfc6aa5cSAndroid Build Coastguard Worker #endif
399*dfc6aa5cSAndroid Build Coastguard Worker }
400*dfc6aa5cSAndroid Build Coastguard Worker }
401*dfc6aa5cSAndroid Build Coastguard Worker
402*dfc6aa5cSAndroid Build Coastguard Worker
403*dfc6aa5cSAndroid Build Coastguard Worker /*
404*dfc6aa5cSAndroid Build Coastguard Worker * Quantize/descale the coefficients, and store into coef_blocks[].
405*dfc6aa5cSAndroid Build Coastguard Worker */
406*dfc6aa5cSAndroid Build Coastguard Worker
407*dfc6aa5cSAndroid Build Coastguard Worker METHODDEF(void)
quantize(JCOEFPTR coef_block,DCTELEM * divisors,DCTELEM * workspace)408*dfc6aa5cSAndroid Build Coastguard Worker quantize(JCOEFPTR coef_block, DCTELEM *divisors, DCTELEM *workspace)
409*dfc6aa5cSAndroid Build Coastguard Worker {
410*dfc6aa5cSAndroid Build Coastguard Worker int i;
411*dfc6aa5cSAndroid Build Coastguard Worker DCTELEM temp;
412*dfc6aa5cSAndroid Build Coastguard Worker JCOEFPTR output_ptr = coef_block;
413*dfc6aa5cSAndroid Build Coastguard Worker
414*dfc6aa5cSAndroid Build Coastguard Worker #if BITS_IN_JSAMPLE == 8
415*dfc6aa5cSAndroid Build Coastguard Worker
416*dfc6aa5cSAndroid Build Coastguard Worker UDCTELEM recip, corr;
417*dfc6aa5cSAndroid Build Coastguard Worker int shift;
418*dfc6aa5cSAndroid Build Coastguard Worker UDCTELEM2 product;
419*dfc6aa5cSAndroid Build Coastguard Worker
420*dfc6aa5cSAndroid Build Coastguard Worker for (i = 0; i < DCTSIZE2; i++) {
421*dfc6aa5cSAndroid Build Coastguard Worker temp = workspace[i];
422*dfc6aa5cSAndroid Build Coastguard Worker recip = divisors[i + DCTSIZE2 * 0];
423*dfc6aa5cSAndroid Build Coastguard Worker corr = divisors[i + DCTSIZE2 * 1];
424*dfc6aa5cSAndroid Build Coastguard Worker shift = divisors[i + DCTSIZE2 * 3];
425*dfc6aa5cSAndroid Build Coastguard Worker
426*dfc6aa5cSAndroid Build Coastguard Worker if (temp < 0) {
427*dfc6aa5cSAndroid Build Coastguard Worker temp = -temp;
428*dfc6aa5cSAndroid Build Coastguard Worker product = (UDCTELEM2)(temp + corr) * recip;
429*dfc6aa5cSAndroid Build Coastguard Worker product >>= shift + sizeof(DCTELEM) * 8;
430*dfc6aa5cSAndroid Build Coastguard Worker temp = (DCTELEM)product;
431*dfc6aa5cSAndroid Build Coastguard Worker temp = -temp;
432*dfc6aa5cSAndroid Build Coastguard Worker } else {
433*dfc6aa5cSAndroid Build Coastguard Worker product = (UDCTELEM2)(temp + corr) * recip;
434*dfc6aa5cSAndroid Build Coastguard Worker product >>= shift + sizeof(DCTELEM) * 8;
435*dfc6aa5cSAndroid Build Coastguard Worker temp = (DCTELEM)product;
436*dfc6aa5cSAndroid Build Coastguard Worker }
437*dfc6aa5cSAndroid Build Coastguard Worker output_ptr[i] = (JCOEF)temp;
438*dfc6aa5cSAndroid Build Coastguard Worker }
439*dfc6aa5cSAndroid Build Coastguard Worker
440*dfc6aa5cSAndroid Build Coastguard Worker #else
441*dfc6aa5cSAndroid Build Coastguard Worker
442*dfc6aa5cSAndroid Build Coastguard Worker register DCTELEM qval;
443*dfc6aa5cSAndroid Build Coastguard Worker
444*dfc6aa5cSAndroid Build Coastguard Worker for (i = 0; i < DCTSIZE2; i++) {
445*dfc6aa5cSAndroid Build Coastguard Worker qval = divisors[i];
446*dfc6aa5cSAndroid Build Coastguard Worker temp = workspace[i];
447*dfc6aa5cSAndroid Build Coastguard Worker /* Divide the coefficient value by qval, ensuring proper rounding.
448*dfc6aa5cSAndroid Build Coastguard Worker * Since C does not specify the direction of rounding for negative
449*dfc6aa5cSAndroid Build Coastguard Worker * quotients, we have to force the dividend positive for portability.
450*dfc6aa5cSAndroid Build Coastguard Worker *
451*dfc6aa5cSAndroid Build Coastguard Worker * In most files, at least half of the output values will be zero
452*dfc6aa5cSAndroid Build Coastguard Worker * (at default quantization settings, more like three-quarters...)
453*dfc6aa5cSAndroid Build Coastguard Worker * so we should ensure that this case is fast. On many machines,
454*dfc6aa5cSAndroid Build Coastguard Worker * a comparison is enough cheaper than a divide to make a special test
455*dfc6aa5cSAndroid Build Coastguard Worker * a win. Since both inputs will be nonnegative, we need only test
456*dfc6aa5cSAndroid Build Coastguard Worker * for a < b to discover whether a/b is 0.
457*dfc6aa5cSAndroid Build Coastguard Worker * If your machine's division is fast enough, define FAST_DIVIDE.
458*dfc6aa5cSAndroid Build Coastguard Worker */
459*dfc6aa5cSAndroid Build Coastguard Worker #ifdef FAST_DIVIDE
460*dfc6aa5cSAndroid Build Coastguard Worker #define DIVIDE_BY(a, b) a /= b
461*dfc6aa5cSAndroid Build Coastguard Worker #else
462*dfc6aa5cSAndroid Build Coastguard Worker #define DIVIDE_BY(a, b) if (a >= b) a /= b; else a = 0
463*dfc6aa5cSAndroid Build Coastguard Worker #endif
464*dfc6aa5cSAndroid Build Coastguard Worker if (temp < 0) {
465*dfc6aa5cSAndroid Build Coastguard Worker temp = -temp;
466*dfc6aa5cSAndroid Build Coastguard Worker temp += qval >> 1; /* for rounding */
467*dfc6aa5cSAndroid Build Coastguard Worker DIVIDE_BY(temp, qval);
468*dfc6aa5cSAndroid Build Coastguard Worker temp = -temp;
469*dfc6aa5cSAndroid Build Coastguard Worker } else {
470*dfc6aa5cSAndroid Build Coastguard Worker temp += qval >> 1; /* for rounding */
471*dfc6aa5cSAndroid Build Coastguard Worker DIVIDE_BY(temp, qval);
472*dfc6aa5cSAndroid Build Coastguard Worker }
473*dfc6aa5cSAndroid Build Coastguard Worker output_ptr[i] = (JCOEF)temp;
474*dfc6aa5cSAndroid Build Coastguard Worker }
475*dfc6aa5cSAndroid Build Coastguard Worker
476*dfc6aa5cSAndroid Build Coastguard Worker #endif
477*dfc6aa5cSAndroid Build Coastguard Worker
478*dfc6aa5cSAndroid Build Coastguard Worker }
479*dfc6aa5cSAndroid Build Coastguard Worker
480*dfc6aa5cSAndroid Build Coastguard Worker
481*dfc6aa5cSAndroid Build Coastguard Worker /*
482*dfc6aa5cSAndroid Build Coastguard Worker * Perform forward DCT on one or more blocks of a component.
483*dfc6aa5cSAndroid Build Coastguard Worker *
484*dfc6aa5cSAndroid Build Coastguard Worker * The input samples are taken from the sample_data[] array starting at
485*dfc6aa5cSAndroid Build Coastguard Worker * position start_row/start_col, and moving to the right for any additional
486*dfc6aa5cSAndroid Build Coastguard Worker * blocks. The quantized coefficients are returned in coef_blocks[].
487*dfc6aa5cSAndroid Build Coastguard Worker */
488*dfc6aa5cSAndroid Build Coastguard Worker
489*dfc6aa5cSAndroid Build Coastguard Worker METHODDEF(void)
forward_DCT(j_compress_ptr cinfo,jpeg_component_info * compptr,JSAMPARRAY sample_data,JBLOCKROW coef_blocks,JDIMENSION start_row,JDIMENSION start_col,JDIMENSION num_blocks)490*dfc6aa5cSAndroid Build Coastguard Worker forward_DCT(j_compress_ptr cinfo, jpeg_component_info *compptr,
491*dfc6aa5cSAndroid Build Coastguard Worker JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
492*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION start_row, JDIMENSION start_col, JDIMENSION num_blocks)
493*dfc6aa5cSAndroid Build Coastguard Worker /* This version is used for integer DCT implementations. */
494*dfc6aa5cSAndroid Build Coastguard Worker {
495*dfc6aa5cSAndroid Build Coastguard Worker /* This routine is heavily used, so it's worth coding it tightly. */
496*dfc6aa5cSAndroid Build Coastguard Worker my_fdct_ptr fdct = (my_fdct_ptr)cinfo->fdct;
497*dfc6aa5cSAndroid Build Coastguard Worker DCTELEM *divisors = fdct->divisors[compptr->quant_tbl_no];
498*dfc6aa5cSAndroid Build Coastguard Worker DCTELEM *workspace;
499*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION bi;
500*dfc6aa5cSAndroid Build Coastguard Worker
501*dfc6aa5cSAndroid Build Coastguard Worker /* Make sure the compiler doesn't look up these every pass */
502*dfc6aa5cSAndroid Build Coastguard Worker forward_DCT_method_ptr do_dct = fdct->dct;
503*dfc6aa5cSAndroid Build Coastguard Worker convsamp_method_ptr do_convsamp = fdct->convsamp;
504*dfc6aa5cSAndroid Build Coastguard Worker quantize_method_ptr do_quantize = fdct->quantize;
505*dfc6aa5cSAndroid Build Coastguard Worker workspace = fdct->workspace;
506*dfc6aa5cSAndroid Build Coastguard Worker
507*dfc6aa5cSAndroid Build Coastguard Worker sample_data += start_row; /* fold in the vertical offset once */
508*dfc6aa5cSAndroid Build Coastguard Worker
509*dfc6aa5cSAndroid Build Coastguard Worker for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) {
510*dfc6aa5cSAndroid Build Coastguard Worker /* Load data into workspace, applying unsigned->signed conversion */
511*dfc6aa5cSAndroid Build Coastguard Worker (*do_convsamp) (sample_data, start_col, workspace);
512*dfc6aa5cSAndroid Build Coastguard Worker
513*dfc6aa5cSAndroid Build Coastguard Worker /* Perform the DCT */
514*dfc6aa5cSAndroid Build Coastguard Worker (*do_dct) (workspace);
515*dfc6aa5cSAndroid Build Coastguard Worker
516*dfc6aa5cSAndroid Build Coastguard Worker /* Quantize/descale the coefficients, and store into coef_blocks[] */
517*dfc6aa5cSAndroid Build Coastguard Worker (*do_quantize) (coef_blocks[bi], divisors, workspace);
518*dfc6aa5cSAndroid Build Coastguard Worker }
519*dfc6aa5cSAndroid Build Coastguard Worker }
520*dfc6aa5cSAndroid Build Coastguard Worker
521*dfc6aa5cSAndroid Build Coastguard Worker
522*dfc6aa5cSAndroid Build Coastguard Worker #ifdef DCT_FLOAT_SUPPORTED
523*dfc6aa5cSAndroid Build Coastguard Worker
524*dfc6aa5cSAndroid Build Coastguard Worker METHODDEF(void)
convsamp_float(JSAMPARRAY sample_data,JDIMENSION start_col,FAST_FLOAT * workspace)525*dfc6aa5cSAndroid Build Coastguard Worker convsamp_float(JSAMPARRAY sample_data, JDIMENSION start_col,
526*dfc6aa5cSAndroid Build Coastguard Worker FAST_FLOAT *workspace)
527*dfc6aa5cSAndroid Build Coastguard Worker {
528*dfc6aa5cSAndroid Build Coastguard Worker register FAST_FLOAT *workspaceptr;
529*dfc6aa5cSAndroid Build Coastguard Worker register JSAMPROW elemptr;
530*dfc6aa5cSAndroid Build Coastguard Worker register int elemr;
531*dfc6aa5cSAndroid Build Coastguard Worker
532*dfc6aa5cSAndroid Build Coastguard Worker workspaceptr = workspace;
533*dfc6aa5cSAndroid Build Coastguard Worker for (elemr = 0; elemr < DCTSIZE; elemr++) {
534*dfc6aa5cSAndroid Build Coastguard Worker elemptr = sample_data[elemr] + start_col;
535*dfc6aa5cSAndroid Build Coastguard Worker #if DCTSIZE == 8 /* unroll the inner loop */
536*dfc6aa5cSAndroid Build Coastguard Worker *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE);
537*dfc6aa5cSAndroid Build Coastguard Worker *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE);
538*dfc6aa5cSAndroid Build Coastguard Worker *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE);
539*dfc6aa5cSAndroid Build Coastguard Worker *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE);
540*dfc6aa5cSAndroid Build Coastguard Worker *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE);
541*dfc6aa5cSAndroid Build Coastguard Worker *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE);
542*dfc6aa5cSAndroid Build Coastguard Worker *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE);
543*dfc6aa5cSAndroid Build Coastguard Worker *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE);
544*dfc6aa5cSAndroid Build Coastguard Worker #else
545*dfc6aa5cSAndroid Build Coastguard Worker {
546*dfc6aa5cSAndroid Build Coastguard Worker register int elemc;
547*dfc6aa5cSAndroid Build Coastguard Worker for (elemc = DCTSIZE; elemc > 0; elemc--)
548*dfc6aa5cSAndroid Build Coastguard Worker *workspaceptr++ = (FAST_FLOAT)((*elemptr++) - CENTERJSAMPLE);
549*dfc6aa5cSAndroid Build Coastguard Worker }
550*dfc6aa5cSAndroid Build Coastguard Worker #endif
551*dfc6aa5cSAndroid Build Coastguard Worker }
552*dfc6aa5cSAndroid Build Coastguard Worker }
553*dfc6aa5cSAndroid Build Coastguard Worker
554*dfc6aa5cSAndroid Build Coastguard Worker
555*dfc6aa5cSAndroid Build Coastguard Worker METHODDEF(void)
quantize_float(JCOEFPTR coef_block,FAST_FLOAT * divisors,FAST_FLOAT * workspace)556*dfc6aa5cSAndroid Build Coastguard Worker quantize_float(JCOEFPTR coef_block, FAST_FLOAT *divisors,
557*dfc6aa5cSAndroid Build Coastguard Worker FAST_FLOAT *workspace)
558*dfc6aa5cSAndroid Build Coastguard Worker {
559*dfc6aa5cSAndroid Build Coastguard Worker register FAST_FLOAT temp;
560*dfc6aa5cSAndroid Build Coastguard Worker register int i;
561*dfc6aa5cSAndroid Build Coastguard Worker register JCOEFPTR output_ptr = coef_block;
562*dfc6aa5cSAndroid Build Coastguard Worker
563*dfc6aa5cSAndroid Build Coastguard Worker for (i = 0; i < DCTSIZE2; i++) {
564*dfc6aa5cSAndroid Build Coastguard Worker /* Apply the quantization and scaling factor */
565*dfc6aa5cSAndroid Build Coastguard Worker temp = workspace[i] * divisors[i];
566*dfc6aa5cSAndroid Build Coastguard Worker
567*dfc6aa5cSAndroid Build Coastguard Worker /* Round to nearest integer.
568*dfc6aa5cSAndroid Build Coastguard Worker * Since C does not specify the direction of rounding for negative
569*dfc6aa5cSAndroid Build Coastguard Worker * quotients, we have to force the dividend positive for portability.
570*dfc6aa5cSAndroid Build Coastguard Worker * The maximum coefficient size is +-16K (for 12-bit data), so this
571*dfc6aa5cSAndroid Build Coastguard Worker * code should work for either 16-bit or 32-bit ints.
572*dfc6aa5cSAndroid Build Coastguard Worker */
573*dfc6aa5cSAndroid Build Coastguard Worker output_ptr[i] = (JCOEF)((int)(temp + (FAST_FLOAT)16384.5) - 16384);
574*dfc6aa5cSAndroid Build Coastguard Worker }
575*dfc6aa5cSAndroid Build Coastguard Worker }
576*dfc6aa5cSAndroid Build Coastguard Worker
577*dfc6aa5cSAndroid Build Coastguard Worker
578*dfc6aa5cSAndroid Build Coastguard Worker METHODDEF(void)
forward_DCT_float(j_compress_ptr cinfo,jpeg_component_info * compptr,JSAMPARRAY sample_data,JBLOCKROW coef_blocks,JDIMENSION start_row,JDIMENSION start_col,JDIMENSION num_blocks)579*dfc6aa5cSAndroid Build Coastguard Worker forward_DCT_float(j_compress_ptr cinfo, jpeg_component_info *compptr,
580*dfc6aa5cSAndroid Build Coastguard Worker JSAMPARRAY sample_data, JBLOCKROW coef_blocks,
581*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION start_row, JDIMENSION start_col,
582*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION num_blocks)
583*dfc6aa5cSAndroid Build Coastguard Worker /* This version is used for floating-point DCT implementations. */
584*dfc6aa5cSAndroid Build Coastguard Worker {
585*dfc6aa5cSAndroid Build Coastguard Worker /* This routine is heavily used, so it's worth coding it tightly. */
586*dfc6aa5cSAndroid Build Coastguard Worker my_fdct_ptr fdct = (my_fdct_ptr)cinfo->fdct;
587*dfc6aa5cSAndroid Build Coastguard Worker FAST_FLOAT *divisors = fdct->float_divisors[compptr->quant_tbl_no];
588*dfc6aa5cSAndroid Build Coastguard Worker FAST_FLOAT *workspace;
589*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION bi;
590*dfc6aa5cSAndroid Build Coastguard Worker
591*dfc6aa5cSAndroid Build Coastguard Worker
592*dfc6aa5cSAndroid Build Coastguard Worker /* Make sure the compiler doesn't look up these every pass */
593*dfc6aa5cSAndroid Build Coastguard Worker float_DCT_method_ptr do_dct = fdct->float_dct;
594*dfc6aa5cSAndroid Build Coastguard Worker float_convsamp_method_ptr do_convsamp = fdct->float_convsamp;
595*dfc6aa5cSAndroid Build Coastguard Worker float_quantize_method_ptr do_quantize = fdct->float_quantize;
596*dfc6aa5cSAndroid Build Coastguard Worker workspace = fdct->float_workspace;
597*dfc6aa5cSAndroid Build Coastguard Worker
598*dfc6aa5cSAndroid Build Coastguard Worker sample_data += start_row; /* fold in the vertical offset once */
599*dfc6aa5cSAndroid Build Coastguard Worker
600*dfc6aa5cSAndroid Build Coastguard Worker for (bi = 0; bi < num_blocks; bi++, start_col += DCTSIZE) {
601*dfc6aa5cSAndroid Build Coastguard Worker /* Load data into workspace, applying unsigned->signed conversion */
602*dfc6aa5cSAndroid Build Coastguard Worker (*do_convsamp) (sample_data, start_col, workspace);
603*dfc6aa5cSAndroid Build Coastguard Worker
604*dfc6aa5cSAndroid Build Coastguard Worker /* Perform the DCT */
605*dfc6aa5cSAndroid Build Coastguard Worker (*do_dct) (workspace);
606*dfc6aa5cSAndroid Build Coastguard Worker
607*dfc6aa5cSAndroid Build Coastguard Worker /* Quantize/descale the coefficients, and store into coef_blocks[] */
608*dfc6aa5cSAndroid Build Coastguard Worker (*do_quantize) (coef_blocks[bi], divisors, workspace);
609*dfc6aa5cSAndroid Build Coastguard Worker }
610*dfc6aa5cSAndroid Build Coastguard Worker }
611*dfc6aa5cSAndroid Build Coastguard Worker
612*dfc6aa5cSAndroid Build Coastguard Worker #endif /* DCT_FLOAT_SUPPORTED */
613*dfc6aa5cSAndroid Build Coastguard Worker
614*dfc6aa5cSAndroid Build Coastguard Worker
615*dfc6aa5cSAndroid Build Coastguard Worker /*
616*dfc6aa5cSAndroid Build Coastguard Worker * Initialize FDCT manager.
617*dfc6aa5cSAndroid Build Coastguard Worker */
618*dfc6aa5cSAndroid Build Coastguard Worker
619*dfc6aa5cSAndroid Build Coastguard Worker GLOBAL(void)
jinit_forward_dct(j_compress_ptr cinfo)620*dfc6aa5cSAndroid Build Coastguard Worker jinit_forward_dct(j_compress_ptr cinfo)
621*dfc6aa5cSAndroid Build Coastguard Worker {
622*dfc6aa5cSAndroid Build Coastguard Worker my_fdct_ptr fdct;
623*dfc6aa5cSAndroid Build Coastguard Worker int i;
624*dfc6aa5cSAndroid Build Coastguard Worker
625*dfc6aa5cSAndroid Build Coastguard Worker fdct = (my_fdct_ptr)
626*dfc6aa5cSAndroid Build Coastguard Worker (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
627*dfc6aa5cSAndroid Build Coastguard Worker sizeof(my_fdct_controller));
628*dfc6aa5cSAndroid Build Coastguard Worker cinfo->fdct = (struct jpeg_forward_dct *)fdct;
629*dfc6aa5cSAndroid Build Coastguard Worker fdct->pub.start_pass = start_pass_fdctmgr;
630*dfc6aa5cSAndroid Build Coastguard Worker
631*dfc6aa5cSAndroid Build Coastguard Worker /* First determine the DCT... */
632*dfc6aa5cSAndroid Build Coastguard Worker switch (cinfo->dct_method) {
633*dfc6aa5cSAndroid Build Coastguard Worker #ifdef DCT_ISLOW_SUPPORTED
634*dfc6aa5cSAndroid Build Coastguard Worker case JDCT_ISLOW:
635*dfc6aa5cSAndroid Build Coastguard Worker fdct->pub.forward_DCT = forward_DCT;
636*dfc6aa5cSAndroid Build Coastguard Worker if (jsimd_can_fdct_islow())
637*dfc6aa5cSAndroid Build Coastguard Worker fdct->dct = jsimd_fdct_islow;
638*dfc6aa5cSAndroid Build Coastguard Worker else
639*dfc6aa5cSAndroid Build Coastguard Worker fdct->dct = jpeg_fdct_islow;
640*dfc6aa5cSAndroid Build Coastguard Worker break;
641*dfc6aa5cSAndroid Build Coastguard Worker #endif
642*dfc6aa5cSAndroid Build Coastguard Worker #ifdef DCT_IFAST_SUPPORTED
643*dfc6aa5cSAndroid Build Coastguard Worker case JDCT_IFAST:
644*dfc6aa5cSAndroid Build Coastguard Worker fdct->pub.forward_DCT = forward_DCT;
645*dfc6aa5cSAndroid Build Coastguard Worker if (jsimd_can_fdct_ifast())
646*dfc6aa5cSAndroid Build Coastguard Worker fdct->dct = jsimd_fdct_ifast;
647*dfc6aa5cSAndroid Build Coastguard Worker else
648*dfc6aa5cSAndroid Build Coastguard Worker fdct->dct = jpeg_fdct_ifast;
649*dfc6aa5cSAndroid Build Coastguard Worker break;
650*dfc6aa5cSAndroid Build Coastguard Worker #endif
651*dfc6aa5cSAndroid Build Coastguard Worker #ifdef DCT_FLOAT_SUPPORTED
652*dfc6aa5cSAndroid Build Coastguard Worker case JDCT_FLOAT:
653*dfc6aa5cSAndroid Build Coastguard Worker fdct->pub.forward_DCT = forward_DCT_float;
654*dfc6aa5cSAndroid Build Coastguard Worker if (jsimd_can_fdct_float())
655*dfc6aa5cSAndroid Build Coastguard Worker fdct->float_dct = jsimd_fdct_float;
656*dfc6aa5cSAndroid Build Coastguard Worker else
657*dfc6aa5cSAndroid Build Coastguard Worker fdct->float_dct = jpeg_fdct_float;
658*dfc6aa5cSAndroid Build Coastguard Worker break;
659*dfc6aa5cSAndroid Build Coastguard Worker #endif
660*dfc6aa5cSAndroid Build Coastguard Worker default:
661*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT(cinfo, JERR_NOT_COMPILED);
662*dfc6aa5cSAndroid Build Coastguard Worker break;
663*dfc6aa5cSAndroid Build Coastguard Worker }
664*dfc6aa5cSAndroid Build Coastguard Worker
665*dfc6aa5cSAndroid Build Coastguard Worker /* ...then the supporting stages. */
666*dfc6aa5cSAndroid Build Coastguard Worker switch (cinfo->dct_method) {
667*dfc6aa5cSAndroid Build Coastguard Worker #ifdef DCT_ISLOW_SUPPORTED
668*dfc6aa5cSAndroid Build Coastguard Worker case JDCT_ISLOW:
669*dfc6aa5cSAndroid Build Coastguard Worker #endif
670*dfc6aa5cSAndroid Build Coastguard Worker #ifdef DCT_IFAST_SUPPORTED
671*dfc6aa5cSAndroid Build Coastguard Worker case JDCT_IFAST:
672*dfc6aa5cSAndroid Build Coastguard Worker #endif
673*dfc6aa5cSAndroid Build Coastguard Worker #if defined(DCT_ISLOW_SUPPORTED) || defined(DCT_IFAST_SUPPORTED)
674*dfc6aa5cSAndroid Build Coastguard Worker if (jsimd_can_convsamp())
675*dfc6aa5cSAndroid Build Coastguard Worker fdct->convsamp = jsimd_convsamp;
676*dfc6aa5cSAndroid Build Coastguard Worker else
677*dfc6aa5cSAndroid Build Coastguard Worker fdct->convsamp = convsamp;
678*dfc6aa5cSAndroid Build Coastguard Worker if (jsimd_can_quantize())
679*dfc6aa5cSAndroid Build Coastguard Worker fdct->quantize = jsimd_quantize;
680*dfc6aa5cSAndroid Build Coastguard Worker else
681*dfc6aa5cSAndroid Build Coastguard Worker fdct->quantize = quantize;
682*dfc6aa5cSAndroid Build Coastguard Worker break;
683*dfc6aa5cSAndroid Build Coastguard Worker #endif
684*dfc6aa5cSAndroid Build Coastguard Worker #ifdef DCT_FLOAT_SUPPORTED
685*dfc6aa5cSAndroid Build Coastguard Worker case JDCT_FLOAT:
686*dfc6aa5cSAndroid Build Coastguard Worker if (jsimd_can_convsamp_float())
687*dfc6aa5cSAndroid Build Coastguard Worker fdct->float_convsamp = jsimd_convsamp_float;
688*dfc6aa5cSAndroid Build Coastguard Worker else
689*dfc6aa5cSAndroid Build Coastguard Worker fdct->float_convsamp = convsamp_float;
690*dfc6aa5cSAndroid Build Coastguard Worker if (jsimd_can_quantize_float())
691*dfc6aa5cSAndroid Build Coastguard Worker fdct->float_quantize = jsimd_quantize_float;
692*dfc6aa5cSAndroid Build Coastguard Worker else
693*dfc6aa5cSAndroid Build Coastguard Worker fdct->float_quantize = quantize_float;
694*dfc6aa5cSAndroid Build Coastguard Worker break;
695*dfc6aa5cSAndroid Build Coastguard Worker #endif
696*dfc6aa5cSAndroid Build Coastguard Worker default:
697*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT(cinfo, JERR_NOT_COMPILED);
698*dfc6aa5cSAndroid Build Coastguard Worker break;
699*dfc6aa5cSAndroid Build Coastguard Worker }
700*dfc6aa5cSAndroid Build Coastguard Worker
701*dfc6aa5cSAndroid Build Coastguard Worker /* Allocate workspace memory */
702*dfc6aa5cSAndroid Build Coastguard Worker #ifdef DCT_FLOAT_SUPPORTED
703*dfc6aa5cSAndroid Build Coastguard Worker if (cinfo->dct_method == JDCT_FLOAT)
704*dfc6aa5cSAndroid Build Coastguard Worker fdct->float_workspace = (FAST_FLOAT *)
705*dfc6aa5cSAndroid Build Coastguard Worker (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
706*dfc6aa5cSAndroid Build Coastguard Worker sizeof(FAST_FLOAT) * DCTSIZE2);
707*dfc6aa5cSAndroid Build Coastguard Worker else
708*dfc6aa5cSAndroid Build Coastguard Worker #endif
709*dfc6aa5cSAndroid Build Coastguard Worker fdct->workspace = (DCTELEM *)
710*dfc6aa5cSAndroid Build Coastguard Worker (*cinfo->mem->alloc_small) ((j_common_ptr)cinfo, JPOOL_IMAGE,
711*dfc6aa5cSAndroid Build Coastguard Worker sizeof(DCTELEM) * DCTSIZE2);
712*dfc6aa5cSAndroid Build Coastguard Worker
713*dfc6aa5cSAndroid Build Coastguard Worker /* Mark divisor tables unallocated */
714*dfc6aa5cSAndroid Build Coastguard Worker for (i = 0; i < NUM_QUANT_TBLS; i++) {
715*dfc6aa5cSAndroid Build Coastguard Worker fdct->divisors[i] = NULL;
716*dfc6aa5cSAndroid Build Coastguard Worker #ifdef DCT_FLOAT_SUPPORTED
717*dfc6aa5cSAndroid Build Coastguard Worker fdct->float_divisors[i] = NULL;
718*dfc6aa5cSAndroid Build Coastguard Worker #endif
719*dfc6aa5cSAndroid Build Coastguard Worker }
720*dfc6aa5cSAndroid Build Coastguard Worker }
721