1*dfc6aa5cSAndroid Build Coastguard Worker /*
2*dfc6aa5cSAndroid Build Coastguard Worker * transupp.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) 1997-2019, Thomas G. Lane, Guido Vollbeding.
6*dfc6aa5cSAndroid Build Coastguard Worker * libjpeg-turbo Modifications:
7*dfc6aa5cSAndroid Build Coastguard Worker * Copyright (C) 2010, 2017, 2021-2022, D. R. Commander.
8*dfc6aa5cSAndroid Build Coastguard Worker * For conditions of distribution and use, see the accompanying README.ijg
9*dfc6aa5cSAndroid Build Coastguard Worker * file.
10*dfc6aa5cSAndroid Build Coastguard Worker *
11*dfc6aa5cSAndroid Build Coastguard Worker * This file contains image transformation routines and other utility code
12*dfc6aa5cSAndroid Build Coastguard Worker * used by the jpegtran sample application. These are NOT part of the core
13*dfc6aa5cSAndroid Build Coastguard Worker * JPEG library. But we keep these routines separate from jpegtran.c to
14*dfc6aa5cSAndroid Build Coastguard Worker * ease the task of maintaining jpegtran-like programs that have other user
15*dfc6aa5cSAndroid Build Coastguard Worker * interfaces.
16*dfc6aa5cSAndroid Build Coastguard Worker */
17*dfc6aa5cSAndroid Build Coastguard Worker
18*dfc6aa5cSAndroid Build Coastguard Worker /* Although this file really shouldn't have access to the library internals,
19*dfc6aa5cSAndroid Build Coastguard Worker * it's helpful to let it call jround_up() and jcopy_block_row().
20*dfc6aa5cSAndroid Build Coastguard Worker */
21*dfc6aa5cSAndroid Build Coastguard Worker #define JPEG_INTERNALS
22*dfc6aa5cSAndroid Build Coastguard Worker
23*dfc6aa5cSAndroid Build Coastguard Worker #include "jinclude.h"
24*dfc6aa5cSAndroid Build Coastguard Worker #include "jpeglib.h"
25*dfc6aa5cSAndroid Build Coastguard Worker #include "transupp.h" /* My own external interface */
26*dfc6aa5cSAndroid Build Coastguard Worker #include "jpegcomp.h"
27*dfc6aa5cSAndroid Build Coastguard Worker #include <ctype.h> /* to declare isdigit() */
28*dfc6aa5cSAndroid Build Coastguard Worker
29*dfc6aa5cSAndroid Build Coastguard Worker
30*dfc6aa5cSAndroid Build Coastguard Worker #if JPEG_LIB_VERSION >= 70
31*dfc6aa5cSAndroid Build Coastguard Worker #define dstinfo_min_DCT_h_scaled_size dstinfo->min_DCT_h_scaled_size
32*dfc6aa5cSAndroid Build Coastguard Worker #define dstinfo_min_DCT_v_scaled_size dstinfo->min_DCT_v_scaled_size
33*dfc6aa5cSAndroid Build Coastguard Worker #else
34*dfc6aa5cSAndroid Build Coastguard Worker #define dstinfo_min_DCT_h_scaled_size DCTSIZE
35*dfc6aa5cSAndroid Build Coastguard Worker #define dstinfo_min_DCT_v_scaled_size DCTSIZE
36*dfc6aa5cSAndroid Build Coastguard Worker #endif
37*dfc6aa5cSAndroid Build Coastguard Worker
38*dfc6aa5cSAndroid Build Coastguard Worker
39*dfc6aa5cSAndroid Build Coastguard Worker #if TRANSFORMS_SUPPORTED
40*dfc6aa5cSAndroid Build Coastguard Worker
41*dfc6aa5cSAndroid Build Coastguard Worker /*
42*dfc6aa5cSAndroid Build Coastguard Worker * Lossless image transformation routines. These routines work on DCT
43*dfc6aa5cSAndroid Build Coastguard Worker * coefficient arrays and thus do not require any lossy decompression
44*dfc6aa5cSAndroid Build Coastguard Worker * or recompression of the image.
45*dfc6aa5cSAndroid Build Coastguard Worker * Thanks to Guido Vollbeding for the initial design and code of this feature,
46*dfc6aa5cSAndroid Build Coastguard Worker * and to Ben Jackson for introducing the cropping feature.
47*dfc6aa5cSAndroid Build Coastguard Worker *
48*dfc6aa5cSAndroid Build Coastguard Worker * Horizontal flipping is done in-place, using a single top-to-bottom
49*dfc6aa5cSAndroid Build Coastguard Worker * pass through the virtual source array. It will thus be much the
50*dfc6aa5cSAndroid Build Coastguard Worker * fastest option for images larger than main memory.
51*dfc6aa5cSAndroid Build Coastguard Worker *
52*dfc6aa5cSAndroid Build Coastguard Worker * The other routines require a set of destination virtual arrays, so they
53*dfc6aa5cSAndroid Build Coastguard Worker * need twice as much memory as jpegtran normally does. The destination
54*dfc6aa5cSAndroid Build Coastguard Worker * arrays are always written in normal scan order (top to bottom) because
55*dfc6aa5cSAndroid Build Coastguard Worker * the virtual array manager expects this. The source arrays will be scanned
56*dfc6aa5cSAndroid Build Coastguard Worker * in the corresponding order, which means multiple passes through the source
57*dfc6aa5cSAndroid Build Coastguard Worker * arrays for most of the transforms. That could result in much thrashing
58*dfc6aa5cSAndroid Build Coastguard Worker * if the image is larger than main memory.
59*dfc6aa5cSAndroid Build Coastguard Worker *
60*dfc6aa5cSAndroid Build Coastguard Worker * If cropping or trimming is involved, the destination arrays may be smaller
61*dfc6aa5cSAndroid Build Coastguard Worker * than the source arrays. Note it is not possible to do horizontal flip
62*dfc6aa5cSAndroid Build Coastguard Worker * in-place when a nonzero Y crop offset is specified, since we'd have to move
63*dfc6aa5cSAndroid Build Coastguard Worker * data from one block row to another but the virtual array manager doesn't
64*dfc6aa5cSAndroid Build Coastguard Worker * guarantee we can touch more than one row at a time. So in that case,
65*dfc6aa5cSAndroid Build Coastguard Worker * we have to use a separate destination array.
66*dfc6aa5cSAndroid Build Coastguard Worker *
67*dfc6aa5cSAndroid Build Coastguard Worker * Some notes about the operating environment of the individual transform
68*dfc6aa5cSAndroid Build Coastguard Worker * routines:
69*dfc6aa5cSAndroid Build Coastguard Worker * 1. Both the source and destination virtual arrays are allocated from the
70*dfc6aa5cSAndroid Build Coastguard Worker * source JPEG object, and therefore should be manipulated by calling the
71*dfc6aa5cSAndroid Build Coastguard Worker * source's memory manager.
72*dfc6aa5cSAndroid Build Coastguard Worker * 2. The destination's component count should be used. It may be smaller
73*dfc6aa5cSAndroid Build Coastguard Worker * than the source's when forcing to grayscale.
74*dfc6aa5cSAndroid Build Coastguard Worker * 3. Likewise the destination's sampling factors should be used. When
75*dfc6aa5cSAndroid Build Coastguard Worker * forcing to grayscale the destination's sampling factors will be all 1,
76*dfc6aa5cSAndroid Build Coastguard Worker * and we may as well take that as the effective iMCU size.
77*dfc6aa5cSAndroid Build Coastguard Worker * 4. When "trim" is in effect, the destination's dimensions will be the
78*dfc6aa5cSAndroid Build Coastguard Worker * trimmed values but the source's will be untrimmed.
79*dfc6aa5cSAndroid Build Coastguard Worker * 5. When "crop" is in effect, the destination's dimensions will be the
80*dfc6aa5cSAndroid Build Coastguard Worker * cropped values but the source's will be uncropped. Each transform
81*dfc6aa5cSAndroid Build Coastguard Worker * routine is responsible for picking up source data starting at the
82*dfc6aa5cSAndroid Build Coastguard Worker * correct X and Y offset for the crop region. (The X and Y offsets
83*dfc6aa5cSAndroid Build Coastguard Worker * passed to the transform routines are measured in iMCU blocks of the
84*dfc6aa5cSAndroid Build Coastguard Worker * destination.)
85*dfc6aa5cSAndroid Build Coastguard Worker * 6. All the routines assume that the source and destination buffers are
86*dfc6aa5cSAndroid Build Coastguard Worker * padded out to a full iMCU boundary. This is true, although for the
87*dfc6aa5cSAndroid Build Coastguard Worker * source buffer it is an undocumented property of jdcoefct.c.
88*dfc6aa5cSAndroid Build Coastguard Worker */
89*dfc6aa5cSAndroid Build Coastguard Worker
90*dfc6aa5cSAndroid Build Coastguard Worker
91*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
dequant_comp(j_decompress_ptr cinfo,jpeg_component_info * compptr,jvirt_barray_ptr coef_array,JQUANT_TBL * qtblptr1)92*dfc6aa5cSAndroid Build Coastguard Worker dequant_comp(j_decompress_ptr cinfo, jpeg_component_info *compptr,
93*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr coef_array, JQUANT_TBL *qtblptr1)
94*dfc6aa5cSAndroid Build Coastguard Worker {
95*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION blk_x, blk_y;
96*dfc6aa5cSAndroid Build Coastguard Worker int offset_y, k;
97*dfc6aa5cSAndroid Build Coastguard Worker JQUANT_TBL *qtblptr;
98*dfc6aa5cSAndroid Build Coastguard Worker JBLOCKARRAY buffer;
99*dfc6aa5cSAndroid Build Coastguard Worker JBLOCKROW block;
100*dfc6aa5cSAndroid Build Coastguard Worker JCOEFPTR ptr;
101*dfc6aa5cSAndroid Build Coastguard Worker
102*dfc6aa5cSAndroid Build Coastguard Worker qtblptr = compptr->quant_table;
103*dfc6aa5cSAndroid Build Coastguard Worker for (blk_y = 0; blk_y < compptr->height_in_blocks;
104*dfc6aa5cSAndroid Build Coastguard Worker blk_y += compptr->v_samp_factor) {
105*dfc6aa5cSAndroid Build Coastguard Worker buffer = (*cinfo->mem->access_virt_barray)
106*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)cinfo, coef_array, blk_y,
107*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->v_samp_factor, TRUE);
108*dfc6aa5cSAndroid Build Coastguard Worker for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
109*dfc6aa5cSAndroid Build Coastguard Worker block = buffer[offset_y];
110*dfc6aa5cSAndroid Build Coastguard Worker for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
111*dfc6aa5cSAndroid Build Coastguard Worker ptr = block[blk_x];
112*dfc6aa5cSAndroid Build Coastguard Worker for (k = 0; k < DCTSIZE2; k++)
113*dfc6aa5cSAndroid Build Coastguard Worker if (qtblptr->quantval[k] != qtblptr1->quantval[k])
114*dfc6aa5cSAndroid Build Coastguard Worker ptr[k] *= qtblptr->quantval[k] / qtblptr1->quantval[k];
115*dfc6aa5cSAndroid Build Coastguard Worker }
116*dfc6aa5cSAndroid Build Coastguard Worker }
117*dfc6aa5cSAndroid Build Coastguard Worker }
118*dfc6aa5cSAndroid Build Coastguard Worker }
119*dfc6aa5cSAndroid Build Coastguard Worker
120*dfc6aa5cSAndroid Build Coastguard Worker
121*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
requant_comp(j_decompress_ptr cinfo,jpeg_component_info * compptr,jvirt_barray_ptr coef_array,JQUANT_TBL * qtblptr1)122*dfc6aa5cSAndroid Build Coastguard Worker requant_comp(j_decompress_ptr cinfo, jpeg_component_info *compptr,
123*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr coef_array, JQUANT_TBL *qtblptr1)
124*dfc6aa5cSAndroid Build Coastguard Worker {
125*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION blk_x, blk_y;
126*dfc6aa5cSAndroid Build Coastguard Worker int offset_y, k;
127*dfc6aa5cSAndroid Build Coastguard Worker JQUANT_TBL *qtblptr;
128*dfc6aa5cSAndroid Build Coastguard Worker JBLOCKARRAY buffer;
129*dfc6aa5cSAndroid Build Coastguard Worker JBLOCKROW block;
130*dfc6aa5cSAndroid Build Coastguard Worker JCOEFPTR ptr;
131*dfc6aa5cSAndroid Build Coastguard Worker JCOEF temp, qval;
132*dfc6aa5cSAndroid Build Coastguard Worker
133*dfc6aa5cSAndroid Build Coastguard Worker qtblptr = compptr->quant_table;
134*dfc6aa5cSAndroid Build Coastguard Worker for (blk_y = 0; blk_y < compptr->height_in_blocks;
135*dfc6aa5cSAndroid Build Coastguard Worker blk_y += compptr->v_samp_factor) {
136*dfc6aa5cSAndroid Build Coastguard Worker buffer = (*cinfo->mem->access_virt_barray)
137*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)cinfo, coef_array, blk_y,
138*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->v_samp_factor, TRUE);
139*dfc6aa5cSAndroid Build Coastguard Worker for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
140*dfc6aa5cSAndroid Build Coastguard Worker block = buffer[offset_y];
141*dfc6aa5cSAndroid Build Coastguard Worker for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
142*dfc6aa5cSAndroid Build Coastguard Worker ptr = block[blk_x];
143*dfc6aa5cSAndroid Build Coastguard Worker for (k = 0; k < DCTSIZE2; k++) {
144*dfc6aa5cSAndroid Build Coastguard Worker temp = qtblptr->quantval[k];
145*dfc6aa5cSAndroid Build Coastguard Worker qval = qtblptr1->quantval[k];
146*dfc6aa5cSAndroid Build Coastguard Worker if (temp != qval && qval != 0) {
147*dfc6aa5cSAndroid Build Coastguard Worker temp *= ptr[k];
148*dfc6aa5cSAndroid Build Coastguard Worker /* The following quantization code is copied from jcdctmgr.c */
149*dfc6aa5cSAndroid Build Coastguard Worker #ifdef FAST_DIVIDE
150*dfc6aa5cSAndroid Build Coastguard Worker #define DIVIDE_BY(a, b) a /= b
151*dfc6aa5cSAndroid Build Coastguard Worker #else
152*dfc6aa5cSAndroid Build Coastguard Worker #define DIVIDE_BY(a, b) if (a >= b) a /= b; else a = 0
153*dfc6aa5cSAndroid Build Coastguard Worker #endif
154*dfc6aa5cSAndroid Build Coastguard Worker if (temp < 0) {
155*dfc6aa5cSAndroid Build Coastguard Worker temp = -temp;
156*dfc6aa5cSAndroid Build Coastguard Worker temp += qval >> 1; /* for rounding */
157*dfc6aa5cSAndroid Build Coastguard Worker DIVIDE_BY(temp, qval);
158*dfc6aa5cSAndroid Build Coastguard Worker temp = -temp;
159*dfc6aa5cSAndroid Build Coastguard Worker } else {
160*dfc6aa5cSAndroid Build Coastguard Worker temp += qval >> 1; /* for rounding */
161*dfc6aa5cSAndroid Build Coastguard Worker DIVIDE_BY(temp, qval);
162*dfc6aa5cSAndroid Build Coastguard Worker }
163*dfc6aa5cSAndroid Build Coastguard Worker ptr[k] = temp;
164*dfc6aa5cSAndroid Build Coastguard Worker }
165*dfc6aa5cSAndroid Build Coastguard Worker }
166*dfc6aa5cSAndroid Build Coastguard Worker }
167*dfc6aa5cSAndroid Build Coastguard Worker }
168*dfc6aa5cSAndroid Build Coastguard Worker }
169*dfc6aa5cSAndroid Build Coastguard Worker }
170*dfc6aa5cSAndroid Build Coastguard Worker
171*dfc6aa5cSAndroid Build Coastguard Worker
172*dfc6aa5cSAndroid Build Coastguard Worker /*
173*dfc6aa5cSAndroid Build Coastguard Worker * Calculate largest common denominator using Euclid's algorithm.
174*dfc6aa5cSAndroid Build Coastguard Worker */
175*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(JCOEF)
largest_common_denominator(JCOEF a,JCOEF b)176*dfc6aa5cSAndroid Build Coastguard Worker largest_common_denominator(JCOEF a, JCOEF b)
177*dfc6aa5cSAndroid Build Coastguard Worker {
178*dfc6aa5cSAndroid Build Coastguard Worker JCOEF c;
179*dfc6aa5cSAndroid Build Coastguard Worker
180*dfc6aa5cSAndroid Build Coastguard Worker do {
181*dfc6aa5cSAndroid Build Coastguard Worker c = a % b;
182*dfc6aa5cSAndroid Build Coastguard Worker a = b;
183*dfc6aa5cSAndroid Build Coastguard Worker b = c;
184*dfc6aa5cSAndroid Build Coastguard Worker } while (c);
185*dfc6aa5cSAndroid Build Coastguard Worker
186*dfc6aa5cSAndroid Build Coastguard Worker return a;
187*dfc6aa5cSAndroid Build Coastguard Worker }
188*dfc6aa5cSAndroid Build Coastguard Worker
189*dfc6aa5cSAndroid Build Coastguard Worker
190*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
adjust_quant(j_decompress_ptr srcinfo,jvirt_barray_ptr * src_coef_arrays,j_decompress_ptr dropinfo,jvirt_barray_ptr * drop_coef_arrays,boolean trim,j_compress_ptr dstinfo)191*dfc6aa5cSAndroid Build Coastguard Worker adjust_quant(j_decompress_ptr srcinfo, jvirt_barray_ptr *src_coef_arrays,
192*dfc6aa5cSAndroid Build Coastguard Worker j_decompress_ptr dropinfo, jvirt_barray_ptr *drop_coef_arrays,
193*dfc6aa5cSAndroid Build Coastguard Worker boolean trim, j_compress_ptr dstinfo)
194*dfc6aa5cSAndroid Build Coastguard Worker {
195*dfc6aa5cSAndroid Build Coastguard Worker jpeg_component_info *compptr1, *compptr2;
196*dfc6aa5cSAndroid Build Coastguard Worker JQUANT_TBL *qtblptr1, *qtblptr2, *qtblptr3;
197*dfc6aa5cSAndroid Build Coastguard Worker int ci, k;
198*dfc6aa5cSAndroid Build Coastguard Worker
199*dfc6aa5cSAndroid Build Coastguard Worker for (ci = 0; ci < dstinfo->num_components && ci < dropinfo->num_components;
200*dfc6aa5cSAndroid Build Coastguard Worker ci++) {
201*dfc6aa5cSAndroid Build Coastguard Worker compptr1 = srcinfo->comp_info + ci;
202*dfc6aa5cSAndroid Build Coastguard Worker compptr2 = dropinfo->comp_info + ci;
203*dfc6aa5cSAndroid Build Coastguard Worker qtblptr1 = compptr1->quant_table;
204*dfc6aa5cSAndroid Build Coastguard Worker qtblptr2 = compptr2->quant_table;
205*dfc6aa5cSAndroid Build Coastguard Worker for (k = 0; k < DCTSIZE2; k++) {
206*dfc6aa5cSAndroid Build Coastguard Worker if (qtblptr1->quantval[k] != qtblptr2->quantval[k]) {
207*dfc6aa5cSAndroid Build Coastguard Worker if (trim)
208*dfc6aa5cSAndroid Build Coastguard Worker requant_comp(dropinfo, compptr2, drop_coef_arrays[ci], qtblptr1);
209*dfc6aa5cSAndroid Build Coastguard Worker else {
210*dfc6aa5cSAndroid Build Coastguard Worker qtblptr3 = dstinfo->quant_tbl_ptrs[compptr1->quant_tbl_no];
211*dfc6aa5cSAndroid Build Coastguard Worker for (k = 0; k < DCTSIZE2; k++)
212*dfc6aa5cSAndroid Build Coastguard Worker if (qtblptr1->quantval[k] != qtblptr2->quantval[k])
213*dfc6aa5cSAndroid Build Coastguard Worker qtblptr3->quantval[k] =
214*dfc6aa5cSAndroid Build Coastguard Worker largest_common_denominator(qtblptr1->quantval[k],
215*dfc6aa5cSAndroid Build Coastguard Worker qtblptr2->quantval[k]);
216*dfc6aa5cSAndroid Build Coastguard Worker dequant_comp(srcinfo, compptr1, src_coef_arrays[ci], qtblptr3);
217*dfc6aa5cSAndroid Build Coastguard Worker dequant_comp(dropinfo, compptr2, drop_coef_arrays[ci], qtblptr3);
218*dfc6aa5cSAndroid Build Coastguard Worker }
219*dfc6aa5cSAndroid Build Coastguard Worker break;
220*dfc6aa5cSAndroid Build Coastguard Worker }
221*dfc6aa5cSAndroid Build Coastguard Worker }
222*dfc6aa5cSAndroid Build Coastguard Worker }
223*dfc6aa5cSAndroid Build Coastguard Worker }
224*dfc6aa5cSAndroid Build Coastguard Worker
225*dfc6aa5cSAndroid Build Coastguard Worker
226*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
do_drop(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,JDIMENSION y_crop_offset,jvirt_barray_ptr * src_coef_arrays,j_decompress_ptr dropinfo,jvirt_barray_ptr * drop_coef_arrays,JDIMENSION drop_width,JDIMENSION drop_height)227*dfc6aa5cSAndroid Build Coastguard Worker do_drop(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
228*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
229*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *src_coef_arrays,
230*dfc6aa5cSAndroid Build Coastguard Worker j_decompress_ptr dropinfo, jvirt_barray_ptr *drop_coef_arrays,
231*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION drop_width, JDIMENSION drop_height)
232*dfc6aa5cSAndroid Build Coastguard Worker /* Drop (insert) the contents of another image into the source image. If the
233*dfc6aa5cSAndroid Build Coastguard Worker * number of components in the drop image is smaller than the number of
234*dfc6aa5cSAndroid Build Coastguard Worker * components in the destination image, then we fill in the remaining
235*dfc6aa5cSAndroid Build Coastguard Worker * components with zero. This allows for dropping the contents of grayscale
236*dfc6aa5cSAndroid Build Coastguard Worker * images into (arbitrarily sampled) color images.
237*dfc6aa5cSAndroid Build Coastguard Worker */
238*dfc6aa5cSAndroid Build Coastguard Worker {
239*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION comp_width, comp_height;
240*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION blk_y, x_drop_blocks, y_drop_blocks;
241*dfc6aa5cSAndroid Build Coastguard Worker int ci, offset_y;
242*dfc6aa5cSAndroid Build Coastguard Worker JBLOCKARRAY src_buffer, dst_buffer;
243*dfc6aa5cSAndroid Build Coastguard Worker jpeg_component_info *compptr;
244*dfc6aa5cSAndroid Build Coastguard Worker
245*dfc6aa5cSAndroid Build Coastguard Worker for (ci = 0; ci < dstinfo->num_components; ci++) {
246*dfc6aa5cSAndroid Build Coastguard Worker compptr = dstinfo->comp_info + ci;
247*dfc6aa5cSAndroid Build Coastguard Worker comp_width = drop_width * compptr->h_samp_factor;
248*dfc6aa5cSAndroid Build Coastguard Worker comp_height = drop_height * compptr->v_samp_factor;
249*dfc6aa5cSAndroid Build Coastguard Worker x_drop_blocks = x_crop_offset * compptr->h_samp_factor;
250*dfc6aa5cSAndroid Build Coastguard Worker y_drop_blocks = y_crop_offset * compptr->v_samp_factor;
251*dfc6aa5cSAndroid Build Coastguard Worker for (blk_y = 0; blk_y < comp_height; blk_y += compptr->v_samp_factor) {
252*dfc6aa5cSAndroid Build Coastguard Worker dst_buffer = (*srcinfo->mem->access_virt_barray)
253*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, src_coef_arrays[ci], blk_y + y_drop_blocks,
254*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->v_samp_factor, TRUE);
255*dfc6aa5cSAndroid Build Coastguard Worker if (ci < dropinfo->num_components) {
256*dfc6aa5cSAndroid Build Coastguard Worker src_buffer = (*dropinfo->mem->access_virt_barray)
257*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)dropinfo, drop_coef_arrays[ci], blk_y,
258*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->v_samp_factor, FALSE);
259*dfc6aa5cSAndroid Build Coastguard Worker for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
260*dfc6aa5cSAndroid Build Coastguard Worker jcopy_block_row(src_buffer[offset_y],
261*dfc6aa5cSAndroid Build Coastguard Worker dst_buffer[offset_y] + x_drop_blocks, comp_width);
262*dfc6aa5cSAndroid Build Coastguard Worker }
263*dfc6aa5cSAndroid Build Coastguard Worker } else {
264*dfc6aa5cSAndroid Build Coastguard Worker for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
265*dfc6aa5cSAndroid Build Coastguard Worker memset(dst_buffer[offset_y] + x_drop_blocks, 0,
266*dfc6aa5cSAndroid Build Coastguard Worker comp_width * sizeof(JBLOCK));
267*dfc6aa5cSAndroid Build Coastguard Worker }
268*dfc6aa5cSAndroid Build Coastguard Worker }
269*dfc6aa5cSAndroid Build Coastguard Worker }
270*dfc6aa5cSAndroid Build Coastguard Worker }
271*dfc6aa5cSAndroid Build Coastguard Worker }
272*dfc6aa5cSAndroid Build Coastguard Worker
273*dfc6aa5cSAndroid Build Coastguard Worker
274*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
do_crop(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,JDIMENSION y_crop_offset,jvirt_barray_ptr * src_coef_arrays,jvirt_barray_ptr * dst_coef_arrays)275*dfc6aa5cSAndroid Build Coastguard Worker do_crop(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
276*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
277*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *src_coef_arrays,
278*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *dst_coef_arrays)
279*dfc6aa5cSAndroid Build Coastguard Worker /* Crop. This is only used when no rotate/flip is requested with the crop. */
280*dfc6aa5cSAndroid Build Coastguard Worker {
281*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks;
282*dfc6aa5cSAndroid Build Coastguard Worker int ci, offset_y;
283*dfc6aa5cSAndroid Build Coastguard Worker JBLOCKARRAY src_buffer, dst_buffer;
284*dfc6aa5cSAndroid Build Coastguard Worker jpeg_component_info *compptr;
285*dfc6aa5cSAndroid Build Coastguard Worker
286*dfc6aa5cSAndroid Build Coastguard Worker /* We simply have to copy the right amount of data (the destination's
287*dfc6aa5cSAndroid Build Coastguard Worker * image size) starting at the given X and Y offsets in the source.
288*dfc6aa5cSAndroid Build Coastguard Worker */
289*dfc6aa5cSAndroid Build Coastguard Worker for (ci = 0; ci < dstinfo->num_components; ci++) {
290*dfc6aa5cSAndroid Build Coastguard Worker compptr = dstinfo->comp_info + ci;
291*dfc6aa5cSAndroid Build Coastguard Worker x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
292*dfc6aa5cSAndroid Build Coastguard Worker y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
293*dfc6aa5cSAndroid Build Coastguard Worker for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
294*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_y += compptr->v_samp_factor) {
295*dfc6aa5cSAndroid Build Coastguard Worker dst_buffer = (*srcinfo->mem->access_virt_barray)
296*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
297*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->v_samp_factor, TRUE);
298*dfc6aa5cSAndroid Build Coastguard Worker src_buffer = (*srcinfo->mem->access_virt_barray)
299*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, src_coef_arrays[ci], dst_blk_y + y_crop_blocks,
300*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->v_samp_factor, FALSE);
301*dfc6aa5cSAndroid Build Coastguard Worker for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
302*dfc6aa5cSAndroid Build Coastguard Worker jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
303*dfc6aa5cSAndroid Build Coastguard Worker dst_buffer[offset_y], compptr->width_in_blocks);
304*dfc6aa5cSAndroid Build Coastguard Worker }
305*dfc6aa5cSAndroid Build Coastguard Worker }
306*dfc6aa5cSAndroid Build Coastguard Worker }
307*dfc6aa5cSAndroid Build Coastguard Worker }
308*dfc6aa5cSAndroid Build Coastguard Worker
309*dfc6aa5cSAndroid Build Coastguard Worker
310*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
do_crop_ext_zero(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,JDIMENSION y_crop_offset,jvirt_barray_ptr * src_coef_arrays,jvirt_barray_ptr * dst_coef_arrays)311*dfc6aa5cSAndroid Build Coastguard Worker do_crop_ext_zero(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
312*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
313*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *src_coef_arrays,
314*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *dst_coef_arrays)
315*dfc6aa5cSAndroid Build Coastguard Worker /* Crop. This is only used when no rotate/flip is requested with the crop.
316*dfc6aa5cSAndroid Build Coastguard Worker * Extension: If the destination size is larger than the source, we fill in the
317*dfc6aa5cSAndroid Build Coastguard Worker * expanded region with zero (neutral gray). Note that we also have to zero
318*dfc6aa5cSAndroid Build Coastguard Worker * partial iMCUs at the right and bottom edge of the source image area in this
319*dfc6aa5cSAndroid Build Coastguard Worker * case.
320*dfc6aa5cSAndroid Build Coastguard Worker */
321*dfc6aa5cSAndroid Build Coastguard Worker {
322*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height;
323*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION dst_blk_y, x_crop_blocks, y_crop_blocks;
324*dfc6aa5cSAndroid Build Coastguard Worker int ci, offset_y;
325*dfc6aa5cSAndroid Build Coastguard Worker JBLOCKARRAY src_buffer, dst_buffer;
326*dfc6aa5cSAndroid Build Coastguard Worker jpeg_component_info *compptr;
327*dfc6aa5cSAndroid Build Coastguard Worker
328*dfc6aa5cSAndroid Build Coastguard Worker MCU_cols = srcinfo->output_width /
329*dfc6aa5cSAndroid Build Coastguard Worker (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
330*dfc6aa5cSAndroid Build Coastguard Worker MCU_rows = srcinfo->output_height /
331*dfc6aa5cSAndroid Build Coastguard Worker (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
332*dfc6aa5cSAndroid Build Coastguard Worker
333*dfc6aa5cSAndroid Build Coastguard Worker for (ci = 0; ci < dstinfo->num_components; ci++) {
334*dfc6aa5cSAndroid Build Coastguard Worker compptr = dstinfo->comp_info + ci;
335*dfc6aa5cSAndroid Build Coastguard Worker comp_width = MCU_cols * compptr->h_samp_factor;
336*dfc6aa5cSAndroid Build Coastguard Worker comp_height = MCU_rows * compptr->v_samp_factor;
337*dfc6aa5cSAndroid Build Coastguard Worker x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
338*dfc6aa5cSAndroid Build Coastguard Worker y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
339*dfc6aa5cSAndroid Build Coastguard Worker for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
340*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_y += compptr->v_samp_factor) {
341*dfc6aa5cSAndroid Build Coastguard Worker dst_buffer = (*srcinfo->mem->access_virt_barray)
342*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
343*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->v_samp_factor, TRUE);
344*dfc6aa5cSAndroid Build Coastguard Worker if (dstinfo->_jpeg_height > srcinfo->output_height) {
345*dfc6aa5cSAndroid Build Coastguard Worker if (dst_blk_y < y_crop_blocks ||
346*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_y >= y_crop_blocks + comp_height) {
347*dfc6aa5cSAndroid Build Coastguard Worker for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
348*dfc6aa5cSAndroid Build Coastguard Worker memset(dst_buffer[offset_y], 0,
349*dfc6aa5cSAndroid Build Coastguard Worker compptr->width_in_blocks * sizeof(JBLOCK));
350*dfc6aa5cSAndroid Build Coastguard Worker }
351*dfc6aa5cSAndroid Build Coastguard Worker continue;
352*dfc6aa5cSAndroid Build Coastguard Worker }
353*dfc6aa5cSAndroid Build Coastguard Worker src_buffer = (*srcinfo->mem->access_virt_barray)
354*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, src_coef_arrays[ci],
355*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_y - y_crop_blocks, (JDIMENSION)compptr->v_samp_factor,
356*dfc6aa5cSAndroid Build Coastguard Worker FALSE);
357*dfc6aa5cSAndroid Build Coastguard Worker } else {
358*dfc6aa5cSAndroid Build Coastguard Worker src_buffer = (*srcinfo->mem->access_virt_barray)
359*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, src_coef_arrays[ci],
360*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_y + y_crop_blocks, (JDIMENSION)compptr->v_samp_factor,
361*dfc6aa5cSAndroid Build Coastguard Worker FALSE);
362*dfc6aa5cSAndroid Build Coastguard Worker }
363*dfc6aa5cSAndroid Build Coastguard Worker for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
364*dfc6aa5cSAndroid Build Coastguard Worker if (dstinfo->_jpeg_width > srcinfo->output_width) {
365*dfc6aa5cSAndroid Build Coastguard Worker if (x_crop_blocks > 0) {
366*dfc6aa5cSAndroid Build Coastguard Worker memset(dst_buffer[offset_y], 0, x_crop_blocks * sizeof(JBLOCK));
367*dfc6aa5cSAndroid Build Coastguard Worker }
368*dfc6aa5cSAndroid Build Coastguard Worker jcopy_block_row(src_buffer[offset_y],
369*dfc6aa5cSAndroid Build Coastguard Worker dst_buffer[offset_y] + x_crop_blocks, comp_width);
370*dfc6aa5cSAndroid Build Coastguard Worker if (compptr->width_in_blocks > x_crop_blocks + comp_width) {
371*dfc6aa5cSAndroid Build Coastguard Worker memset(dst_buffer[offset_y] + x_crop_blocks + comp_width, 0,
372*dfc6aa5cSAndroid Build Coastguard Worker (compptr->width_in_blocks - x_crop_blocks - comp_width) *
373*dfc6aa5cSAndroid Build Coastguard Worker sizeof(JBLOCK));
374*dfc6aa5cSAndroid Build Coastguard Worker }
375*dfc6aa5cSAndroid Build Coastguard Worker } else {
376*dfc6aa5cSAndroid Build Coastguard Worker jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
377*dfc6aa5cSAndroid Build Coastguard Worker dst_buffer[offset_y], compptr->width_in_blocks);
378*dfc6aa5cSAndroid Build Coastguard Worker }
379*dfc6aa5cSAndroid Build Coastguard Worker }
380*dfc6aa5cSAndroid Build Coastguard Worker }
381*dfc6aa5cSAndroid Build Coastguard Worker }
382*dfc6aa5cSAndroid Build Coastguard Worker }
383*dfc6aa5cSAndroid Build Coastguard Worker
384*dfc6aa5cSAndroid Build Coastguard Worker
385*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
do_crop_ext_flat(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,JDIMENSION y_crop_offset,jvirt_barray_ptr * src_coef_arrays,jvirt_barray_ptr * dst_coef_arrays)386*dfc6aa5cSAndroid Build Coastguard Worker do_crop_ext_flat(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
387*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
388*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *src_coef_arrays,
389*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *dst_coef_arrays)
390*dfc6aa5cSAndroid Build Coastguard Worker /* Crop. This is only used when no rotate/flip is requested with the crop.
391*dfc6aa5cSAndroid Build Coastguard Worker * Extension: The destination width is larger than the source, and we fill in
392*dfc6aa5cSAndroid Build Coastguard Worker * the expanded region with the DC coefficient of the adjacent block. Note
393*dfc6aa5cSAndroid Build Coastguard Worker * that we also have to fill partial iMCUs at the right and bottom edge of the
394*dfc6aa5cSAndroid Build Coastguard Worker * source image area in this case.
395*dfc6aa5cSAndroid Build Coastguard Worker */
396*dfc6aa5cSAndroid Build Coastguard Worker {
397*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height;
398*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks;
399*dfc6aa5cSAndroid Build Coastguard Worker int ci, offset_y;
400*dfc6aa5cSAndroid Build Coastguard Worker JCOEF dc;
401*dfc6aa5cSAndroid Build Coastguard Worker JBLOCKARRAY src_buffer, dst_buffer;
402*dfc6aa5cSAndroid Build Coastguard Worker jpeg_component_info *compptr;
403*dfc6aa5cSAndroid Build Coastguard Worker
404*dfc6aa5cSAndroid Build Coastguard Worker MCU_cols = srcinfo->output_width /
405*dfc6aa5cSAndroid Build Coastguard Worker (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
406*dfc6aa5cSAndroid Build Coastguard Worker MCU_rows = srcinfo->output_height /
407*dfc6aa5cSAndroid Build Coastguard Worker (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
408*dfc6aa5cSAndroid Build Coastguard Worker
409*dfc6aa5cSAndroid Build Coastguard Worker for (ci = 0; ci < dstinfo->num_components; ci++) {
410*dfc6aa5cSAndroid Build Coastguard Worker compptr = dstinfo->comp_info + ci;
411*dfc6aa5cSAndroid Build Coastguard Worker comp_width = MCU_cols * compptr->h_samp_factor;
412*dfc6aa5cSAndroid Build Coastguard Worker comp_height = MCU_rows * compptr->v_samp_factor;
413*dfc6aa5cSAndroid Build Coastguard Worker x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
414*dfc6aa5cSAndroid Build Coastguard Worker y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
415*dfc6aa5cSAndroid Build Coastguard Worker for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
416*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_y += compptr->v_samp_factor) {
417*dfc6aa5cSAndroid Build Coastguard Worker dst_buffer = (*srcinfo->mem->access_virt_barray)
418*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
419*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->v_samp_factor, TRUE);
420*dfc6aa5cSAndroid Build Coastguard Worker if (dstinfo->_jpeg_height > srcinfo->output_height) {
421*dfc6aa5cSAndroid Build Coastguard Worker if (dst_blk_y < y_crop_blocks ||
422*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_y >= y_crop_blocks + comp_height) {
423*dfc6aa5cSAndroid Build Coastguard Worker for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
424*dfc6aa5cSAndroid Build Coastguard Worker memset(dst_buffer[offset_y], 0,
425*dfc6aa5cSAndroid Build Coastguard Worker compptr->width_in_blocks * sizeof(JBLOCK));
426*dfc6aa5cSAndroid Build Coastguard Worker }
427*dfc6aa5cSAndroid Build Coastguard Worker continue;
428*dfc6aa5cSAndroid Build Coastguard Worker }
429*dfc6aa5cSAndroid Build Coastguard Worker src_buffer = (*srcinfo->mem->access_virt_barray)
430*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, src_coef_arrays[ci],
431*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_y - y_crop_blocks, (JDIMENSION)compptr->v_samp_factor,
432*dfc6aa5cSAndroid Build Coastguard Worker FALSE);
433*dfc6aa5cSAndroid Build Coastguard Worker } else {
434*dfc6aa5cSAndroid Build Coastguard Worker src_buffer = (*srcinfo->mem->access_virt_barray)
435*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, src_coef_arrays[ci],
436*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_y + y_crop_blocks, (JDIMENSION)compptr->v_samp_factor,
437*dfc6aa5cSAndroid Build Coastguard Worker FALSE);
438*dfc6aa5cSAndroid Build Coastguard Worker }
439*dfc6aa5cSAndroid Build Coastguard Worker for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
440*dfc6aa5cSAndroid Build Coastguard Worker if (x_crop_blocks > 0) {
441*dfc6aa5cSAndroid Build Coastguard Worker memset(dst_buffer[offset_y], 0, x_crop_blocks * sizeof(JBLOCK));
442*dfc6aa5cSAndroid Build Coastguard Worker dc = src_buffer[offset_y][0][0];
443*dfc6aa5cSAndroid Build Coastguard Worker for (dst_blk_x = 0; dst_blk_x < x_crop_blocks; dst_blk_x++) {
444*dfc6aa5cSAndroid Build Coastguard Worker dst_buffer[offset_y][dst_blk_x][0] = dc;
445*dfc6aa5cSAndroid Build Coastguard Worker }
446*dfc6aa5cSAndroid Build Coastguard Worker }
447*dfc6aa5cSAndroid Build Coastguard Worker jcopy_block_row(src_buffer[offset_y],
448*dfc6aa5cSAndroid Build Coastguard Worker dst_buffer[offset_y] + x_crop_blocks, comp_width);
449*dfc6aa5cSAndroid Build Coastguard Worker if (compptr->width_in_blocks > x_crop_blocks + comp_width) {
450*dfc6aa5cSAndroid Build Coastguard Worker memset(dst_buffer[offset_y] + x_crop_blocks + comp_width, 0,
451*dfc6aa5cSAndroid Build Coastguard Worker (compptr->width_in_blocks - x_crop_blocks - comp_width) *
452*dfc6aa5cSAndroid Build Coastguard Worker sizeof(JBLOCK));
453*dfc6aa5cSAndroid Build Coastguard Worker dc = src_buffer[offset_y][comp_width - 1][0];
454*dfc6aa5cSAndroid Build Coastguard Worker for (dst_blk_x = x_crop_blocks + comp_width;
455*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_x < compptr->width_in_blocks; dst_blk_x++) {
456*dfc6aa5cSAndroid Build Coastguard Worker dst_buffer[offset_y][dst_blk_x][0] = dc;
457*dfc6aa5cSAndroid Build Coastguard Worker }
458*dfc6aa5cSAndroid Build Coastguard Worker }
459*dfc6aa5cSAndroid Build Coastguard Worker }
460*dfc6aa5cSAndroid Build Coastguard Worker }
461*dfc6aa5cSAndroid Build Coastguard Worker }
462*dfc6aa5cSAndroid Build Coastguard Worker }
463*dfc6aa5cSAndroid Build Coastguard Worker
464*dfc6aa5cSAndroid Build Coastguard Worker
465*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
do_crop_ext_reflect(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,JDIMENSION y_crop_offset,jvirt_barray_ptr * src_coef_arrays,jvirt_barray_ptr * dst_coef_arrays)466*dfc6aa5cSAndroid Build Coastguard Worker do_crop_ext_reflect(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
467*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
468*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *src_coef_arrays,
469*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *dst_coef_arrays)
470*dfc6aa5cSAndroid Build Coastguard Worker /* Crop. This is only used when no rotate/flip is requested with the crop.
471*dfc6aa5cSAndroid Build Coastguard Worker * Extension: The destination width is larger than the source, and we fill in
472*dfc6aa5cSAndroid Build Coastguard Worker * the expanded region with repeated reflections of the source image. Note
473*dfc6aa5cSAndroid Build Coastguard Worker * that we also have to fill partial iMCUs at the right and bottom edge of the
474*dfc6aa5cSAndroid Build Coastguard Worker * source image area in this case.
475*dfc6aa5cSAndroid Build Coastguard Worker */
476*dfc6aa5cSAndroid Build Coastguard Worker {
477*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, src_blk_x;
478*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks;
479*dfc6aa5cSAndroid Build Coastguard Worker int ci, k, offset_y;
480*dfc6aa5cSAndroid Build Coastguard Worker JBLOCKARRAY src_buffer, dst_buffer;
481*dfc6aa5cSAndroid Build Coastguard Worker JBLOCKROW src_row_ptr, dst_row_ptr;
482*dfc6aa5cSAndroid Build Coastguard Worker JCOEFPTR src_ptr, dst_ptr;
483*dfc6aa5cSAndroid Build Coastguard Worker jpeg_component_info *compptr;
484*dfc6aa5cSAndroid Build Coastguard Worker
485*dfc6aa5cSAndroid Build Coastguard Worker MCU_cols = srcinfo->output_width /
486*dfc6aa5cSAndroid Build Coastguard Worker (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
487*dfc6aa5cSAndroid Build Coastguard Worker MCU_rows = srcinfo->output_height /
488*dfc6aa5cSAndroid Build Coastguard Worker (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
489*dfc6aa5cSAndroid Build Coastguard Worker
490*dfc6aa5cSAndroid Build Coastguard Worker for (ci = 0; ci < dstinfo->num_components; ci++) {
491*dfc6aa5cSAndroid Build Coastguard Worker compptr = dstinfo->comp_info + ci;
492*dfc6aa5cSAndroid Build Coastguard Worker comp_width = MCU_cols * compptr->h_samp_factor;
493*dfc6aa5cSAndroid Build Coastguard Worker comp_height = MCU_rows * compptr->v_samp_factor;
494*dfc6aa5cSAndroid Build Coastguard Worker x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
495*dfc6aa5cSAndroid Build Coastguard Worker y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
496*dfc6aa5cSAndroid Build Coastguard Worker for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
497*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_y += compptr->v_samp_factor) {
498*dfc6aa5cSAndroid Build Coastguard Worker dst_buffer = (*srcinfo->mem->access_virt_barray)
499*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
500*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->v_samp_factor, TRUE);
501*dfc6aa5cSAndroid Build Coastguard Worker if (dstinfo->_jpeg_height > srcinfo->output_height) {
502*dfc6aa5cSAndroid Build Coastguard Worker if (dst_blk_y < y_crop_blocks ||
503*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_y >= y_crop_blocks + comp_height) {
504*dfc6aa5cSAndroid Build Coastguard Worker for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
505*dfc6aa5cSAndroid Build Coastguard Worker memset(dst_buffer[offset_y], 0,
506*dfc6aa5cSAndroid Build Coastguard Worker compptr->width_in_blocks * sizeof(JBLOCK));
507*dfc6aa5cSAndroid Build Coastguard Worker }
508*dfc6aa5cSAndroid Build Coastguard Worker continue;
509*dfc6aa5cSAndroid Build Coastguard Worker }
510*dfc6aa5cSAndroid Build Coastguard Worker src_buffer = (*srcinfo->mem->access_virt_barray)
511*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, src_coef_arrays[ci],
512*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_y - y_crop_blocks, (JDIMENSION)compptr->v_samp_factor,
513*dfc6aa5cSAndroid Build Coastguard Worker FALSE);
514*dfc6aa5cSAndroid Build Coastguard Worker } else {
515*dfc6aa5cSAndroid Build Coastguard Worker src_buffer = (*srcinfo->mem->access_virt_barray)
516*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, src_coef_arrays[ci],
517*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_y + y_crop_blocks, (JDIMENSION)compptr->v_samp_factor,
518*dfc6aa5cSAndroid Build Coastguard Worker FALSE);
519*dfc6aa5cSAndroid Build Coastguard Worker }
520*dfc6aa5cSAndroid Build Coastguard Worker for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
521*dfc6aa5cSAndroid Build Coastguard Worker /* Copy source region */
522*dfc6aa5cSAndroid Build Coastguard Worker jcopy_block_row(src_buffer[offset_y],
523*dfc6aa5cSAndroid Build Coastguard Worker dst_buffer[offset_y] + x_crop_blocks, comp_width);
524*dfc6aa5cSAndroid Build Coastguard Worker if (x_crop_blocks > 0) {
525*dfc6aa5cSAndroid Build Coastguard Worker /* Reflect to left */
526*dfc6aa5cSAndroid Build Coastguard Worker dst_row_ptr = dst_buffer[offset_y] + x_crop_blocks;
527*dfc6aa5cSAndroid Build Coastguard Worker for (dst_blk_x = x_crop_blocks; dst_blk_x > 0;) {
528*dfc6aa5cSAndroid Build Coastguard Worker src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */
529*dfc6aa5cSAndroid Build Coastguard Worker for (src_blk_x = comp_width; src_blk_x > 0 && dst_blk_x > 0;
530*dfc6aa5cSAndroid Build Coastguard Worker src_blk_x--, dst_blk_x--) {
531*dfc6aa5cSAndroid Build Coastguard Worker dst_ptr = *(--dst_row_ptr); /* destination goes left */
532*dfc6aa5cSAndroid Build Coastguard Worker src_ptr = *src_row_ptr++; /* source goes right */
533*dfc6aa5cSAndroid Build Coastguard Worker /* This unrolled loop doesn't need to know which row it's on. */
534*dfc6aa5cSAndroid Build Coastguard Worker for (k = 0; k < DCTSIZE2; k += 2) {
535*dfc6aa5cSAndroid Build Coastguard Worker *dst_ptr++ = *src_ptr++; /* copy even column */
536*dfc6aa5cSAndroid Build Coastguard Worker *dst_ptr++ = -(*src_ptr++); /* copy odd column with sign
537*dfc6aa5cSAndroid Build Coastguard Worker change */
538*dfc6aa5cSAndroid Build Coastguard Worker }
539*dfc6aa5cSAndroid Build Coastguard Worker }
540*dfc6aa5cSAndroid Build Coastguard Worker }
541*dfc6aa5cSAndroid Build Coastguard Worker }
542*dfc6aa5cSAndroid Build Coastguard Worker if (compptr->width_in_blocks > x_crop_blocks + comp_width) {
543*dfc6aa5cSAndroid Build Coastguard Worker /* Reflect to right */
544*dfc6aa5cSAndroid Build Coastguard Worker dst_row_ptr = dst_buffer[offset_y] + x_crop_blocks + comp_width;
545*dfc6aa5cSAndroid Build Coastguard Worker for (dst_blk_x = compptr->width_in_blocks - x_crop_blocks - comp_width;
546*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_x > 0;) {
547*dfc6aa5cSAndroid Build Coastguard Worker src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */
548*dfc6aa5cSAndroid Build Coastguard Worker for (src_blk_x = comp_width; src_blk_x > 0 && dst_blk_x > 0;
549*dfc6aa5cSAndroid Build Coastguard Worker src_blk_x--, dst_blk_x--) {
550*dfc6aa5cSAndroid Build Coastguard Worker dst_ptr = *dst_row_ptr++; /* destination goes right */
551*dfc6aa5cSAndroid Build Coastguard Worker src_ptr = *(--src_row_ptr); /* source goes left */
552*dfc6aa5cSAndroid Build Coastguard Worker /* This unrolled loop doesn't need to know which row it's on. */
553*dfc6aa5cSAndroid Build Coastguard Worker for (k = 0; k < DCTSIZE2; k += 2) {
554*dfc6aa5cSAndroid Build Coastguard Worker *dst_ptr++ = *src_ptr++; /* copy even column */
555*dfc6aa5cSAndroid Build Coastguard Worker *dst_ptr++ = -(*src_ptr++); /* copy odd column with sign
556*dfc6aa5cSAndroid Build Coastguard Worker change */
557*dfc6aa5cSAndroid Build Coastguard Worker }
558*dfc6aa5cSAndroid Build Coastguard Worker }
559*dfc6aa5cSAndroid Build Coastguard Worker }
560*dfc6aa5cSAndroid Build Coastguard Worker }
561*dfc6aa5cSAndroid Build Coastguard Worker }
562*dfc6aa5cSAndroid Build Coastguard Worker }
563*dfc6aa5cSAndroid Build Coastguard Worker }
564*dfc6aa5cSAndroid Build Coastguard Worker }
565*dfc6aa5cSAndroid Build Coastguard Worker
566*dfc6aa5cSAndroid Build Coastguard Worker
567*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
do_wipe(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,JDIMENSION y_crop_offset,jvirt_barray_ptr * src_coef_arrays,JDIMENSION drop_width,JDIMENSION drop_height)568*dfc6aa5cSAndroid Build Coastguard Worker do_wipe(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
569*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
570*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *src_coef_arrays,
571*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION drop_width, JDIMENSION drop_height)
572*dfc6aa5cSAndroid Build Coastguard Worker /* Wipe - discard image contents of specified region and fill with zero
573*dfc6aa5cSAndroid Build Coastguard Worker * (neutral gray)
574*dfc6aa5cSAndroid Build Coastguard Worker */
575*dfc6aa5cSAndroid Build Coastguard Worker {
576*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION x_wipe_blocks, wipe_width;
577*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION y_wipe_blocks, wipe_bottom;
578*dfc6aa5cSAndroid Build Coastguard Worker int ci, offset_y;
579*dfc6aa5cSAndroid Build Coastguard Worker JBLOCKARRAY buffer;
580*dfc6aa5cSAndroid Build Coastguard Worker jpeg_component_info *compptr;
581*dfc6aa5cSAndroid Build Coastguard Worker
582*dfc6aa5cSAndroid Build Coastguard Worker for (ci = 0; ci < dstinfo->num_components; ci++) {
583*dfc6aa5cSAndroid Build Coastguard Worker compptr = dstinfo->comp_info + ci;
584*dfc6aa5cSAndroid Build Coastguard Worker x_wipe_blocks = x_crop_offset * compptr->h_samp_factor;
585*dfc6aa5cSAndroid Build Coastguard Worker wipe_width = drop_width * compptr->h_samp_factor;
586*dfc6aa5cSAndroid Build Coastguard Worker y_wipe_blocks = y_crop_offset * compptr->v_samp_factor;
587*dfc6aa5cSAndroid Build Coastguard Worker wipe_bottom = drop_height * compptr->v_samp_factor + y_wipe_blocks;
588*dfc6aa5cSAndroid Build Coastguard Worker for (; y_wipe_blocks < wipe_bottom;
589*dfc6aa5cSAndroid Build Coastguard Worker y_wipe_blocks += compptr->v_samp_factor) {
590*dfc6aa5cSAndroid Build Coastguard Worker buffer = (*srcinfo->mem->access_virt_barray)
591*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, src_coef_arrays[ci], y_wipe_blocks,
592*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->v_samp_factor, TRUE);
593*dfc6aa5cSAndroid Build Coastguard Worker for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
594*dfc6aa5cSAndroid Build Coastguard Worker memset(buffer[offset_y] + x_wipe_blocks, 0,
595*dfc6aa5cSAndroid Build Coastguard Worker wipe_width * sizeof(JBLOCK));
596*dfc6aa5cSAndroid Build Coastguard Worker }
597*dfc6aa5cSAndroid Build Coastguard Worker }
598*dfc6aa5cSAndroid Build Coastguard Worker }
599*dfc6aa5cSAndroid Build Coastguard Worker }
600*dfc6aa5cSAndroid Build Coastguard Worker
601*dfc6aa5cSAndroid Build Coastguard Worker
602*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
do_flatten(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,JDIMENSION y_crop_offset,jvirt_barray_ptr * src_coef_arrays,JDIMENSION drop_width,JDIMENSION drop_height)603*dfc6aa5cSAndroid Build Coastguard Worker do_flatten(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
604*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
605*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *src_coef_arrays,
606*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION drop_width, JDIMENSION drop_height)
607*dfc6aa5cSAndroid Build Coastguard Worker /* Flatten - discard image contents of specified region, similarly to wipe,
608*dfc6aa5cSAndroid Build Coastguard Worker * but fill with the average of adjacent blocks instead of zero.
609*dfc6aa5cSAndroid Build Coastguard Worker */
610*dfc6aa5cSAndroid Build Coastguard Worker {
611*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION x_wipe_blocks, wipe_width, wipe_right;
612*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION y_wipe_blocks, wipe_bottom, blk_x;
613*dfc6aa5cSAndroid Build Coastguard Worker int ci, offset_y, dc_left_value, dc_right_value, average;
614*dfc6aa5cSAndroid Build Coastguard Worker JBLOCKARRAY buffer;
615*dfc6aa5cSAndroid Build Coastguard Worker jpeg_component_info *compptr;
616*dfc6aa5cSAndroid Build Coastguard Worker
617*dfc6aa5cSAndroid Build Coastguard Worker for (ci = 0; ci < dstinfo->num_components; ci++) {
618*dfc6aa5cSAndroid Build Coastguard Worker compptr = dstinfo->comp_info + ci;
619*dfc6aa5cSAndroid Build Coastguard Worker x_wipe_blocks = x_crop_offset * compptr->h_samp_factor;
620*dfc6aa5cSAndroid Build Coastguard Worker wipe_width = drop_width * compptr->h_samp_factor;
621*dfc6aa5cSAndroid Build Coastguard Worker wipe_right = wipe_width + x_wipe_blocks;
622*dfc6aa5cSAndroid Build Coastguard Worker y_wipe_blocks = y_crop_offset * compptr->v_samp_factor;
623*dfc6aa5cSAndroid Build Coastguard Worker wipe_bottom = drop_height * compptr->v_samp_factor + y_wipe_blocks;
624*dfc6aa5cSAndroid Build Coastguard Worker for (; y_wipe_blocks < wipe_bottom;
625*dfc6aa5cSAndroid Build Coastguard Worker y_wipe_blocks += compptr->v_samp_factor) {
626*dfc6aa5cSAndroid Build Coastguard Worker buffer = (*srcinfo->mem->access_virt_barray)
627*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, src_coef_arrays[ci], y_wipe_blocks,
628*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->v_samp_factor, TRUE);
629*dfc6aa5cSAndroid Build Coastguard Worker for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
630*dfc6aa5cSAndroid Build Coastguard Worker memset(buffer[offset_y] + x_wipe_blocks, 0,
631*dfc6aa5cSAndroid Build Coastguard Worker wipe_width * sizeof(JBLOCK));
632*dfc6aa5cSAndroid Build Coastguard Worker if (x_wipe_blocks > 0) {
633*dfc6aa5cSAndroid Build Coastguard Worker dc_left_value = buffer[offset_y][x_wipe_blocks - 1][0];
634*dfc6aa5cSAndroid Build Coastguard Worker if (wipe_right < compptr->width_in_blocks) {
635*dfc6aa5cSAndroid Build Coastguard Worker dc_right_value = buffer[offset_y][wipe_right][0];
636*dfc6aa5cSAndroid Build Coastguard Worker average = (dc_left_value + dc_right_value) >> 1;
637*dfc6aa5cSAndroid Build Coastguard Worker } else {
638*dfc6aa5cSAndroid Build Coastguard Worker average = dc_left_value;
639*dfc6aa5cSAndroid Build Coastguard Worker }
640*dfc6aa5cSAndroid Build Coastguard Worker } else if (wipe_right < compptr->width_in_blocks) {
641*dfc6aa5cSAndroid Build Coastguard Worker average = buffer[offset_y][wipe_right][0];
642*dfc6aa5cSAndroid Build Coastguard Worker } else continue;
643*dfc6aa5cSAndroid Build Coastguard Worker for (blk_x = x_wipe_blocks; blk_x < wipe_right; blk_x++) {
644*dfc6aa5cSAndroid Build Coastguard Worker buffer[offset_y][blk_x][0] = (JCOEF)average;
645*dfc6aa5cSAndroid Build Coastguard Worker }
646*dfc6aa5cSAndroid Build Coastguard Worker }
647*dfc6aa5cSAndroid Build Coastguard Worker }
648*dfc6aa5cSAndroid Build Coastguard Worker }
649*dfc6aa5cSAndroid Build Coastguard Worker }
650*dfc6aa5cSAndroid Build Coastguard Worker
651*dfc6aa5cSAndroid Build Coastguard Worker
652*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
do_reflect(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,jvirt_barray_ptr * src_coef_arrays,JDIMENSION drop_width,JDIMENSION drop_height)653*dfc6aa5cSAndroid Build Coastguard Worker do_reflect(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
654*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION x_crop_offset, jvirt_barray_ptr *src_coef_arrays,
655*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION drop_width, JDIMENSION drop_height)
656*dfc6aa5cSAndroid Build Coastguard Worker /* Reflect - discard image contents of specified region, similarly to wipe,
657*dfc6aa5cSAndroid Build Coastguard Worker * but fill with repeated reflections of the outside region instead of zero.
658*dfc6aa5cSAndroid Build Coastguard Worker * NB: y_crop_offset is assumed to be zero.
659*dfc6aa5cSAndroid Build Coastguard Worker */
660*dfc6aa5cSAndroid Build Coastguard Worker {
661*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION x_wipe_blocks, wipe_width;
662*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION y_wipe_blocks, wipe_bottom;
663*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION src_blk_x, dst_blk_x;
664*dfc6aa5cSAndroid Build Coastguard Worker int ci, k, offset_y;
665*dfc6aa5cSAndroid Build Coastguard Worker JBLOCKARRAY buffer;
666*dfc6aa5cSAndroid Build Coastguard Worker JBLOCKROW src_row_ptr, dst_row_ptr;
667*dfc6aa5cSAndroid Build Coastguard Worker JCOEFPTR src_ptr, dst_ptr;
668*dfc6aa5cSAndroid Build Coastguard Worker jpeg_component_info *compptr;
669*dfc6aa5cSAndroid Build Coastguard Worker
670*dfc6aa5cSAndroid Build Coastguard Worker for (ci = 0; ci < dstinfo->num_components; ci++) {
671*dfc6aa5cSAndroid Build Coastguard Worker compptr = dstinfo->comp_info + ci;
672*dfc6aa5cSAndroid Build Coastguard Worker x_wipe_blocks = x_crop_offset * compptr->h_samp_factor;
673*dfc6aa5cSAndroid Build Coastguard Worker wipe_width = drop_width * compptr->h_samp_factor;
674*dfc6aa5cSAndroid Build Coastguard Worker wipe_bottom = drop_height * compptr->v_samp_factor;
675*dfc6aa5cSAndroid Build Coastguard Worker for (y_wipe_blocks = 0; y_wipe_blocks < wipe_bottom;
676*dfc6aa5cSAndroid Build Coastguard Worker y_wipe_blocks += compptr->v_samp_factor) {
677*dfc6aa5cSAndroid Build Coastguard Worker buffer = (*srcinfo->mem->access_virt_barray)
678*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, src_coef_arrays[ci], y_wipe_blocks,
679*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->v_samp_factor, TRUE);
680*dfc6aa5cSAndroid Build Coastguard Worker for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
681*dfc6aa5cSAndroid Build Coastguard Worker if (x_wipe_blocks > 0) {
682*dfc6aa5cSAndroid Build Coastguard Worker /* Reflect from left */
683*dfc6aa5cSAndroid Build Coastguard Worker dst_row_ptr = buffer[offset_y] + x_wipe_blocks;
684*dfc6aa5cSAndroid Build Coastguard Worker for (dst_blk_x = wipe_width; dst_blk_x > 0;) {
685*dfc6aa5cSAndroid Build Coastguard Worker src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */
686*dfc6aa5cSAndroid Build Coastguard Worker for (src_blk_x = x_wipe_blocks;
687*dfc6aa5cSAndroid Build Coastguard Worker src_blk_x > 0 && dst_blk_x > 0; src_blk_x--, dst_blk_x--) {
688*dfc6aa5cSAndroid Build Coastguard Worker dst_ptr = *dst_row_ptr++; /* destination goes right */
689*dfc6aa5cSAndroid Build Coastguard Worker src_ptr = *(--src_row_ptr); /* source goes left */
690*dfc6aa5cSAndroid Build Coastguard Worker /* this unrolled loop doesn't need to know which row it's on... */
691*dfc6aa5cSAndroid Build Coastguard Worker for (k = 0; k < DCTSIZE2; k += 2) {
692*dfc6aa5cSAndroid Build Coastguard Worker *dst_ptr++ = *src_ptr++; /* copy even column */
693*dfc6aa5cSAndroid Build Coastguard Worker *dst_ptr++ = -(*src_ptr++); /* copy odd column with sign change */
694*dfc6aa5cSAndroid Build Coastguard Worker }
695*dfc6aa5cSAndroid Build Coastguard Worker }
696*dfc6aa5cSAndroid Build Coastguard Worker }
697*dfc6aa5cSAndroid Build Coastguard Worker } else if (compptr->width_in_blocks > x_wipe_blocks + wipe_width) {
698*dfc6aa5cSAndroid Build Coastguard Worker /* Reflect from right */
699*dfc6aa5cSAndroid Build Coastguard Worker dst_row_ptr = buffer[offset_y] + x_wipe_blocks + wipe_width;
700*dfc6aa5cSAndroid Build Coastguard Worker for (dst_blk_x = wipe_width; dst_blk_x > 0;) {
701*dfc6aa5cSAndroid Build Coastguard Worker src_row_ptr = dst_row_ptr; /* (re)set axis of reflection */
702*dfc6aa5cSAndroid Build Coastguard Worker src_blk_x = compptr->width_in_blocks - x_wipe_blocks - wipe_width;
703*dfc6aa5cSAndroid Build Coastguard Worker for (; src_blk_x > 0 && dst_blk_x > 0; src_blk_x--, dst_blk_x--) {
704*dfc6aa5cSAndroid Build Coastguard Worker dst_ptr = *(--dst_row_ptr); /* destination goes left */
705*dfc6aa5cSAndroid Build Coastguard Worker src_ptr = *src_row_ptr++; /* source goes right */
706*dfc6aa5cSAndroid Build Coastguard Worker /* this unrolled loop doesn't need to know which row it's on... */
707*dfc6aa5cSAndroid Build Coastguard Worker for (k = 0; k < DCTSIZE2; k += 2) {
708*dfc6aa5cSAndroid Build Coastguard Worker *dst_ptr++ = *src_ptr++; /* copy even column */
709*dfc6aa5cSAndroid Build Coastguard Worker *dst_ptr++ = -(*src_ptr++); /* copy odd column with sign change */
710*dfc6aa5cSAndroid Build Coastguard Worker }
711*dfc6aa5cSAndroid Build Coastguard Worker }
712*dfc6aa5cSAndroid Build Coastguard Worker }
713*dfc6aa5cSAndroid Build Coastguard Worker } else {
714*dfc6aa5cSAndroid Build Coastguard Worker memset(buffer[offset_y] + x_wipe_blocks, 0,
715*dfc6aa5cSAndroid Build Coastguard Worker wipe_width * sizeof(JBLOCK));
716*dfc6aa5cSAndroid Build Coastguard Worker }
717*dfc6aa5cSAndroid Build Coastguard Worker }
718*dfc6aa5cSAndroid Build Coastguard Worker }
719*dfc6aa5cSAndroid Build Coastguard Worker }
720*dfc6aa5cSAndroid Build Coastguard Worker }
721*dfc6aa5cSAndroid Build Coastguard Worker
722*dfc6aa5cSAndroid Build Coastguard Worker
723*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
do_flip_h_no_crop(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,jvirt_barray_ptr * src_coef_arrays)724*dfc6aa5cSAndroid Build Coastguard Worker do_flip_h_no_crop(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
725*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION x_crop_offset, jvirt_barray_ptr *src_coef_arrays)
726*dfc6aa5cSAndroid Build Coastguard Worker /* Horizontal flip; done in-place, so no separate dest array is required.
727*dfc6aa5cSAndroid Build Coastguard Worker * NB: this only works when y_crop_offset is zero.
728*dfc6aa5cSAndroid Build Coastguard Worker */
729*dfc6aa5cSAndroid Build Coastguard Worker {
730*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION MCU_cols, comp_width, blk_x, blk_y, x_crop_blocks;
731*dfc6aa5cSAndroid Build Coastguard Worker int ci, k, offset_y;
732*dfc6aa5cSAndroid Build Coastguard Worker JBLOCKARRAY buffer;
733*dfc6aa5cSAndroid Build Coastguard Worker JCOEFPTR ptr1, ptr2;
734*dfc6aa5cSAndroid Build Coastguard Worker JCOEF temp1, temp2;
735*dfc6aa5cSAndroid Build Coastguard Worker jpeg_component_info *compptr;
736*dfc6aa5cSAndroid Build Coastguard Worker
737*dfc6aa5cSAndroid Build Coastguard Worker /* Horizontal mirroring of DCT blocks is accomplished by swapping
738*dfc6aa5cSAndroid Build Coastguard Worker * pairs of blocks in-place. Within a DCT block, we perform horizontal
739*dfc6aa5cSAndroid Build Coastguard Worker * mirroring by changing the signs of odd-numbered columns.
740*dfc6aa5cSAndroid Build Coastguard Worker * Partial iMCUs at the right edge are left untouched.
741*dfc6aa5cSAndroid Build Coastguard Worker */
742*dfc6aa5cSAndroid Build Coastguard Worker MCU_cols = srcinfo->output_width /
743*dfc6aa5cSAndroid Build Coastguard Worker (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
744*dfc6aa5cSAndroid Build Coastguard Worker
745*dfc6aa5cSAndroid Build Coastguard Worker for (ci = 0; ci < dstinfo->num_components; ci++) {
746*dfc6aa5cSAndroid Build Coastguard Worker compptr = dstinfo->comp_info + ci;
747*dfc6aa5cSAndroid Build Coastguard Worker comp_width = MCU_cols * compptr->h_samp_factor;
748*dfc6aa5cSAndroid Build Coastguard Worker x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
749*dfc6aa5cSAndroid Build Coastguard Worker for (blk_y = 0; blk_y < compptr->height_in_blocks;
750*dfc6aa5cSAndroid Build Coastguard Worker blk_y += compptr->v_samp_factor) {
751*dfc6aa5cSAndroid Build Coastguard Worker buffer = (*srcinfo->mem->access_virt_barray)
752*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, src_coef_arrays[ci], blk_y,
753*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->v_samp_factor, TRUE);
754*dfc6aa5cSAndroid Build Coastguard Worker for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
755*dfc6aa5cSAndroid Build Coastguard Worker /* Do the mirroring */
756*dfc6aa5cSAndroid Build Coastguard Worker for (blk_x = 0; blk_x * 2 < comp_width; blk_x++) {
757*dfc6aa5cSAndroid Build Coastguard Worker ptr1 = buffer[offset_y][blk_x];
758*dfc6aa5cSAndroid Build Coastguard Worker ptr2 = buffer[offset_y][comp_width - blk_x - 1];
759*dfc6aa5cSAndroid Build Coastguard Worker /* this unrolled loop doesn't need to know which row it's on... */
760*dfc6aa5cSAndroid Build Coastguard Worker for (k = 0; k < DCTSIZE2; k += 2) {
761*dfc6aa5cSAndroid Build Coastguard Worker temp1 = *ptr1; /* swap even column */
762*dfc6aa5cSAndroid Build Coastguard Worker temp2 = *ptr2;
763*dfc6aa5cSAndroid Build Coastguard Worker *ptr1++ = temp2;
764*dfc6aa5cSAndroid Build Coastguard Worker *ptr2++ = temp1;
765*dfc6aa5cSAndroid Build Coastguard Worker temp1 = *ptr1; /* swap odd column with sign change */
766*dfc6aa5cSAndroid Build Coastguard Worker temp2 = *ptr2;
767*dfc6aa5cSAndroid Build Coastguard Worker *ptr1++ = -temp2;
768*dfc6aa5cSAndroid Build Coastguard Worker *ptr2++ = -temp1;
769*dfc6aa5cSAndroid Build Coastguard Worker }
770*dfc6aa5cSAndroid Build Coastguard Worker }
771*dfc6aa5cSAndroid Build Coastguard Worker if (x_crop_blocks > 0) {
772*dfc6aa5cSAndroid Build Coastguard Worker /* Now left-justify the portion of the data to be kept.
773*dfc6aa5cSAndroid Build Coastguard Worker * We can't use a single jcopy_block_row() call because that routine
774*dfc6aa5cSAndroid Build Coastguard Worker * depends on memcpy(), whose behavior is unspecified for overlapping
775*dfc6aa5cSAndroid Build Coastguard Worker * source and destination areas. Sigh.
776*dfc6aa5cSAndroid Build Coastguard Worker */
777*dfc6aa5cSAndroid Build Coastguard Worker for (blk_x = 0; blk_x < compptr->width_in_blocks; blk_x++) {
778*dfc6aa5cSAndroid Build Coastguard Worker jcopy_block_row(buffer[offset_y] + blk_x + x_crop_blocks,
779*dfc6aa5cSAndroid Build Coastguard Worker buffer[offset_y] + blk_x, (JDIMENSION)1);
780*dfc6aa5cSAndroid Build Coastguard Worker }
781*dfc6aa5cSAndroid Build Coastguard Worker }
782*dfc6aa5cSAndroid Build Coastguard Worker }
783*dfc6aa5cSAndroid Build Coastguard Worker }
784*dfc6aa5cSAndroid Build Coastguard Worker }
785*dfc6aa5cSAndroid Build Coastguard Worker }
786*dfc6aa5cSAndroid Build Coastguard Worker
787*dfc6aa5cSAndroid Build Coastguard Worker
788*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
do_flip_h(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,JDIMENSION y_crop_offset,jvirt_barray_ptr * src_coef_arrays,jvirt_barray_ptr * dst_coef_arrays)789*dfc6aa5cSAndroid Build Coastguard Worker do_flip_h(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
790*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
791*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *src_coef_arrays,
792*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *dst_coef_arrays)
793*dfc6aa5cSAndroid Build Coastguard Worker /* Horizontal flip in general cropping case */
794*dfc6aa5cSAndroid Build Coastguard Worker {
795*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
796*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION x_crop_blocks, y_crop_blocks;
797*dfc6aa5cSAndroid Build Coastguard Worker int ci, k, offset_y;
798*dfc6aa5cSAndroid Build Coastguard Worker JBLOCKARRAY src_buffer, dst_buffer;
799*dfc6aa5cSAndroid Build Coastguard Worker JBLOCKROW src_row_ptr, dst_row_ptr;
800*dfc6aa5cSAndroid Build Coastguard Worker JCOEFPTR src_ptr, dst_ptr;
801*dfc6aa5cSAndroid Build Coastguard Worker jpeg_component_info *compptr;
802*dfc6aa5cSAndroid Build Coastguard Worker
803*dfc6aa5cSAndroid Build Coastguard Worker /* Here we must output into a separate array because we can't touch
804*dfc6aa5cSAndroid Build Coastguard Worker * different rows of a single virtual array simultaneously. Otherwise,
805*dfc6aa5cSAndroid Build Coastguard Worker * this is essentially the same as the routine above.
806*dfc6aa5cSAndroid Build Coastguard Worker */
807*dfc6aa5cSAndroid Build Coastguard Worker MCU_cols = srcinfo->output_width /
808*dfc6aa5cSAndroid Build Coastguard Worker (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
809*dfc6aa5cSAndroid Build Coastguard Worker
810*dfc6aa5cSAndroid Build Coastguard Worker for (ci = 0; ci < dstinfo->num_components; ci++) {
811*dfc6aa5cSAndroid Build Coastguard Worker compptr = dstinfo->comp_info + ci;
812*dfc6aa5cSAndroid Build Coastguard Worker comp_width = MCU_cols * compptr->h_samp_factor;
813*dfc6aa5cSAndroid Build Coastguard Worker x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
814*dfc6aa5cSAndroid Build Coastguard Worker y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
815*dfc6aa5cSAndroid Build Coastguard Worker for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
816*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_y += compptr->v_samp_factor) {
817*dfc6aa5cSAndroid Build Coastguard Worker dst_buffer = (*srcinfo->mem->access_virt_barray)
818*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
819*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->v_samp_factor, TRUE);
820*dfc6aa5cSAndroid Build Coastguard Worker src_buffer = (*srcinfo->mem->access_virt_barray)
821*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, src_coef_arrays[ci], dst_blk_y + y_crop_blocks,
822*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->v_samp_factor, FALSE);
823*dfc6aa5cSAndroid Build Coastguard Worker for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
824*dfc6aa5cSAndroid Build Coastguard Worker dst_row_ptr = dst_buffer[offset_y];
825*dfc6aa5cSAndroid Build Coastguard Worker src_row_ptr = src_buffer[offset_y];
826*dfc6aa5cSAndroid Build Coastguard Worker for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
827*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_x++) {
828*dfc6aa5cSAndroid Build Coastguard Worker if (x_crop_blocks + dst_blk_x < comp_width) {
829*dfc6aa5cSAndroid Build Coastguard Worker /* Do the mirrorable blocks */
830*dfc6aa5cSAndroid Build Coastguard Worker dst_ptr = dst_row_ptr[dst_blk_x];
831*dfc6aa5cSAndroid Build Coastguard Worker src_ptr = src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
832*dfc6aa5cSAndroid Build Coastguard Worker /* this unrolled loop doesn't need to know which row it's on... */
833*dfc6aa5cSAndroid Build Coastguard Worker for (k = 0; k < DCTSIZE2; k += 2) {
834*dfc6aa5cSAndroid Build Coastguard Worker *dst_ptr++ = *src_ptr++; /* copy even column */
835*dfc6aa5cSAndroid Build Coastguard Worker *dst_ptr++ = -(*src_ptr++); /* copy odd column with sign
836*dfc6aa5cSAndroid Build Coastguard Worker change */
837*dfc6aa5cSAndroid Build Coastguard Worker }
838*dfc6aa5cSAndroid Build Coastguard Worker } else {
839*dfc6aa5cSAndroid Build Coastguard Worker /* Copy last partial block(s) verbatim */
840*dfc6aa5cSAndroid Build Coastguard Worker jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
841*dfc6aa5cSAndroid Build Coastguard Worker dst_row_ptr + dst_blk_x, (JDIMENSION)1);
842*dfc6aa5cSAndroid Build Coastguard Worker }
843*dfc6aa5cSAndroid Build Coastguard Worker }
844*dfc6aa5cSAndroid Build Coastguard Worker }
845*dfc6aa5cSAndroid Build Coastguard Worker }
846*dfc6aa5cSAndroid Build Coastguard Worker }
847*dfc6aa5cSAndroid Build Coastguard Worker }
848*dfc6aa5cSAndroid Build Coastguard Worker
849*dfc6aa5cSAndroid Build Coastguard Worker
850*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
do_flip_v(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,JDIMENSION y_crop_offset,jvirt_barray_ptr * src_coef_arrays,jvirt_barray_ptr * dst_coef_arrays)851*dfc6aa5cSAndroid Build Coastguard Worker do_flip_v(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
852*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
853*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *src_coef_arrays,
854*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *dst_coef_arrays)
855*dfc6aa5cSAndroid Build Coastguard Worker /* Vertical flip */
856*dfc6aa5cSAndroid Build Coastguard Worker {
857*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
858*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION x_crop_blocks, y_crop_blocks;
859*dfc6aa5cSAndroid Build Coastguard Worker int ci, i, j, offset_y;
860*dfc6aa5cSAndroid Build Coastguard Worker JBLOCKARRAY src_buffer, dst_buffer;
861*dfc6aa5cSAndroid Build Coastguard Worker JBLOCKROW src_row_ptr, dst_row_ptr;
862*dfc6aa5cSAndroid Build Coastguard Worker JCOEFPTR src_ptr, dst_ptr;
863*dfc6aa5cSAndroid Build Coastguard Worker jpeg_component_info *compptr;
864*dfc6aa5cSAndroid Build Coastguard Worker
865*dfc6aa5cSAndroid Build Coastguard Worker /* We output into a separate array because we can't touch different
866*dfc6aa5cSAndroid Build Coastguard Worker * rows of the source virtual array simultaneously. Otherwise, this
867*dfc6aa5cSAndroid Build Coastguard Worker * is a pretty straightforward analog of horizontal flip.
868*dfc6aa5cSAndroid Build Coastguard Worker * Within a DCT block, vertical mirroring is done by changing the signs
869*dfc6aa5cSAndroid Build Coastguard Worker * of odd-numbered rows.
870*dfc6aa5cSAndroid Build Coastguard Worker * Partial iMCUs at the bottom edge are copied verbatim.
871*dfc6aa5cSAndroid Build Coastguard Worker */
872*dfc6aa5cSAndroid Build Coastguard Worker MCU_rows = srcinfo->output_height /
873*dfc6aa5cSAndroid Build Coastguard Worker (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
874*dfc6aa5cSAndroid Build Coastguard Worker
875*dfc6aa5cSAndroid Build Coastguard Worker for (ci = 0; ci < dstinfo->num_components; ci++) {
876*dfc6aa5cSAndroid Build Coastguard Worker compptr = dstinfo->comp_info + ci;
877*dfc6aa5cSAndroid Build Coastguard Worker comp_height = MCU_rows * compptr->v_samp_factor;
878*dfc6aa5cSAndroid Build Coastguard Worker x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
879*dfc6aa5cSAndroid Build Coastguard Worker y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
880*dfc6aa5cSAndroid Build Coastguard Worker for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
881*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_y += compptr->v_samp_factor) {
882*dfc6aa5cSAndroid Build Coastguard Worker dst_buffer = (*srcinfo->mem->access_virt_barray)
883*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
884*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->v_samp_factor, TRUE);
885*dfc6aa5cSAndroid Build Coastguard Worker if (y_crop_blocks + dst_blk_y < comp_height) {
886*dfc6aa5cSAndroid Build Coastguard Worker /* Row is within the mirrorable area. */
887*dfc6aa5cSAndroid Build Coastguard Worker src_buffer = (*srcinfo->mem->access_virt_barray)
888*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, src_coef_arrays[ci],
889*dfc6aa5cSAndroid Build Coastguard Worker comp_height - y_crop_blocks - dst_blk_y -
890*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->v_samp_factor,
891*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->v_samp_factor, FALSE);
892*dfc6aa5cSAndroid Build Coastguard Worker } else {
893*dfc6aa5cSAndroid Build Coastguard Worker /* Bottom-edge blocks will be copied verbatim. */
894*dfc6aa5cSAndroid Build Coastguard Worker src_buffer = (*srcinfo->mem->access_virt_barray)
895*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, src_coef_arrays[ci],
896*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_y + y_crop_blocks,
897*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->v_samp_factor, FALSE);
898*dfc6aa5cSAndroid Build Coastguard Worker }
899*dfc6aa5cSAndroid Build Coastguard Worker for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
900*dfc6aa5cSAndroid Build Coastguard Worker if (y_crop_blocks + dst_blk_y < comp_height) {
901*dfc6aa5cSAndroid Build Coastguard Worker /* Row is within the mirrorable area. */
902*dfc6aa5cSAndroid Build Coastguard Worker dst_row_ptr = dst_buffer[offset_y];
903*dfc6aa5cSAndroid Build Coastguard Worker src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
904*dfc6aa5cSAndroid Build Coastguard Worker src_row_ptr += x_crop_blocks;
905*dfc6aa5cSAndroid Build Coastguard Worker for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
906*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_x++) {
907*dfc6aa5cSAndroid Build Coastguard Worker dst_ptr = dst_row_ptr[dst_blk_x];
908*dfc6aa5cSAndroid Build Coastguard Worker src_ptr = src_row_ptr[dst_blk_x];
909*dfc6aa5cSAndroid Build Coastguard Worker for (i = 0; i < DCTSIZE; i += 2) {
910*dfc6aa5cSAndroid Build Coastguard Worker /* copy even row */
911*dfc6aa5cSAndroid Build Coastguard Worker for (j = 0; j < DCTSIZE; j++)
912*dfc6aa5cSAndroid Build Coastguard Worker *dst_ptr++ = *src_ptr++;
913*dfc6aa5cSAndroid Build Coastguard Worker /* copy odd row with sign change */
914*dfc6aa5cSAndroid Build Coastguard Worker for (j = 0; j < DCTSIZE; j++)
915*dfc6aa5cSAndroid Build Coastguard Worker *dst_ptr++ = -(*src_ptr++);
916*dfc6aa5cSAndroid Build Coastguard Worker }
917*dfc6aa5cSAndroid Build Coastguard Worker }
918*dfc6aa5cSAndroid Build Coastguard Worker } else {
919*dfc6aa5cSAndroid Build Coastguard Worker /* Just copy row verbatim. */
920*dfc6aa5cSAndroid Build Coastguard Worker jcopy_block_row(src_buffer[offset_y] + x_crop_blocks,
921*dfc6aa5cSAndroid Build Coastguard Worker dst_buffer[offset_y], compptr->width_in_blocks);
922*dfc6aa5cSAndroid Build Coastguard Worker }
923*dfc6aa5cSAndroid Build Coastguard Worker }
924*dfc6aa5cSAndroid Build Coastguard Worker }
925*dfc6aa5cSAndroid Build Coastguard Worker }
926*dfc6aa5cSAndroid Build Coastguard Worker }
927*dfc6aa5cSAndroid Build Coastguard Worker
928*dfc6aa5cSAndroid Build Coastguard Worker
929*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
do_transpose(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,JDIMENSION y_crop_offset,jvirt_barray_ptr * src_coef_arrays,jvirt_barray_ptr * dst_coef_arrays)930*dfc6aa5cSAndroid Build Coastguard Worker do_transpose(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
931*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
932*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *src_coef_arrays,
933*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *dst_coef_arrays)
934*dfc6aa5cSAndroid Build Coastguard Worker /* Transpose source into destination */
935*dfc6aa5cSAndroid Build Coastguard Worker {
936*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION dst_blk_x, dst_blk_y, x_crop_blocks, y_crop_blocks;
937*dfc6aa5cSAndroid Build Coastguard Worker int ci, i, j, offset_x, offset_y;
938*dfc6aa5cSAndroid Build Coastguard Worker JBLOCKARRAY src_buffer, dst_buffer;
939*dfc6aa5cSAndroid Build Coastguard Worker JCOEFPTR src_ptr, dst_ptr;
940*dfc6aa5cSAndroid Build Coastguard Worker jpeg_component_info *compptr;
941*dfc6aa5cSAndroid Build Coastguard Worker
942*dfc6aa5cSAndroid Build Coastguard Worker /* Transposing pixels within a block just requires transposing the
943*dfc6aa5cSAndroid Build Coastguard Worker * DCT coefficients.
944*dfc6aa5cSAndroid Build Coastguard Worker * Partial iMCUs at the edges require no special treatment; we simply
945*dfc6aa5cSAndroid Build Coastguard Worker * process all the available DCT blocks for every component.
946*dfc6aa5cSAndroid Build Coastguard Worker */
947*dfc6aa5cSAndroid Build Coastguard Worker for (ci = 0; ci < dstinfo->num_components; ci++) {
948*dfc6aa5cSAndroid Build Coastguard Worker compptr = dstinfo->comp_info + ci;
949*dfc6aa5cSAndroid Build Coastguard Worker x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
950*dfc6aa5cSAndroid Build Coastguard Worker y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
951*dfc6aa5cSAndroid Build Coastguard Worker for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
952*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_y += compptr->v_samp_factor) {
953*dfc6aa5cSAndroid Build Coastguard Worker dst_buffer = (*srcinfo->mem->access_virt_barray)
954*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
955*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->v_samp_factor, TRUE);
956*dfc6aa5cSAndroid Build Coastguard Worker for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
957*dfc6aa5cSAndroid Build Coastguard Worker for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
958*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_x += compptr->h_samp_factor) {
959*dfc6aa5cSAndroid Build Coastguard Worker src_buffer = (*srcinfo->mem->access_virt_barray)
960*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, src_coef_arrays[ci],
961*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_x + x_crop_blocks,
962*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->h_samp_factor, FALSE);
963*dfc6aa5cSAndroid Build Coastguard Worker for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
964*dfc6aa5cSAndroid Build Coastguard Worker dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
965*dfc6aa5cSAndroid Build Coastguard Worker src_ptr =
966*dfc6aa5cSAndroid Build Coastguard Worker src_buffer[offset_x][dst_blk_y + offset_y + y_crop_blocks];
967*dfc6aa5cSAndroid Build Coastguard Worker for (i = 0; i < DCTSIZE; i++)
968*dfc6aa5cSAndroid Build Coastguard Worker for (j = 0; j < DCTSIZE; j++)
969*dfc6aa5cSAndroid Build Coastguard Worker dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
970*dfc6aa5cSAndroid Build Coastguard Worker }
971*dfc6aa5cSAndroid Build Coastguard Worker }
972*dfc6aa5cSAndroid Build Coastguard Worker }
973*dfc6aa5cSAndroid Build Coastguard Worker }
974*dfc6aa5cSAndroid Build Coastguard Worker }
975*dfc6aa5cSAndroid Build Coastguard Worker }
976*dfc6aa5cSAndroid Build Coastguard Worker
977*dfc6aa5cSAndroid Build Coastguard Worker
978*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
do_rot_90(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,JDIMENSION y_crop_offset,jvirt_barray_ptr * src_coef_arrays,jvirt_barray_ptr * dst_coef_arrays)979*dfc6aa5cSAndroid Build Coastguard Worker do_rot_90(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
980*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
981*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *src_coef_arrays,
982*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *dst_coef_arrays)
983*dfc6aa5cSAndroid Build Coastguard Worker /* 90 degree rotation is equivalent to
984*dfc6aa5cSAndroid Build Coastguard Worker * 1. Transposing the image;
985*dfc6aa5cSAndroid Build Coastguard Worker * 2. Horizontal mirroring.
986*dfc6aa5cSAndroid Build Coastguard Worker * These two steps are merged into a single processing routine.
987*dfc6aa5cSAndroid Build Coastguard Worker */
988*dfc6aa5cSAndroid Build Coastguard Worker {
989*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION MCU_cols, comp_width, dst_blk_x, dst_blk_y;
990*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION x_crop_blocks, y_crop_blocks;
991*dfc6aa5cSAndroid Build Coastguard Worker int ci, i, j, offset_x, offset_y;
992*dfc6aa5cSAndroid Build Coastguard Worker JBLOCKARRAY src_buffer, dst_buffer;
993*dfc6aa5cSAndroid Build Coastguard Worker JCOEFPTR src_ptr, dst_ptr;
994*dfc6aa5cSAndroid Build Coastguard Worker jpeg_component_info *compptr;
995*dfc6aa5cSAndroid Build Coastguard Worker
996*dfc6aa5cSAndroid Build Coastguard Worker /* Because of the horizontal mirror step, we can't process partial iMCUs
997*dfc6aa5cSAndroid Build Coastguard Worker * at the (output) right edge properly. They just get transposed and
998*dfc6aa5cSAndroid Build Coastguard Worker * not mirrored.
999*dfc6aa5cSAndroid Build Coastguard Worker */
1000*dfc6aa5cSAndroid Build Coastguard Worker MCU_cols = srcinfo->output_height /
1001*dfc6aa5cSAndroid Build Coastguard Worker (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
1002*dfc6aa5cSAndroid Build Coastguard Worker
1003*dfc6aa5cSAndroid Build Coastguard Worker for (ci = 0; ci < dstinfo->num_components; ci++) {
1004*dfc6aa5cSAndroid Build Coastguard Worker compptr = dstinfo->comp_info + ci;
1005*dfc6aa5cSAndroid Build Coastguard Worker comp_width = MCU_cols * compptr->h_samp_factor;
1006*dfc6aa5cSAndroid Build Coastguard Worker x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
1007*dfc6aa5cSAndroid Build Coastguard Worker y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
1008*dfc6aa5cSAndroid Build Coastguard Worker for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
1009*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_y += compptr->v_samp_factor) {
1010*dfc6aa5cSAndroid Build Coastguard Worker dst_buffer = (*srcinfo->mem->access_virt_barray)
1011*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
1012*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->v_samp_factor, TRUE);
1013*dfc6aa5cSAndroid Build Coastguard Worker for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
1014*dfc6aa5cSAndroid Build Coastguard Worker for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
1015*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_x += compptr->h_samp_factor) {
1016*dfc6aa5cSAndroid Build Coastguard Worker if (x_crop_blocks + dst_blk_x < comp_width) {
1017*dfc6aa5cSAndroid Build Coastguard Worker /* Block is within the mirrorable area. */
1018*dfc6aa5cSAndroid Build Coastguard Worker src_buffer = (*srcinfo->mem->access_virt_barray)
1019*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, src_coef_arrays[ci],
1020*dfc6aa5cSAndroid Build Coastguard Worker comp_width - x_crop_blocks - dst_blk_x -
1021*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->h_samp_factor,
1022*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->h_samp_factor, FALSE);
1023*dfc6aa5cSAndroid Build Coastguard Worker } else {
1024*dfc6aa5cSAndroid Build Coastguard Worker /* Edge blocks are transposed but not mirrored. */
1025*dfc6aa5cSAndroid Build Coastguard Worker src_buffer = (*srcinfo->mem->access_virt_barray)
1026*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, src_coef_arrays[ci],
1027*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_x + x_crop_blocks,
1028*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->h_samp_factor, FALSE);
1029*dfc6aa5cSAndroid Build Coastguard Worker }
1030*dfc6aa5cSAndroid Build Coastguard Worker for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
1031*dfc6aa5cSAndroid Build Coastguard Worker dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
1032*dfc6aa5cSAndroid Build Coastguard Worker if (x_crop_blocks + dst_blk_x < comp_width) {
1033*dfc6aa5cSAndroid Build Coastguard Worker /* Block is within the mirrorable area. */
1034*dfc6aa5cSAndroid Build Coastguard Worker src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
1035*dfc6aa5cSAndroid Build Coastguard Worker [dst_blk_y + offset_y + y_crop_blocks];
1036*dfc6aa5cSAndroid Build Coastguard Worker for (i = 0; i < DCTSIZE; i++) {
1037*dfc6aa5cSAndroid Build Coastguard Worker for (j = 0; j < DCTSIZE; j++)
1038*dfc6aa5cSAndroid Build Coastguard Worker dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1039*dfc6aa5cSAndroid Build Coastguard Worker i++;
1040*dfc6aa5cSAndroid Build Coastguard Worker for (j = 0; j < DCTSIZE; j++)
1041*dfc6aa5cSAndroid Build Coastguard Worker dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
1042*dfc6aa5cSAndroid Build Coastguard Worker }
1043*dfc6aa5cSAndroid Build Coastguard Worker } else {
1044*dfc6aa5cSAndroid Build Coastguard Worker /* Edge blocks are transposed but not mirrored. */
1045*dfc6aa5cSAndroid Build Coastguard Worker src_ptr = src_buffer[offset_x]
1046*dfc6aa5cSAndroid Build Coastguard Worker [dst_blk_y + offset_y + y_crop_blocks];
1047*dfc6aa5cSAndroid Build Coastguard Worker for (i = 0; i < DCTSIZE; i++)
1048*dfc6aa5cSAndroid Build Coastguard Worker for (j = 0; j < DCTSIZE; j++)
1049*dfc6aa5cSAndroid Build Coastguard Worker dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1050*dfc6aa5cSAndroid Build Coastguard Worker }
1051*dfc6aa5cSAndroid Build Coastguard Worker }
1052*dfc6aa5cSAndroid Build Coastguard Worker }
1053*dfc6aa5cSAndroid Build Coastguard Worker }
1054*dfc6aa5cSAndroid Build Coastguard Worker }
1055*dfc6aa5cSAndroid Build Coastguard Worker }
1056*dfc6aa5cSAndroid Build Coastguard Worker }
1057*dfc6aa5cSAndroid Build Coastguard Worker
1058*dfc6aa5cSAndroid Build Coastguard Worker
1059*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
do_rot_270(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,JDIMENSION y_crop_offset,jvirt_barray_ptr * src_coef_arrays,jvirt_barray_ptr * dst_coef_arrays)1060*dfc6aa5cSAndroid Build Coastguard Worker do_rot_270(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
1061*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
1062*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *src_coef_arrays,
1063*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *dst_coef_arrays)
1064*dfc6aa5cSAndroid Build Coastguard Worker /* 270 degree rotation is equivalent to
1065*dfc6aa5cSAndroid Build Coastguard Worker * 1. Horizontal mirroring;
1066*dfc6aa5cSAndroid Build Coastguard Worker * 2. Transposing the image.
1067*dfc6aa5cSAndroid Build Coastguard Worker * These two steps are merged into a single processing routine.
1068*dfc6aa5cSAndroid Build Coastguard Worker */
1069*dfc6aa5cSAndroid Build Coastguard Worker {
1070*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION MCU_rows, comp_height, dst_blk_x, dst_blk_y;
1071*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION x_crop_blocks, y_crop_blocks;
1072*dfc6aa5cSAndroid Build Coastguard Worker int ci, i, j, offset_x, offset_y;
1073*dfc6aa5cSAndroid Build Coastguard Worker JBLOCKARRAY src_buffer, dst_buffer;
1074*dfc6aa5cSAndroid Build Coastguard Worker JCOEFPTR src_ptr, dst_ptr;
1075*dfc6aa5cSAndroid Build Coastguard Worker jpeg_component_info *compptr;
1076*dfc6aa5cSAndroid Build Coastguard Worker
1077*dfc6aa5cSAndroid Build Coastguard Worker /* Because of the horizontal mirror step, we can't process partial iMCUs
1078*dfc6aa5cSAndroid Build Coastguard Worker * at the (output) bottom edge properly. They just get transposed and
1079*dfc6aa5cSAndroid Build Coastguard Worker * not mirrored.
1080*dfc6aa5cSAndroid Build Coastguard Worker */
1081*dfc6aa5cSAndroid Build Coastguard Worker MCU_rows = srcinfo->output_width /
1082*dfc6aa5cSAndroid Build Coastguard Worker (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
1083*dfc6aa5cSAndroid Build Coastguard Worker
1084*dfc6aa5cSAndroid Build Coastguard Worker for (ci = 0; ci < dstinfo->num_components; ci++) {
1085*dfc6aa5cSAndroid Build Coastguard Worker compptr = dstinfo->comp_info + ci;
1086*dfc6aa5cSAndroid Build Coastguard Worker comp_height = MCU_rows * compptr->v_samp_factor;
1087*dfc6aa5cSAndroid Build Coastguard Worker x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
1088*dfc6aa5cSAndroid Build Coastguard Worker y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
1089*dfc6aa5cSAndroid Build Coastguard Worker for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
1090*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_y += compptr->v_samp_factor) {
1091*dfc6aa5cSAndroid Build Coastguard Worker dst_buffer = (*srcinfo->mem->access_virt_barray)
1092*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
1093*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->v_samp_factor, TRUE);
1094*dfc6aa5cSAndroid Build Coastguard Worker for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
1095*dfc6aa5cSAndroid Build Coastguard Worker for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
1096*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_x += compptr->h_samp_factor) {
1097*dfc6aa5cSAndroid Build Coastguard Worker src_buffer = (*srcinfo->mem->access_virt_barray)
1098*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, src_coef_arrays[ci],
1099*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_x + x_crop_blocks,
1100*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->h_samp_factor, FALSE);
1101*dfc6aa5cSAndroid Build Coastguard Worker for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
1102*dfc6aa5cSAndroid Build Coastguard Worker dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
1103*dfc6aa5cSAndroid Build Coastguard Worker if (y_crop_blocks + dst_blk_y < comp_height) {
1104*dfc6aa5cSAndroid Build Coastguard Worker /* Block is within the mirrorable area. */
1105*dfc6aa5cSAndroid Build Coastguard Worker src_ptr = src_buffer[offset_x]
1106*dfc6aa5cSAndroid Build Coastguard Worker [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
1107*dfc6aa5cSAndroid Build Coastguard Worker for (i = 0; i < DCTSIZE; i++) {
1108*dfc6aa5cSAndroid Build Coastguard Worker for (j = 0; j < DCTSIZE; j++) {
1109*dfc6aa5cSAndroid Build Coastguard Worker dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1110*dfc6aa5cSAndroid Build Coastguard Worker j++;
1111*dfc6aa5cSAndroid Build Coastguard Worker dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
1112*dfc6aa5cSAndroid Build Coastguard Worker }
1113*dfc6aa5cSAndroid Build Coastguard Worker }
1114*dfc6aa5cSAndroid Build Coastguard Worker } else {
1115*dfc6aa5cSAndroid Build Coastguard Worker /* Edge blocks are transposed but not mirrored. */
1116*dfc6aa5cSAndroid Build Coastguard Worker src_ptr = src_buffer[offset_x]
1117*dfc6aa5cSAndroid Build Coastguard Worker [dst_blk_y + offset_y + y_crop_blocks];
1118*dfc6aa5cSAndroid Build Coastguard Worker for (i = 0; i < DCTSIZE; i++)
1119*dfc6aa5cSAndroid Build Coastguard Worker for (j = 0; j < DCTSIZE; j++)
1120*dfc6aa5cSAndroid Build Coastguard Worker dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1121*dfc6aa5cSAndroid Build Coastguard Worker }
1122*dfc6aa5cSAndroid Build Coastguard Worker }
1123*dfc6aa5cSAndroid Build Coastguard Worker }
1124*dfc6aa5cSAndroid Build Coastguard Worker }
1125*dfc6aa5cSAndroid Build Coastguard Worker }
1126*dfc6aa5cSAndroid Build Coastguard Worker }
1127*dfc6aa5cSAndroid Build Coastguard Worker }
1128*dfc6aa5cSAndroid Build Coastguard Worker
1129*dfc6aa5cSAndroid Build Coastguard Worker
1130*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
do_rot_180(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,JDIMENSION y_crop_offset,jvirt_barray_ptr * src_coef_arrays,jvirt_barray_ptr * dst_coef_arrays)1131*dfc6aa5cSAndroid Build Coastguard Worker do_rot_180(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
1132*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
1133*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *src_coef_arrays,
1134*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *dst_coef_arrays)
1135*dfc6aa5cSAndroid Build Coastguard Worker /* 180 degree rotation is equivalent to
1136*dfc6aa5cSAndroid Build Coastguard Worker * 1. Vertical mirroring;
1137*dfc6aa5cSAndroid Build Coastguard Worker * 2. Horizontal mirroring.
1138*dfc6aa5cSAndroid Build Coastguard Worker * These two steps are merged into a single processing routine.
1139*dfc6aa5cSAndroid Build Coastguard Worker */
1140*dfc6aa5cSAndroid Build Coastguard Worker {
1141*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
1142*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION x_crop_blocks, y_crop_blocks;
1143*dfc6aa5cSAndroid Build Coastguard Worker int ci, i, j, offset_y;
1144*dfc6aa5cSAndroid Build Coastguard Worker JBLOCKARRAY src_buffer, dst_buffer;
1145*dfc6aa5cSAndroid Build Coastguard Worker JBLOCKROW src_row_ptr, dst_row_ptr;
1146*dfc6aa5cSAndroid Build Coastguard Worker JCOEFPTR src_ptr, dst_ptr;
1147*dfc6aa5cSAndroid Build Coastguard Worker jpeg_component_info *compptr;
1148*dfc6aa5cSAndroid Build Coastguard Worker
1149*dfc6aa5cSAndroid Build Coastguard Worker MCU_cols = srcinfo->output_width /
1150*dfc6aa5cSAndroid Build Coastguard Worker (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
1151*dfc6aa5cSAndroid Build Coastguard Worker MCU_rows = srcinfo->output_height /
1152*dfc6aa5cSAndroid Build Coastguard Worker (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
1153*dfc6aa5cSAndroid Build Coastguard Worker
1154*dfc6aa5cSAndroid Build Coastguard Worker for (ci = 0; ci < dstinfo->num_components; ci++) {
1155*dfc6aa5cSAndroid Build Coastguard Worker compptr = dstinfo->comp_info + ci;
1156*dfc6aa5cSAndroid Build Coastguard Worker comp_width = MCU_cols * compptr->h_samp_factor;
1157*dfc6aa5cSAndroid Build Coastguard Worker comp_height = MCU_rows * compptr->v_samp_factor;
1158*dfc6aa5cSAndroid Build Coastguard Worker x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
1159*dfc6aa5cSAndroid Build Coastguard Worker y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
1160*dfc6aa5cSAndroid Build Coastguard Worker for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
1161*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_y += compptr->v_samp_factor) {
1162*dfc6aa5cSAndroid Build Coastguard Worker dst_buffer = (*srcinfo->mem->access_virt_barray)
1163*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
1164*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->v_samp_factor, TRUE);
1165*dfc6aa5cSAndroid Build Coastguard Worker if (y_crop_blocks + dst_blk_y < comp_height) {
1166*dfc6aa5cSAndroid Build Coastguard Worker /* Row is within the vertically mirrorable area. */
1167*dfc6aa5cSAndroid Build Coastguard Worker src_buffer = (*srcinfo->mem->access_virt_barray)
1168*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, src_coef_arrays[ci],
1169*dfc6aa5cSAndroid Build Coastguard Worker comp_height - y_crop_blocks - dst_blk_y -
1170*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->v_samp_factor,
1171*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->v_samp_factor, FALSE);
1172*dfc6aa5cSAndroid Build Coastguard Worker } else {
1173*dfc6aa5cSAndroid Build Coastguard Worker /* Bottom-edge rows are only mirrored horizontally. */
1174*dfc6aa5cSAndroid Build Coastguard Worker src_buffer = (*srcinfo->mem->access_virt_barray)
1175*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, src_coef_arrays[ci],
1176*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_y + y_crop_blocks,
1177*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->v_samp_factor, FALSE);
1178*dfc6aa5cSAndroid Build Coastguard Worker }
1179*dfc6aa5cSAndroid Build Coastguard Worker for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
1180*dfc6aa5cSAndroid Build Coastguard Worker dst_row_ptr = dst_buffer[offset_y];
1181*dfc6aa5cSAndroid Build Coastguard Worker if (y_crop_blocks + dst_blk_y < comp_height) {
1182*dfc6aa5cSAndroid Build Coastguard Worker /* Row is within the mirrorable area. */
1183*dfc6aa5cSAndroid Build Coastguard Worker src_row_ptr = src_buffer[compptr->v_samp_factor - offset_y - 1];
1184*dfc6aa5cSAndroid Build Coastguard Worker for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
1185*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_x++) {
1186*dfc6aa5cSAndroid Build Coastguard Worker dst_ptr = dst_row_ptr[dst_blk_x];
1187*dfc6aa5cSAndroid Build Coastguard Worker if (x_crop_blocks + dst_blk_x < comp_width) {
1188*dfc6aa5cSAndroid Build Coastguard Worker /* Process the blocks that can be mirrored both ways. */
1189*dfc6aa5cSAndroid Build Coastguard Worker src_ptr =
1190*dfc6aa5cSAndroid Build Coastguard Worker src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
1191*dfc6aa5cSAndroid Build Coastguard Worker for (i = 0; i < DCTSIZE; i += 2) {
1192*dfc6aa5cSAndroid Build Coastguard Worker /* For even row, negate every odd column. */
1193*dfc6aa5cSAndroid Build Coastguard Worker for (j = 0; j < DCTSIZE; j += 2) {
1194*dfc6aa5cSAndroid Build Coastguard Worker *dst_ptr++ = *src_ptr++;
1195*dfc6aa5cSAndroid Build Coastguard Worker *dst_ptr++ = -(*src_ptr++);
1196*dfc6aa5cSAndroid Build Coastguard Worker }
1197*dfc6aa5cSAndroid Build Coastguard Worker /* For odd row, negate every even column. */
1198*dfc6aa5cSAndroid Build Coastguard Worker for (j = 0; j < DCTSIZE; j += 2) {
1199*dfc6aa5cSAndroid Build Coastguard Worker *dst_ptr++ = -(*src_ptr++);
1200*dfc6aa5cSAndroid Build Coastguard Worker *dst_ptr++ = *src_ptr++;
1201*dfc6aa5cSAndroid Build Coastguard Worker }
1202*dfc6aa5cSAndroid Build Coastguard Worker }
1203*dfc6aa5cSAndroid Build Coastguard Worker } else {
1204*dfc6aa5cSAndroid Build Coastguard Worker /* Any remaining right-edge blocks are only mirrored vertically. */
1205*dfc6aa5cSAndroid Build Coastguard Worker src_ptr = src_row_ptr[x_crop_blocks + dst_blk_x];
1206*dfc6aa5cSAndroid Build Coastguard Worker for (i = 0; i < DCTSIZE; i += 2) {
1207*dfc6aa5cSAndroid Build Coastguard Worker for (j = 0; j < DCTSIZE; j++)
1208*dfc6aa5cSAndroid Build Coastguard Worker *dst_ptr++ = *src_ptr++;
1209*dfc6aa5cSAndroid Build Coastguard Worker for (j = 0; j < DCTSIZE; j++)
1210*dfc6aa5cSAndroid Build Coastguard Worker *dst_ptr++ = -(*src_ptr++);
1211*dfc6aa5cSAndroid Build Coastguard Worker }
1212*dfc6aa5cSAndroid Build Coastguard Worker }
1213*dfc6aa5cSAndroid Build Coastguard Worker }
1214*dfc6aa5cSAndroid Build Coastguard Worker } else {
1215*dfc6aa5cSAndroid Build Coastguard Worker /* Remaining rows are just mirrored horizontally. */
1216*dfc6aa5cSAndroid Build Coastguard Worker src_row_ptr = src_buffer[offset_y];
1217*dfc6aa5cSAndroid Build Coastguard Worker for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
1218*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_x++) {
1219*dfc6aa5cSAndroid Build Coastguard Worker if (x_crop_blocks + dst_blk_x < comp_width) {
1220*dfc6aa5cSAndroid Build Coastguard Worker /* Process the blocks that can be mirrored. */
1221*dfc6aa5cSAndroid Build Coastguard Worker dst_ptr = dst_row_ptr[dst_blk_x];
1222*dfc6aa5cSAndroid Build Coastguard Worker src_ptr =
1223*dfc6aa5cSAndroid Build Coastguard Worker src_row_ptr[comp_width - x_crop_blocks - dst_blk_x - 1];
1224*dfc6aa5cSAndroid Build Coastguard Worker for (i = 0; i < DCTSIZE2; i += 2) {
1225*dfc6aa5cSAndroid Build Coastguard Worker *dst_ptr++ = *src_ptr++;
1226*dfc6aa5cSAndroid Build Coastguard Worker *dst_ptr++ = -(*src_ptr++);
1227*dfc6aa5cSAndroid Build Coastguard Worker }
1228*dfc6aa5cSAndroid Build Coastguard Worker } else {
1229*dfc6aa5cSAndroid Build Coastguard Worker /* Any remaining right-edge blocks are only copied. */
1230*dfc6aa5cSAndroid Build Coastguard Worker jcopy_block_row(src_row_ptr + dst_blk_x + x_crop_blocks,
1231*dfc6aa5cSAndroid Build Coastguard Worker dst_row_ptr + dst_blk_x, (JDIMENSION)1);
1232*dfc6aa5cSAndroid Build Coastguard Worker }
1233*dfc6aa5cSAndroid Build Coastguard Worker }
1234*dfc6aa5cSAndroid Build Coastguard Worker }
1235*dfc6aa5cSAndroid Build Coastguard Worker }
1236*dfc6aa5cSAndroid Build Coastguard Worker }
1237*dfc6aa5cSAndroid Build Coastguard Worker }
1238*dfc6aa5cSAndroid Build Coastguard Worker }
1239*dfc6aa5cSAndroid Build Coastguard Worker
1240*dfc6aa5cSAndroid Build Coastguard Worker
1241*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
do_transverse(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JDIMENSION x_crop_offset,JDIMENSION y_crop_offset,jvirt_barray_ptr * src_coef_arrays,jvirt_barray_ptr * dst_coef_arrays)1242*dfc6aa5cSAndroid Build Coastguard Worker do_transverse(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
1243*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION x_crop_offset, JDIMENSION y_crop_offset,
1244*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *src_coef_arrays,
1245*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *dst_coef_arrays)
1246*dfc6aa5cSAndroid Build Coastguard Worker /* Transverse transpose is equivalent to
1247*dfc6aa5cSAndroid Build Coastguard Worker * 1. 180 degree rotation;
1248*dfc6aa5cSAndroid Build Coastguard Worker * 2. Transposition;
1249*dfc6aa5cSAndroid Build Coastguard Worker * or
1250*dfc6aa5cSAndroid Build Coastguard Worker * 1. Horizontal mirroring;
1251*dfc6aa5cSAndroid Build Coastguard Worker * 2. Transposition;
1252*dfc6aa5cSAndroid Build Coastguard Worker * 3. Horizontal mirroring.
1253*dfc6aa5cSAndroid Build Coastguard Worker * These steps are merged into a single processing routine.
1254*dfc6aa5cSAndroid Build Coastguard Worker */
1255*dfc6aa5cSAndroid Build Coastguard Worker {
1256*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION MCU_cols, MCU_rows, comp_width, comp_height, dst_blk_x, dst_blk_y;
1257*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION x_crop_blocks, y_crop_blocks;
1258*dfc6aa5cSAndroid Build Coastguard Worker int ci, i, j, offset_x, offset_y;
1259*dfc6aa5cSAndroid Build Coastguard Worker JBLOCKARRAY src_buffer, dst_buffer;
1260*dfc6aa5cSAndroid Build Coastguard Worker JCOEFPTR src_ptr, dst_ptr;
1261*dfc6aa5cSAndroid Build Coastguard Worker jpeg_component_info *compptr;
1262*dfc6aa5cSAndroid Build Coastguard Worker
1263*dfc6aa5cSAndroid Build Coastguard Worker MCU_cols = srcinfo->output_height /
1264*dfc6aa5cSAndroid Build Coastguard Worker (dstinfo->max_h_samp_factor * dstinfo_min_DCT_h_scaled_size);
1265*dfc6aa5cSAndroid Build Coastguard Worker MCU_rows = srcinfo->output_width /
1266*dfc6aa5cSAndroid Build Coastguard Worker (dstinfo->max_v_samp_factor * dstinfo_min_DCT_v_scaled_size);
1267*dfc6aa5cSAndroid Build Coastguard Worker
1268*dfc6aa5cSAndroid Build Coastguard Worker for (ci = 0; ci < dstinfo->num_components; ci++) {
1269*dfc6aa5cSAndroid Build Coastguard Worker compptr = dstinfo->comp_info + ci;
1270*dfc6aa5cSAndroid Build Coastguard Worker comp_width = MCU_cols * compptr->h_samp_factor;
1271*dfc6aa5cSAndroid Build Coastguard Worker comp_height = MCU_rows * compptr->v_samp_factor;
1272*dfc6aa5cSAndroid Build Coastguard Worker x_crop_blocks = x_crop_offset * compptr->h_samp_factor;
1273*dfc6aa5cSAndroid Build Coastguard Worker y_crop_blocks = y_crop_offset * compptr->v_samp_factor;
1274*dfc6aa5cSAndroid Build Coastguard Worker for (dst_blk_y = 0; dst_blk_y < compptr->height_in_blocks;
1275*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_y += compptr->v_samp_factor) {
1276*dfc6aa5cSAndroid Build Coastguard Worker dst_buffer = (*srcinfo->mem->access_virt_barray)
1277*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, dst_coef_arrays[ci], dst_blk_y,
1278*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->v_samp_factor, TRUE);
1279*dfc6aa5cSAndroid Build Coastguard Worker for (offset_y = 0; offset_y < compptr->v_samp_factor; offset_y++) {
1280*dfc6aa5cSAndroid Build Coastguard Worker for (dst_blk_x = 0; dst_blk_x < compptr->width_in_blocks;
1281*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_x += compptr->h_samp_factor) {
1282*dfc6aa5cSAndroid Build Coastguard Worker if (x_crop_blocks + dst_blk_x < comp_width) {
1283*dfc6aa5cSAndroid Build Coastguard Worker /* Block is within the mirrorable area. */
1284*dfc6aa5cSAndroid Build Coastguard Worker src_buffer = (*srcinfo->mem->access_virt_barray)
1285*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, src_coef_arrays[ci],
1286*dfc6aa5cSAndroid Build Coastguard Worker comp_width - x_crop_blocks - dst_blk_x -
1287*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->h_samp_factor,
1288*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->h_samp_factor, FALSE);
1289*dfc6aa5cSAndroid Build Coastguard Worker } else {
1290*dfc6aa5cSAndroid Build Coastguard Worker src_buffer = (*srcinfo->mem->access_virt_barray)
1291*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, src_coef_arrays[ci],
1292*dfc6aa5cSAndroid Build Coastguard Worker dst_blk_x + x_crop_blocks,
1293*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)compptr->h_samp_factor, FALSE);
1294*dfc6aa5cSAndroid Build Coastguard Worker }
1295*dfc6aa5cSAndroid Build Coastguard Worker for (offset_x = 0; offset_x < compptr->h_samp_factor; offset_x++) {
1296*dfc6aa5cSAndroid Build Coastguard Worker dst_ptr = dst_buffer[offset_y][dst_blk_x + offset_x];
1297*dfc6aa5cSAndroid Build Coastguard Worker if (y_crop_blocks + dst_blk_y < comp_height) {
1298*dfc6aa5cSAndroid Build Coastguard Worker if (x_crop_blocks + dst_blk_x < comp_width) {
1299*dfc6aa5cSAndroid Build Coastguard Worker /* Block is within the mirrorable area. */
1300*dfc6aa5cSAndroid Build Coastguard Worker src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
1301*dfc6aa5cSAndroid Build Coastguard Worker [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
1302*dfc6aa5cSAndroid Build Coastguard Worker for (i = 0; i < DCTSIZE; i++) {
1303*dfc6aa5cSAndroid Build Coastguard Worker for (j = 0; j < DCTSIZE; j++) {
1304*dfc6aa5cSAndroid Build Coastguard Worker dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1305*dfc6aa5cSAndroid Build Coastguard Worker j++;
1306*dfc6aa5cSAndroid Build Coastguard Worker dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
1307*dfc6aa5cSAndroid Build Coastguard Worker }
1308*dfc6aa5cSAndroid Build Coastguard Worker i++;
1309*dfc6aa5cSAndroid Build Coastguard Worker for (j = 0; j < DCTSIZE; j++) {
1310*dfc6aa5cSAndroid Build Coastguard Worker dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
1311*dfc6aa5cSAndroid Build Coastguard Worker j++;
1312*dfc6aa5cSAndroid Build Coastguard Worker dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1313*dfc6aa5cSAndroid Build Coastguard Worker }
1314*dfc6aa5cSAndroid Build Coastguard Worker }
1315*dfc6aa5cSAndroid Build Coastguard Worker } else {
1316*dfc6aa5cSAndroid Build Coastguard Worker /* Right-edge blocks are mirrored in y only */
1317*dfc6aa5cSAndroid Build Coastguard Worker src_ptr = src_buffer[offset_x]
1318*dfc6aa5cSAndroid Build Coastguard Worker [comp_height - y_crop_blocks - dst_blk_y - offset_y - 1];
1319*dfc6aa5cSAndroid Build Coastguard Worker for (i = 0; i < DCTSIZE; i++) {
1320*dfc6aa5cSAndroid Build Coastguard Worker for (j = 0; j < DCTSIZE; j++) {
1321*dfc6aa5cSAndroid Build Coastguard Worker dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1322*dfc6aa5cSAndroid Build Coastguard Worker j++;
1323*dfc6aa5cSAndroid Build Coastguard Worker dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
1324*dfc6aa5cSAndroid Build Coastguard Worker }
1325*dfc6aa5cSAndroid Build Coastguard Worker }
1326*dfc6aa5cSAndroid Build Coastguard Worker }
1327*dfc6aa5cSAndroid Build Coastguard Worker } else {
1328*dfc6aa5cSAndroid Build Coastguard Worker if (x_crop_blocks + dst_blk_x < comp_width) {
1329*dfc6aa5cSAndroid Build Coastguard Worker /* Bottom-edge blocks are mirrored in x only */
1330*dfc6aa5cSAndroid Build Coastguard Worker src_ptr = src_buffer[compptr->h_samp_factor - offset_x - 1]
1331*dfc6aa5cSAndroid Build Coastguard Worker [dst_blk_y + offset_y + y_crop_blocks];
1332*dfc6aa5cSAndroid Build Coastguard Worker for (i = 0; i < DCTSIZE; i++) {
1333*dfc6aa5cSAndroid Build Coastguard Worker for (j = 0; j < DCTSIZE; j++)
1334*dfc6aa5cSAndroid Build Coastguard Worker dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1335*dfc6aa5cSAndroid Build Coastguard Worker i++;
1336*dfc6aa5cSAndroid Build Coastguard Worker for (j = 0; j < DCTSIZE; j++)
1337*dfc6aa5cSAndroid Build Coastguard Worker dst_ptr[j * DCTSIZE + i] = -src_ptr[i * DCTSIZE + j];
1338*dfc6aa5cSAndroid Build Coastguard Worker }
1339*dfc6aa5cSAndroid Build Coastguard Worker } else {
1340*dfc6aa5cSAndroid Build Coastguard Worker /* At lower right corner, just transpose, no mirroring */
1341*dfc6aa5cSAndroid Build Coastguard Worker src_ptr = src_buffer[offset_x]
1342*dfc6aa5cSAndroid Build Coastguard Worker [dst_blk_y + offset_y + y_crop_blocks];
1343*dfc6aa5cSAndroid Build Coastguard Worker for (i = 0; i < DCTSIZE; i++)
1344*dfc6aa5cSAndroid Build Coastguard Worker for (j = 0; j < DCTSIZE; j++)
1345*dfc6aa5cSAndroid Build Coastguard Worker dst_ptr[j * DCTSIZE + i] = src_ptr[i * DCTSIZE + j];
1346*dfc6aa5cSAndroid Build Coastguard Worker }
1347*dfc6aa5cSAndroid Build Coastguard Worker }
1348*dfc6aa5cSAndroid Build Coastguard Worker }
1349*dfc6aa5cSAndroid Build Coastguard Worker }
1350*dfc6aa5cSAndroid Build Coastguard Worker }
1351*dfc6aa5cSAndroid Build Coastguard Worker }
1352*dfc6aa5cSAndroid Build Coastguard Worker }
1353*dfc6aa5cSAndroid Build Coastguard Worker }
1354*dfc6aa5cSAndroid Build Coastguard Worker
1355*dfc6aa5cSAndroid Build Coastguard Worker
1356*dfc6aa5cSAndroid Build Coastguard Worker /* Parse an unsigned integer: subroutine for jtransform_parse_crop_spec.
1357*dfc6aa5cSAndroid Build Coastguard Worker * Returns TRUE if valid integer found, FALSE if not.
1358*dfc6aa5cSAndroid Build Coastguard Worker * *strptr is advanced over the digit string, and *result is set to its value.
1359*dfc6aa5cSAndroid Build Coastguard Worker */
1360*dfc6aa5cSAndroid Build Coastguard Worker
1361*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(boolean)
jt_read_integer(const char ** strptr,JDIMENSION * result)1362*dfc6aa5cSAndroid Build Coastguard Worker jt_read_integer(const char **strptr, JDIMENSION *result)
1363*dfc6aa5cSAndroid Build Coastguard Worker {
1364*dfc6aa5cSAndroid Build Coastguard Worker const char *ptr = *strptr;
1365*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION val = 0;
1366*dfc6aa5cSAndroid Build Coastguard Worker
1367*dfc6aa5cSAndroid Build Coastguard Worker for (; isdigit(*ptr); ptr++) {
1368*dfc6aa5cSAndroid Build Coastguard Worker val = val * 10 + (JDIMENSION)(*ptr - '0');
1369*dfc6aa5cSAndroid Build Coastguard Worker }
1370*dfc6aa5cSAndroid Build Coastguard Worker *result = val;
1371*dfc6aa5cSAndroid Build Coastguard Worker if (ptr == *strptr)
1372*dfc6aa5cSAndroid Build Coastguard Worker return FALSE; /* oops, no digits */
1373*dfc6aa5cSAndroid Build Coastguard Worker *strptr = ptr;
1374*dfc6aa5cSAndroid Build Coastguard Worker return TRUE;
1375*dfc6aa5cSAndroid Build Coastguard Worker }
1376*dfc6aa5cSAndroid Build Coastguard Worker
1377*dfc6aa5cSAndroid Build Coastguard Worker
1378*dfc6aa5cSAndroid Build Coastguard Worker /* Parse a crop specification (written in X11 geometry style).
1379*dfc6aa5cSAndroid Build Coastguard Worker * The routine returns TRUE if the spec string is valid, FALSE if not.
1380*dfc6aa5cSAndroid Build Coastguard Worker *
1381*dfc6aa5cSAndroid Build Coastguard Worker * The crop spec string should have the format
1382*dfc6aa5cSAndroid Build Coastguard Worker * <width>[{fr}]x<height>[{fr}]{+-}<xoffset>{+-}<yoffset>
1383*dfc6aa5cSAndroid Build Coastguard Worker * where width, height, xoffset, and yoffset are unsigned integers.
1384*dfc6aa5cSAndroid Build Coastguard Worker * Each of the elements can be omitted to indicate a default value.
1385*dfc6aa5cSAndroid Build Coastguard Worker * (A weakness of this style is that it is not possible to omit xoffset
1386*dfc6aa5cSAndroid Build Coastguard Worker * while specifying yoffset, since they look alike.)
1387*dfc6aa5cSAndroid Build Coastguard Worker *
1388*dfc6aa5cSAndroid Build Coastguard Worker * This code is loosely based on XParseGeometry from the X11 distribution.
1389*dfc6aa5cSAndroid Build Coastguard Worker */
1390*dfc6aa5cSAndroid Build Coastguard Worker
1391*dfc6aa5cSAndroid Build Coastguard Worker GLOBAL(boolean)
jtransform_parse_crop_spec(jpeg_transform_info * info,const char * spec)1392*dfc6aa5cSAndroid Build Coastguard Worker jtransform_parse_crop_spec(jpeg_transform_info *info, const char *spec)
1393*dfc6aa5cSAndroid Build Coastguard Worker {
1394*dfc6aa5cSAndroid Build Coastguard Worker info->crop = FALSE;
1395*dfc6aa5cSAndroid Build Coastguard Worker info->crop_width_set = JCROP_UNSET;
1396*dfc6aa5cSAndroid Build Coastguard Worker info->crop_height_set = JCROP_UNSET;
1397*dfc6aa5cSAndroid Build Coastguard Worker info->crop_xoffset_set = JCROP_UNSET;
1398*dfc6aa5cSAndroid Build Coastguard Worker info->crop_yoffset_set = JCROP_UNSET;
1399*dfc6aa5cSAndroid Build Coastguard Worker
1400*dfc6aa5cSAndroid Build Coastguard Worker if (isdigit(*spec)) {
1401*dfc6aa5cSAndroid Build Coastguard Worker /* fetch width */
1402*dfc6aa5cSAndroid Build Coastguard Worker if (!jt_read_integer(&spec, &info->crop_width))
1403*dfc6aa5cSAndroid Build Coastguard Worker return FALSE;
1404*dfc6aa5cSAndroid Build Coastguard Worker if (*spec == 'f' || *spec == 'F') {
1405*dfc6aa5cSAndroid Build Coastguard Worker spec++;
1406*dfc6aa5cSAndroid Build Coastguard Worker info->crop_width_set = JCROP_FORCE;
1407*dfc6aa5cSAndroid Build Coastguard Worker } else if (*spec == 'r' || *spec == 'R') {
1408*dfc6aa5cSAndroid Build Coastguard Worker spec++;
1409*dfc6aa5cSAndroid Build Coastguard Worker info->crop_width_set = JCROP_REFLECT;
1410*dfc6aa5cSAndroid Build Coastguard Worker } else
1411*dfc6aa5cSAndroid Build Coastguard Worker info->crop_width_set = JCROP_POS;
1412*dfc6aa5cSAndroid Build Coastguard Worker }
1413*dfc6aa5cSAndroid Build Coastguard Worker if (*spec == 'x' || *spec == 'X') {
1414*dfc6aa5cSAndroid Build Coastguard Worker /* fetch height */
1415*dfc6aa5cSAndroid Build Coastguard Worker spec++;
1416*dfc6aa5cSAndroid Build Coastguard Worker if (!jt_read_integer(&spec, &info->crop_height))
1417*dfc6aa5cSAndroid Build Coastguard Worker return FALSE;
1418*dfc6aa5cSAndroid Build Coastguard Worker if (*spec == 'f' || *spec == 'F') {
1419*dfc6aa5cSAndroid Build Coastguard Worker spec++;
1420*dfc6aa5cSAndroid Build Coastguard Worker info->crop_height_set = JCROP_FORCE;
1421*dfc6aa5cSAndroid Build Coastguard Worker } else if (*spec == 'r' || *spec == 'R') {
1422*dfc6aa5cSAndroid Build Coastguard Worker spec++;
1423*dfc6aa5cSAndroid Build Coastguard Worker info->crop_height_set = JCROP_REFLECT;
1424*dfc6aa5cSAndroid Build Coastguard Worker } else
1425*dfc6aa5cSAndroid Build Coastguard Worker info->crop_height_set = JCROP_POS;
1426*dfc6aa5cSAndroid Build Coastguard Worker }
1427*dfc6aa5cSAndroid Build Coastguard Worker if (*spec == '+' || *spec == '-') {
1428*dfc6aa5cSAndroid Build Coastguard Worker /* fetch xoffset */
1429*dfc6aa5cSAndroid Build Coastguard Worker info->crop_xoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
1430*dfc6aa5cSAndroid Build Coastguard Worker spec++;
1431*dfc6aa5cSAndroid Build Coastguard Worker if (!jt_read_integer(&spec, &info->crop_xoffset))
1432*dfc6aa5cSAndroid Build Coastguard Worker return FALSE;
1433*dfc6aa5cSAndroid Build Coastguard Worker }
1434*dfc6aa5cSAndroid Build Coastguard Worker if (*spec == '+' || *spec == '-') {
1435*dfc6aa5cSAndroid Build Coastguard Worker /* fetch yoffset */
1436*dfc6aa5cSAndroid Build Coastguard Worker info->crop_yoffset_set = (*spec == '-') ? JCROP_NEG : JCROP_POS;
1437*dfc6aa5cSAndroid Build Coastguard Worker spec++;
1438*dfc6aa5cSAndroid Build Coastguard Worker if (!jt_read_integer(&spec, &info->crop_yoffset))
1439*dfc6aa5cSAndroid Build Coastguard Worker return FALSE;
1440*dfc6aa5cSAndroid Build Coastguard Worker }
1441*dfc6aa5cSAndroid Build Coastguard Worker /* We had better have gotten to the end of the string. */
1442*dfc6aa5cSAndroid Build Coastguard Worker if (*spec != '\0')
1443*dfc6aa5cSAndroid Build Coastguard Worker return FALSE;
1444*dfc6aa5cSAndroid Build Coastguard Worker info->crop = TRUE;
1445*dfc6aa5cSAndroid Build Coastguard Worker return TRUE;
1446*dfc6aa5cSAndroid Build Coastguard Worker }
1447*dfc6aa5cSAndroid Build Coastguard Worker
1448*dfc6aa5cSAndroid Build Coastguard Worker
1449*dfc6aa5cSAndroid Build Coastguard Worker /* Trim off any partial iMCUs on the indicated destination edge */
1450*dfc6aa5cSAndroid Build Coastguard Worker
1451*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
trim_right_edge(jpeg_transform_info * info,JDIMENSION full_width)1452*dfc6aa5cSAndroid Build Coastguard Worker trim_right_edge(jpeg_transform_info *info, JDIMENSION full_width)
1453*dfc6aa5cSAndroid Build Coastguard Worker {
1454*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION MCU_cols;
1455*dfc6aa5cSAndroid Build Coastguard Worker
1456*dfc6aa5cSAndroid Build Coastguard Worker MCU_cols = info->output_width / info->iMCU_sample_width;
1457*dfc6aa5cSAndroid Build Coastguard Worker if (MCU_cols > 0 && info->x_crop_offset + MCU_cols ==
1458*dfc6aa5cSAndroid Build Coastguard Worker full_width / info->iMCU_sample_width)
1459*dfc6aa5cSAndroid Build Coastguard Worker info->output_width = MCU_cols * info->iMCU_sample_width;
1460*dfc6aa5cSAndroid Build Coastguard Worker }
1461*dfc6aa5cSAndroid Build Coastguard Worker
1462*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
trim_bottom_edge(jpeg_transform_info * info,JDIMENSION full_height)1463*dfc6aa5cSAndroid Build Coastguard Worker trim_bottom_edge(jpeg_transform_info *info, JDIMENSION full_height)
1464*dfc6aa5cSAndroid Build Coastguard Worker {
1465*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION MCU_rows;
1466*dfc6aa5cSAndroid Build Coastguard Worker
1467*dfc6aa5cSAndroid Build Coastguard Worker MCU_rows = info->output_height / info->iMCU_sample_height;
1468*dfc6aa5cSAndroid Build Coastguard Worker if (MCU_rows > 0 && info->y_crop_offset + MCU_rows ==
1469*dfc6aa5cSAndroid Build Coastguard Worker full_height / info->iMCU_sample_height)
1470*dfc6aa5cSAndroid Build Coastguard Worker info->output_height = MCU_rows * info->iMCU_sample_height;
1471*dfc6aa5cSAndroid Build Coastguard Worker }
1472*dfc6aa5cSAndroid Build Coastguard Worker
1473*dfc6aa5cSAndroid Build Coastguard Worker
1474*dfc6aa5cSAndroid Build Coastguard Worker /* Request any required workspace.
1475*dfc6aa5cSAndroid Build Coastguard Worker *
1476*dfc6aa5cSAndroid Build Coastguard Worker * This routine figures out the size that the output image will be
1477*dfc6aa5cSAndroid Build Coastguard Worker * (which implies that all the transform parameters must be set before
1478*dfc6aa5cSAndroid Build Coastguard Worker * it is called).
1479*dfc6aa5cSAndroid Build Coastguard Worker *
1480*dfc6aa5cSAndroid Build Coastguard Worker * We allocate the workspace virtual arrays from the source decompression
1481*dfc6aa5cSAndroid Build Coastguard Worker * object, so that all the arrays (both the original data and the workspace)
1482*dfc6aa5cSAndroid Build Coastguard Worker * will be taken into account while making memory management decisions.
1483*dfc6aa5cSAndroid Build Coastguard Worker * Hence, this routine must be called after jpeg_read_header (which reads
1484*dfc6aa5cSAndroid Build Coastguard Worker * the image dimensions) and before jpeg_read_coefficients (which realizes
1485*dfc6aa5cSAndroid Build Coastguard Worker * the source's virtual arrays).
1486*dfc6aa5cSAndroid Build Coastguard Worker *
1487*dfc6aa5cSAndroid Build Coastguard Worker * This function returns FALSE right away if -perfect is given
1488*dfc6aa5cSAndroid Build Coastguard Worker * and transformation is not perfect. Otherwise returns TRUE.
1489*dfc6aa5cSAndroid Build Coastguard Worker */
1490*dfc6aa5cSAndroid Build Coastguard Worker
1491*dfc6aa5cSAndroid Build Coastguard Worker GLOBAL(boolean)
jtransform_request_workspace(j_decompress_ptr srcinfo,jpeg_transform_info * info)1492*dfc6aa5cSAndroid Build Coastguard Worker jtransform_request_workspace(j_decompress_ptr srcinfo,
1493*dfc6aa5cSAndroid Build Coastguard Worker jpeg_transform_info *info)
1494*dfc6aa5cSAndroid Build Coastguard Worker {
1495*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *coef_arrays;
1496*dfc6aa5cSAndroid Build Coastguard Worker boolean need_workspace, transpose_it;
1497*dfc6aa5cSAndroid Build Coastguard Worker jpeg_component_info *compptr;
1498*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION xoffset, yoffset, dtemp;
1499*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION width_in_iMCUs, height_in_iMCUs;
1500*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION width_in_blocks, height_in_blocks;
1501*dfc6aa5cSAndroid Build Coastguard Worker int itemp, ci, h_samp_factor, v_samp_factor;
1502*dfc6aa5cSAndroid Build Coastguard Worker
1503*dfc6aa5cSAndroid Build Coastguard Worker /* Determine number of components in output image */
1504*dfc6aa5cSAndroid Build Coastguard Worker if (info->force_grayscale &&
1505*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->jpeg_color_space == JCS_YCbCr &&
1506*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->num_components == 3)
1507*dfc6aa5cSAndroid Build Coastguard Worker /* We'll only process the first component */
1508*dfc6aa5cSAndroid Build Coastguard Worker info->num_components = 1;
1509*dfc6aa5cSAndroid Build Coastguard Worker else
1510*dfc6aa5cSAndroid Build Coastguard Worker /* Process all the components */
1511*dfc6aa5cSAndroid Build Coastguard Worker info->num_components = srcinfo->num_components;
1512*dfc6aa5cSAndroid Build Coastguard Worker
1513*dfc6aa5cSAndroid Build Coastguard Worker /* Compute output image dimensions and related values. */
1514*dfc6aa5cSAndroid Build Coastguard Worker #if JPEG_LIB_VERSION >= 80
1515*dfc6aa5cSAndroid Build Coastguard Worker jpeg_core_output_dimensions(srcinfo);
1516*dfc6aa5cSAndroid Build Coastguard Worker #else
1517*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->output_width = srcinfo->image_width;
1518*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->output_height = srcinfo->image_height;
1519*dfc6aa5cSAndroid Build Coastguard Worker #endif
1520*dfc6aa5cSAndroid Build Coastguard Worker
1521*dfc6aa5cSAndroid Build Coastguard Worker /* Return right away if -perfect is given and transformation is not perfect.
1522*dfc6aa5cSAndroid Build Coastguard Worker */
1523*dfc6aa5cSAndroid Build Coastguard Worker if (info->perfect) {
1524*dfc6aa5cSAndroid Build Coastguard Worker if (info->num_components == 1) {
1525*dfc6aa5cSAndroid Build Coastguard Worker if (!jtransform_perfect_transform(srcinfo->output_width,
1526*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->output_height,
1527*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->_min_DCT_h_scaled_size,
1528*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->_min_DCT_v_scaled_size,
1529*dfc6aa5cSAndroid Build Coastguard Worker info->transform))
1530*dfc6aa5cSAndroid Build Coastguard Worker return FALSE;
1531*dfc6aa5cSAndroid Build Coastguard Worker } else {
1532*dfc6aa5cSAndroid Build Coastguard Worker if (!jtransform_perfect_transform(srcinfo->output_width,
1533*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->output_height,
1534*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size,
1535*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size,
1536*dfc6aa5cSAndroid Build Coastguard Worker info->transform))
1537*dfc6aa5cSAndroid Build Coastguard Worker return FALSE;
1538*dfc6aa5cSAndroid Build Coastguard Worker }
1539*dfc6aa5cSAndroid Build Coastguard Worker }
1540*dfc6aa5cSAndroid Build Coastguard Worker
1541*dfc6aa5cSAndroid Build Coastguard Worker /* If there is only one output component, force the iMCU size to be 1;
1542*dfc6aa5cSAndroid Build Coastguard Worker * else use the source iMCU size. (This allows us to do the right thing
1543*dfc6aa5cSAndroid Build Coastguard Worker * when reducing color to grayscale, and also provides a handy way of
1544*dfc6aa5cSAndroid Build Coastguard Worker * cleaning up "funny" grayscale images whose sampling factors are not 1x1.)
1545*dfc6aa5cSAndroid Build Coastguard Worker */
1546*dfc6aa5cSAndroid Build Coastguard Worker switch (info->transform) {
1547*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_TRANSPOSE:
1548*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_TRANSVERSE:
1549*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_ROT_90:
1550*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_ROT_270:
1551*dfc6aa5cSAndroid Build Coastguard Worker info->output_width = srcinfo->output_height;
1552*dfc6aa5cSAndroid Build Coastguard Worker info->output_height = srcinfo->output_width;
1553*dfc6aa5cSAndroid Build Coastguard Worker if (info->num_components == 1) {
1554*dfc6aa5cSAndroid Build Coastguard Worker info->iMCU_sample_width = srcinfo->_min_DCT_v_scaled_size;
1555*dfc6aa5cSAndroid Build Coastguard Worker info->iMCU_sample_height = srcinfo->_min_DCT_h_scaled_size;
1556*dfc6aa5cSAndroid Build Coastguard Worker } else {
1557*dfc6aa5cSAndroid Build Coastguard Worker info->iMCU_sample_width =
1558*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size;
1559*dfc6aa5cSAndroid Build Coastguard Worker info->iMCU_sample_height =
1560*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size;
1561*dfc6aa5cSAndroid Build Coastguard Worker }
1562*dfc6aa5cSAndroid Build Coastguard Worker break;
1563*dfc6aa5cSAndroid Build Coastguard Worker default:
1564*dfc6aa5cSAndroid Build Coastguard Worker info->output_width = srcinfo->output_width;
1565*dfc6aa5cSAndroid Build Coastguard Worker info->output_height = srcinfo->output_height;
1566*dfc6aa5cSAndroid Build Coastguard Worker if (info->num_components == 1) {
1567*dfc6aa5cSAndroid Build Coastguard Worker info->iMCU_sample_width = srcinfo->_min_DCT_h_scaled_size;
1568*dfc6aa5cSAndroid Build Coastguard Worker info->iMCU_sample_height = srcinfo->_min_DCT_v_scaled_size;
1569*dfc6aa5cSAndroid Build Coastguard Worker } else {
1570*dfc6aa5cSAndroid Build Coastguard Worker info->iMCU_sample_width =
1571*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->max_h_samp_factor * srcinfo->_min_DCT_h_scaled_size;
1572*dfc6aa5cSAndroid Build Coastguard Worker info->iMCU_sample_height =
1573*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->max_v_samp_factor * srcinfo->_min_DCT_v_scaled_size;
1574*dfc6aa5cSAndroid Build Coastguard Worker }
1575*dfc6aa5cSAndroid Build Coastguard Worker break;
1576*dfc6aa5cSAndroid Build Coastguard Worker }
1577*dfc6aa5cSAndroid Build Coastguard Worker
1578*dfc6aa5cSAndroid Build Coastguard Worker /* If cropping has been requested, compute the crop area's position and
1579*dfc6aa5cSAndroid Build Coastguard Worker * dimensions, ensuring that its upper left corner falls at an iMCU boundary.
1580*dfc6aa5cSAndroid Build Coastguard Worker */
1581*dfc6aa5cSAndroid Build Coastguard Worker if (info->crop) {
1582*dfc6aa5cSAndroid Build Coastguard Worker /* Insert default values for unset crop parameters */
1583*dfc6aa5cSAndroid Build Coastguard Worker if (info->crop_xoffset_set == JCROP_UNSET)
1584*dfc6aa5cSAndroid Build Coastguard Worker info->crop_xoffset = 0; /* default to +0 */
1585*dfc6aa5cSAndroid Build Coastguard Worker if (info->crop_yoffset_set == JCROP_UNSET)
1586*dfc6aa5cSAndroid Build Coastguard Worker info->crop_yoffset = 0; /* default to +0 */
1587*dfc6aa5cSAndroid Build Coastguard Worker if (info->crop_width_set == JCROP_UNSET) {
1588*dfc6aa5cSAndroid Build Coastguard Worker if (info->crop_xoffset >= info->output_width)
1589*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1590*dfc6aa5cSAndroid Build Coastguard Worker info->crop_width = info->output_width - info->crop_xoffset;
1591*dfc6aa5cSAndroid Build Coastguard Worker } else {
1592*dfc6aa5cSAndroid Build Coastguard Worker /* Check for crop extension */
1593*dfc6aa5cSAndroid Build Coastguard Worker if (info->crop_width > info->output_width) {
1594*dfc6aa5cSAndroid Build Coastguard Worker /* Crop extension does not work when transforming! */
1595*dfc6aa5cSAndroid Build Coastguard Worker if (info->transform != JXFORM_NONE ||
1596*dfc6aa5cSAndroid Build Coastguard Worker info->crop_xoffset >= info->crop_width ||
1597*dfc6aa5cSAndroid Build Coastguard Worker info->crop_xoffset > info->crop_width - info->output_width)
1598*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1599*dfc6aa5cSAndroid Build Coastguard Worker } else {
1600*dfc6aa5cSAndroid Build Coastguard Worker if (info->crop_xoffset >= info->output_width ||
1601*dfc6aa5cSAndroid Build Coastguard Worker info->crop_width <= 0 ||
1602*dfc6aa5cSAndroid Build Coastguard Worker info->crop_xoffset > info->output_width - info->crop_width)
1603*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1604*dfc6aa5cSAndroid Build Coastguard Worker }
1605*dfc6aa5cSAndroid Build Coastguard Worker }
1606*dfc6aa5cSAndroid Build Coastguard Worker if (info->crop_height_set == JCROP_UNSET) {
1607*dfc6aa5cSAndroid Build Coastguard Worker if (info->crop_yoffset >= info->output_height)
1608*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1609*dfc6aa5cSAndroid Build Coastguard Worker info->crop_height = info->output_height - info->crop_yoffset;
1610*dfc6aa5cSAndroid Build Coastguard Worker } else {
1611*dfc6aa5cSAndroid Build Coastguard Worker /* Check for crop extension */
1612*dfc6aa5cSAndroid Build Coastguard Worker if (info->crop_height > info->output_height) {
1613*dfc6aa5cSAndroid Build Coastguard Worker /* Crop extension does not work when transforming! */
1614*dfc6aa5cSAndroid Build Coastguard Worker if (info->transform != JXFORM_NONE ||
1615*dfc6aa5cSAndroid Build Coastguard Worker info->crop_yoffset >= info->crop_height ||
1616*dfc6aa5cSAndroid Build Coastguard Worker info->crop_yoffset > info->crop_height - info->output_height)
1617*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1618*dfc6aa5cSAndroid Build Coastguard Worker } else {
1619*dfc6aa5cSAndroid Build Coastguard Worker if (info->crop_yoffset >= info->output_height ||
1620*dfc6aa5cSAndroid Build Coastguard Worker info->crop_height <= 0 ||
1621*dfc6aa5cSAndroid Build Coastguard Worker info->crop_yoffset > info->output_height - info->crop_height)
1622*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT(srcinfo, JERR_BAD_CROP_SPEC);
1623*dfc6aa5cSAndroid Build Coastguard Worker }
1624*dfc6aa5cSAndroid Build Coastguard Worker }
1625*dfc6aa5cSAndroid Build Coastguard Worker /* Convert negative crop offsets into regular offsets */
1626*dfc6aa5cSAndroid Build Coastguard Worker if (info->crop_xoffset_set != JCROP_NEG)
1627*dfc6aa5cSAndroid Build Coastguard Worker xoffset = info->crop_xoffset;
1628*dfc6aa5cSAndroid Build Coastguard Worker else if (info->crop_width > info->output_width) /* crop extension */
1629*dfc6aa5cSAndroid Build Coastguard Worker xoffset = info->crop_width - info->output_width - info->crop_xoffset;
1630*dfc6aa5cSAndroid Build Coastguard Worker else
1631*dfc6aa5cSAndroid Build Coastguard Worker xoffset = info->output_width - info->crop_width - info->crop_xoffset;
1632*dfc6aa5cSAndroid Build Coastguard Worker if (info->crop_yoffset_set != JCROP_NEG)
1633*dfc6aa5cSAndroid Build Coastguard Worker yoffset = info->crop_yoffset;
1634*dfc6aa5cSAndroid Build Coastguard Worker else if (info->crop_height > info->output_height) /* crop extension */
1635*dfc6aa5cSAndroid Build Coastguard Worker yoffset = info->crop_height - info->output_height - info->crop_yoffset;
1636*dfc6aa5cSAndroid Build Coastguard Worker else
1637*dfc6aa5cSAndroid Build Coastguard Worker yoffset = info->output_height - info->crop_height - info->crop_yoffset;
1638*dfc6aa5cSAndroid Build Coastguard Worker /* Now adjust so that upper left corner falls at an iMCU boundary */
1639*dfc6aa5cSAndroid Build Coastguard Worker switch (info->transform) {
1640*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_DROP:
1641*dfc6aa5cSAndroid Build Coastguard Worker /* Ensure the effective drop region will not exceed the requested */
1642*dfc6aa5cSAndroid Build Coastguard Worker itemp = info->iMCU_sample_width;
1643*dfc6aa5cSAndroid Build Coastguard Worker dtemp = itemp - 1 - ((xoffset + itemp - 1) % itemp);
1644*dfc6aa5cSAndroid Build Coastguard Worker xoffset += dtemp;
1645*dfc6aa5cSAndroid Build Coastguard Worker if (info->crop_width <= dtemp)
1646*dfc6aa5cSAndroid Build Coastguard Worker info->drop_width = 0;
1647*dfc6aa5cSAndroid Build Coastguard Worker else if (xoffset + info->crop_width - dtemp == info->output_width)
1648*dfc6aa5cSAndroid Build Coastguard Worker /* Matching right edge: include partial iMCU */
1649*dfc6aa5cSAndroid Build Coastguard Worker info->drop_width = (info->crop_width - dtemp + itemp - 1) / itemp;
1650*dfc6aa5cSAndroid Build Coastguard Worker else
1651*dfc6aa5cSAndroid Build Coastguard Worker info->drop_width = (info->crop_width - dtemp) / itemp;
1652*dfc6aa5cSAndroid Build Coastguard Worker itemp = info->iMCU_sample_height;
1653*dfc6aa5cSAndroid Build Coastguard Worker dtemp = itemp - 1 - ((yoffset + itemp - 1) % itemp);
1654*dfc6aa5cSAndroid Build Coastguard Worker yoffset += dtemp;
1655*dfc6aa5cSAndroid Build Coastguard Worker if (info->crop_height <= dtemp)
1656*dfc6aa5cSAndroid Build Coastguard Worker info->drop_height = 0;
1657*dfc6aa5cSAndroid Build Coastguard Worker else if (yoffset + info->crop_height - dtemp == info->output_height)
1658*dfc6aa5cSAndroid Build Coastguard Worker /* Matching bottom edge: include partial iMCU */
1659*dfc6aa5cSAndroid Build Coastguard Worker info->drop_height = (info->crop_height - dtemp + itemp - 1) / itemp;
1660*dfc6aa5cSAndroid Build Coastguard Worker else
1661*dfc6aa5cSAndroid Build Coastguard Worker info->drop_height = (info->crop_height - dtemp) / itemp;
1662*dfc6aa5cSAndroid Build Coastguard Worker /* Check if sampling factors match for dropping */
1663*dfc6aa5cSAndroid Build Coastguard Worker if (info->drop_width != 0 && info->drop_height != 0)
1664*dfc6aa5cSAndroid Build Coastguard Worker for (ci = 0; ci < info->num_components &&
1665*dfc6aa5cSAndroid Build Coastguard Worker ci < info->drop_ptr->num_components; ci++) {
1666*dfc6aa5cSAndroid Build Coastguard Worker if (info->drop_ptr->comp_info[ci].h_samp_factor *
1667*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->max_h_samp_factor !=
1668*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->comp_info[ci].h_samp_factor *
1669*dfc6aa5cSAndroid Build Coastguard Worker info->drop_ptr->max_h_samp_factor)
1670*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT6(srcinfo, JERR_BAD_DROP_SAMPLING, ci,
1671*dfc6aa5cSAndroid Build Coastguard Worker info->drop_ptr->comp_info[ci].h_samp_factor,
1672*dfc6aa5cSAndroid Build Coastguard Worker info->drop_ptr->max_h_samp_factor,
1673*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->comp_info[ci].h_samp_factor,
1674*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->max_h_samp_factor, 'h');
1675*dfc6aa5cSAndroid Build Coastguard Worker if (info->drop_ptr->comp_info[ci].v_samp_factor *
1676*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->max_v_samp_factor !=
1677*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->comp_info[ci].v_samp_factor *
1678*dfc6aa5cSAndroid Build Coastguard Worker info->drop_ptr->max_v_samp_factor)
1679*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT6(srcinfo, JERR_BAD_DROP_SAMPLING, ci,
1680*dfc6aa5cSAndroid Build Coastguard Worker info->drop_ptr->comp_info[ci].v_samp_factor,
1681*dfc6aa5cSAndroid Build Coastguard Worker info->drop_ptr->max_v_samp_factor,
1682*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->comp_info[ci].v_samp_factor,
1683*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->max_v_samp_factor, 'v');
1684*dfc6aa5cSAndroid Build Coastguard Worker }
1685*dfc6aa5cSAndroid Build Coastguard Worker break;
1686*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_WIPE:
1687*dfc6aa5cSAndroid Build Coastguard Worker /* Ensure the effective wipe region will cover the requested */
1688*dfc6aa5cSAndroid Build Coastguard Worker info->drop_width = (JDIMENSION)jdiv_round_up
1689*dfc6aa5cSAndroid Build Coastguard Worker ((long)(info->crop_width + (xoffset % info->iMCU_sample_width)),
1690*dfc6aa5cSAndroid Build Coastguard Worker (long)info->iMCU_sample_width);
1691*dfc6aa5cSAndroid Build Coastguard Worker info->drop_height = (JDIMENSION)jdiv_round_up
1692*dfc6aa5cSAndroid Build Coastguard Worker ((long)(info->crop_height + (yoffset % info->iMCU_sample_height)),
1693*dfc6aa5cSAndroid Build Coastguard Worker (long)info->iMCU_sample_height);
1694*dfc6aa5cSAndroid Build Coastguard Worker break;
1695*dfc6aa5cSAndroid Build Coastguard Worker default:
1696*dfc6aa5cSAndroid Build Coastguard Worker /* Ensure the effective crop region will cover the requested */
1697*dfc6aa5cSAndroid Build Coastguard Worker if (info->crop_width_set == JCROP_FORCE ||
1698*dfc6aa5cSAndroid Build Coastguard Worker info->crop_width > info->output_width)
1699*dfc6aa5cSAndroid Build Coastguard Worker info->output_width = info->crop_width;
1700*dfc6aa5cSAndroid Build Coastguard Worker else
1701*dfc6aa5cSAndroid Build Coastguard Worker info->output_width =
1702*dfc6aa5cSAndroid Build Coastguard Worker info->crop_width + (xoffset % info->iMCU_sample_width);
1703*dfc6aa5cSAndroid Build Coastguard Worker if (info->crop_height_set == JCROP_FORCE ||
1704*dfc6aa5cSAndroid Build Coastguard Worker info->crop_height > info->output_height)
1705*dfc6aa5cSAndroid Build Coastguard Worker info->output_height = info->crop_height;
1706*dfc6aa5cSAndroid Build Coastguard Worker else
1707*dfc6aa5cSAndroid Build Coastguard Worker info->output_height =
1708*dfc6aa5cSAndroid Build Coastguard Worker info->crop_height + (yoffset % info->iMCU_sample_height);
1709*dfc6aa5cSAndroid Build Coastguard Worker }
1710*dfc6aa5cSAndroid Build Coastguard Worker /* Save x/y offsets measured in iMCUs */
1711*dfc6aa5cSAndroid Build Coastguard Worker info->x_crop_offset = xoffset / info->iMCU_sample_width;
1712*dfc6aa5cSAndroid Build Coastguard Worker info->y_crop_offset = yoffset / info->iMCU_sample_height;
1713*dfc6aa5cSAndroid Build Coastguard Worker } else {
1714*dfc6aa5cSAndroid Build Coastguard Worker info->x_crop_offset = 0;
1715*dfc6aa5cSAndroid Build Coastguard Worker info->y_crop_offset = 0;
1716*dfc6aa5cSAndroid Build Coastguard Worker }
1717*dfc6aa5cSAndroid Build Coastguard Worker
1718*dfc6aa5cSAndroid Build Coastguard Worker /* Figure out whether we need workspace arrays,
1719*dfc6aa5cSAndroid Build Coastguard Worker * and if so whether they are transposed relative to the source.
1720*dfc6aa5cSAndroid Build Coastguard Worker */
1721*dfc6aa5cSAndroid Build Coastguard Worker need_workspace = FALSE;
1722*dfc6aa5cSAndroid Build Coastguard Worker transpose_it = FALSE;
1723*dfc6aa5cSAndroid Build Coastguard Worker switch (info->transform) {
1724*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_NONE:
1725*dfc6aa5cSAndroid Build Coastguard Worker if (info->x_crop_offset != 0 || info->y_crop_offset != 0 ||
1726*dfc6aa5cSAndroid Build Coastguard Worker info->output_width > srcinfo->output_width ||
1727*dfc6aa5cSAndroid Build Coastguard Worker info->output_height > srcinfo->output_height)
1728*dfc6aa5cSAndroid Build Coastguard Worker need_workspace = TRUE;
1729*dfc6aa5cSAndroid Build Coastguard Worker /* No workspace needed if neither cropping nor transforming */
1730*dfc6aa5cSAndroid Build Coastguard Worker break;
1731*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_FLIP_H:
1732*dfc6aa5cSAndroid Build Coastguard Worker if (info->trim)
1733*dfc6aa5cSAndroid Build Coastguard Worker trim_right_edge(info, srcinfo->output_width);
1734*dfc6aa5cSAndroid Build Coastguard Worker if (info->y_crop_offset != 0 || info->slow_hflip)
1735*dfc6aa5cSAndroid Build Coastguard Worker need_workspace = TRUE;
1736*dfc6aa5cSAndroid Build Coastguard Worker /* do_flip_h_no_crop doesn't need a workspace array */
1737*dfc6aa5cSAndroid Build Coastguard Worker break;
1738*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_FLIP_V:
1739*dfc6aa5cSAndroid Build Coastguard Worker if (info->trim)
1740*dfc6aa5cSAndroid Build Coastguard Worker trim_bottom_edge(info, srcinfo->output_height);
1741*dfc6aa5cSAndroid Build Coastguard Worker /* Need workspace arrays having same dimensions as source image. */
1742*dfc6aa5cSAndroid Build Coastguard Worker need_workspace = TRUE;
1743*dfc6aa5cSAndroid Build Coastguard Worker break;
1744*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_TRANSPOSE:
1745*dfc6aa5cSAndroid Build Coastguard Worker /* transpose does NOT have to trim anything */
1746*dfc6aa5cSAndroid Build Coastguard Worker /* Need workspace arrays having transposed dimensions. */
1747*dfc6aa5cSAndroid Build Coastguard Worker need_workspace = TRUE;
1748*dfc6aa5cSAndroid Build Coastguard Worker transpose_it = TRUE;
1749*dfc6aa5cSAndroid Build Coastguard Worker break;
1750*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_TRANSVERSE:
1751*dfc6aa5cSAndroid Build Coastguard Worker if (info->trim) {
1752*dfc6aa5cSAndroid Build Coastguard Worker trim_right_edge(info, srcinfo->output_height);
1753*dfc6aa5cSAndroid Build Coastguard Worker trim_bottom_edge(info, srcinfo->output_width);
1754*dfc6aa5cSAndroid Build Coastguard Worker }
1755*dfc6aa5cSAndroid Build Coastguard Worker /* Need workspace arrays having transposed dimensions. */
1756*dfc6aa5cSAndroid Build Coastguard Worker need_workspace = TRUE;
1757*dfc6aa5cSAndroid Build Coastguard Worker transpose_it = TRUE;
1758*dfc6aa5cSAndroid Build Coastguard Worker break;
1759*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_ROT_90:
1760*dfc6aa5cSAndroid Build Coastguard Worker if (info->trim)
1761*dfc6aa5cSAndroid Build Coastguard Worker trim_right_edge(info, srcinfo->output_height);
1762*dfc6aa5cSAndroid Build Coastguard Worker /* Need workspace arrays having transposed dimensions. */
1763*dfc6aa5cSAndroid Build Coastguard Worker need_workspace = TRUE;
1764*dfc6aa5cSAndroid Build Coastguard Worker transpose_it = TRUE;
1765*dfc6aa5cSAndroid Build Coastguard Worker break;
1766*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_ROT_180:
1767*dfc6aa5cSAndroid Build Coastguard Worker if (info->trim) {
1768*dfc6aa5cSAndroid Build Coastguard Worker trim_right_edge(info, srcinfo->output_width);
1769*dfc6aa5cSAndroid Build Coastguard Worker trim_bottom_edge(info, srcinfo->output_height);
1770*dfc6aa5cSAndroid Build Coastguard Worker }
1771*dfc6aa5cSAndroid Build Coastguard Worker /* Need workspace arrays having same dimensions as source image. */
1772*dfc6aa5cSAndroid Build Coastguard Worker need_workspace = TRUE;
1773*dfc6aa5cSAndroid Build Coastguard Worker break;
1774*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_ROT_270:
1775*dfc6aa5cSAndroid Build Coastguard Worker if (info->trim)
1776*dfc6aa5cSAndroid Build Coastguard Worker trim_bottom_edge(info, srcinfo->output_width);
1777*dfc6aa5cSAndroid Build Coastguard Worker /* Need workspace arrays having transposed dimensions. */
1778*dfc6aa5cSAndroid Build Coastguard Worker need_workspace = TRUE;
1779*dfc6aa5cSAndroid Build Coastguard Worker transpose_it = TRUE;
1780*dfc6aa5cSAndroid Build Coastguard Worker break;
1781*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_WIPE:
1782*dfc6aa5cSAndroid Build Coastguard Worker break;
1783*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_DROP:
1784*dfc6aa5cSAndroid Build Coastguard Worker break;
1785*dfc6aa5cSAndroid Build Coastguard Worker }
1786*dfc6aa5cSAndroid Build Coastguard Worker
1787*dfc6aa5cSAndroid Build Coastguard Worker /* Allocate workspace if needed.
1788*dfc6aa5cSAndroid Build Coastguard Worker * Note that we allocate arrays padded out to the next iMCU boundary,
1789*dfc6aa5cSAndroid Build Coastguard Worker * so that transform routines need not worry about missing edge blocks.
1790*dfc6aa5cSAndroid Build Coastguard Worker */
1791*dfc6aa5cSAndroid Build Coastguard Worker if (need_workspace) {
1792*dfc6aa5cSAndroid Build Coastguard Worker coef_arrays = (jvirt_barray_ptr *)
1793*dfc6aa5cSAndroid Build Coastguard Worker (*srcinfo->mem->alloc_small) ((j_common_ptr)srcinfo, JPOOL_IMAGE,
1794*dfc6aa5cSAndroid Build Coastguard Worker sizeof(jvirt_barray_ptr) * info->num_components);
1795*dfc6aa5cSAndroid Build Coastguard Worker width_in_iMCUs = (JDIMENSION)
1796*dfc6aa5cSAndroid Build Coastguard Worker jdiv_round_up((long)info->output_width, (long)info->iMCU_sample_width);
1797*dfc6aa5cSAndroid Build Coastguard Worker height_in_iMCUs = (JDIMENSION)
1798*dfc6aa5cSAndroid Build Coastguard Worker jdiv_round_up((long)info->output_height, (long)info->iMCU_sample_height);
1799*dfc6aa5cSAndroid Build Coastguard Worker for (ci = 0; ci < info->num_components; ci++) {
1800*dfc6aa5cSAndroid Build Coastguard Worker compptr = srcinfo->comp_info + ci;
1801*dfc6aa5cSAndroid Build Coastguard Worker if (info->num_components == 1) {
1802*dfc6aa5cSAndroid Build Coastguard Worker /* we're going to force samp factors to 1x1 in this case */
1803*dfc6aa5cSAndroid Build Coastguard Worker h_samp_factor = v_samp_factor = 1;
1804*dfc6aa5cSAndroid Build Coastguard Worker } else if (transpose_it) {
1805*dfc6aa5cSAndroid Build Coastguard Worker h_samp_factor = compptr->v_samp_factor;
1806*dfc6aa5cSAndroid Build Coastguard Worker v_samp_factor = compptr->h_samp_factor;
1807*dfc6aa5cSAndroid Build Coastguard Worker } else {
1808*dfc6aa5cSAndroid Build Coastguard Worker h_samp_factor = compptr->h_samp_factor;
1809*dfc6aa5cSAndroid Build Coastguard Worker v_samp_factor = compptr->v_samp_factor;
1810*dfc6aa5cSAndroid Build Coastguard Worker }
1811*dfc6aa5cSAndroid Build Coastguard Worker width_in_blocks = width_in_iMCUs * h_samp_factor;
1812*dfc6aa5cSAndroid Build Coastguard Worker height_in_blocks = height_in_iMCUs * v_samp_factor;
1813*dfc6aa5cSAndroid Build Coastguard Worker coef_arrays[ci] = (*srcinfo->mem->request_virt_barray)
1814*dfc6aa5cSAndroid Build Coastguard Worker ((j_common_ptr)srcinfo, JPOOL_IMAGE, FALSE,
1815*dfc6aa5cSAndroid Build Coastguard Worker width_in_blocks, height_in_blocks, (JDIMENSION)v_samp_factor);
1816*dfc6aa5cSAndroid Build Coastguard Worker }
1817*dfc6aa5cSAndroid Build Coastguard Worker info->workspace_coef_arrays = coef_arrays;
1818*dfc6aa5cSAndroid Build Coastguard Worker } else
1819*dfc6aa5cSAndroid Build Coastguard Worker info->workspace_coef_arrays = NULL;
1820*dfc6aa5cSAndroid Build Coastguard Worker
1821*dfc6aa5cSAndroid Build Coastguard Worker return TRUE;
1822*dfc6aa5cSAndroid Build Coastguard Worker }
1823*dfc6aa5cSAndroid Build Coastguard Worker
1824*dfc6aa5cSAndroid Build Coastguard Worker
1825*dfc6aa5cSAndroid Build Coastguard Worker /* Transpose destination image parameters */
1826*dfc6aa5cSAndroid Build Coastguard Worker
1827*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
transpose_critical_parameters(j_compress_ptr dstinfo)1828*dfc6aa5cSAndroid Build Coastguard Worker transpose_critical_parameters(j_compress_ptr dstinfo)
1829*dfc6aa5cSAndroid Build Coastguard Worker {
1830*dfc6aa5cSAndroid Build Coastguard Worker int tblno, i, j, ci, itemp;
1831*dfc6aa5cSAndroid Build Coastguard Worker jpeg_component_info *compptr;
1832*dfc6aa5cSAndroid Build Coastguard Worker JQUANT_TBL *qtblptr;
1833*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION jtemp;
1834*dfc6aa5cSAndroid Build Coastguard Worker UINT16 qtemp;
1835*dfc6aa5cSAndroid Build Coastguard Worker
1836*dfc6aa5cSAndroid Build Coastguard Worker /* Transpose image dimensions */
1837*dfc6aa5cSAndroid Build Coastguard Worker jtemp = dstinfo->image_width;
1838*dfc6aa5cSAndroid Build Coastguard Worker dstinfo->image_width = dstinfo->image_height;
1839*dfc6aa5cSAndroid Build Coastguard Worker dstinfo->image_height = jtemp;
1840*dfc6aa5cSAndroid Build Coastguard Worker #if JPEG_LIB_VERSION >= 70
1841*dfc6aa5cSAndroid Build Coastguard Worker itemp = dstinfo->min_DCT_h_scaled_size;
1842*dfc6aa5cSAndroid Build Coastguard Worker dstinfo->min_DCT_h_scaled_size = dstinfo->min_DCT_v_scaled_size;
1843*dfc6aa5cSAndroid Build Coastguard Worker dstinfo->min_DCT_v_scaled_size = itemp;
1844*dfc6aa5cSAndroid Build Coastguard Worker #endif
1845*dfc6aa5cSAndroid Build Coastguard Worker
1846*dfc6aa5cSAndroid Build Coastguard Worker /* Transpose sampling factors */
1847*dfc6aa5cSAndroid Build Coastguard Worker for (ci = 0; ci < dstinfo->num_components; ci++) {
1848*dfc6aa5cSAndroid Build Coastguard Worker compptr = dstinfo->comp_info + ci;
1849*dfc6aa5cSAndroid Build Coastguard Worker itemp = compptr->h_samp_factor;
1850*dfc6aa5cSAndroid Build Coastguard Worker compptr->h_samp_factor = compptr->v_samp_factor;
1851*dfc6aa5cSAndroid Build Coastguard Worker compptr->v_samp_factor = itemp;
1852*dfc6aa5cSAndroid Build Coastguard Worker }
1853*dfc6aa5cSAndroid Build Coastguard Worker
1854*dfc6aa5cSAndroid Build Coastguard Worker /* Transpose quantization tables */
1855*dfc6aa5cSAndroid Build Coastguard Worker for (tblno = 0; tblno < NUM_QUANT_TBLS; tblno++) {
1856*dfc6aa5cSAndroid Build Coastguard Worker qtblptr = dstinfo->quant_tbl_ptrs[tblno];
1857*dfc6aa5cSAndroid Build Coastguard Worker if (qtblptr != NULL) {
1858*dfc6aa5cSAndroid Build Coastguard Worker for (i = 0; i < DCTSIZE; i++) {
1859*dfc6aa5cSAndroid Build Coastguard Worker for (j = 0; j < i; j++) {
1860*dfc6aa5cSAndroid Build Coastguard Worker qtemp = qtblptr->quantval[i * DCTSIZE + j];
1861*dfc6aa5cSAndroid Build Coastguard Worker qtblptr->quantval[i * DCTSIZE + j] =
1862*dfc6aa5cSAndroid Build Coastguard Worker qtblptr->quantval[j * DCTSIZE + i];
1863*dfc6aa5cSAndroid Build Coastguard Worker qtblptr->quantval[j * DCTSIZE + i] = qtemp;
1864*dfc6aa5cSAndroid Build Coastguard Worker }
1865*dfc6aa5cSAndroid Build Coastguard Worker }
1866*dfc6aa5cSAndroid Build Coastguard Worker }
1867*dfc6aa5cSAndroid Build Coastguard Worker }
1868*dfc6aa5cSAndroid Build Coastguard Worker }
1869*dfc6aa5cSAndroid Build Coastguard Worker
1870*dfc6aa5cSAndroid Build Coastguard Worker
1871*dfc6aa5cSAndroid Build Coastguard Worker /* Adjust Exif image parameters.
1872*dfc6aa5cSAndroid Build Coastguard Worker *
1873*dfc6aa5cSAndroid Build Coastguard Worker * We try to adjust the Tags ExifImageWidth and ExifImageHeight if possible.
1874*dfc6aa5cSAndroid Build Coastguard Worker */
1875*dfc6aa5cSAndroid Build Coastguard Worker
1876*dfc6aa5cSAndroid Build Coastguard Worker LOCAL(void)
adjust_exif_parameters(JOCTET * data,unsigned int length,JDIMENSION new_width,JDIMENSION new_height)1877*dfc6aa5cSAndroid Build Coastguard Worker adjust_exif_parameters(JOCTET *data, unsigned int length, JDIMENSION new_width,
1878*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION new_height)
1879*dfc6aa5cSAndroid Build Coastguard Worker {
1880*dfc6aa5cSAndroid Build Coastguard Worker boolean is_motorola; /* Flag for byte order */
1881*dfc6aa5cSAndroid Build Coastguard Worker unsigned int number_of_tags, tagnum;
1882*dfc6aa5cSAndroid Build Coastguard Worker unsigned int firstoffset, offset;
1883*dfc6aa5cSAndroid Build Coastguard Worker JDIMENSION new_value;
1884*dfc6aa5cSAndroid Build Coastguard Worker
1885*dfc6aa5cSAndroid Build Coastguard Worker if (length < 12) return; /* Length of an IFD entry */
1886*dfc6aa5cSAndroid Build Coastguard Worker
1887*dfc6aa5cSAndroid Build Coastguard Worker /* Discover byte order */
1888*dfc6aa5cSAndroid Build Coastguard Worker if (data[0] == 0x49 && data[1] == 0x49)
1889*dfc6aa5cSAndroid Build Coastguard Worker is_motorola = FALSE;
1890*dfc6aa5cSAndroid Build Coastguard Worker else if (data[0] == 0x4D && data[1] == 0x4D)
1891*dfc6aa5cSAndroid Build Coastguard Worker is_motorola = TRUE;
1892*dfc6aa5cSAndroid Build Coastguard Worker else
1893*dfc6aa5cSAndroid Build Coastguard Worker return;
1894*dfc6aa5cSAndroid Build Coastguard Worker
1895*dfc6aa5cSAndroid Build Coastguard Worker /* Check Tag Mark */
1896*dfc6aa5cSAndroid Build Coastguard Worker if (is_motorola) {
1897*dfc6aa5cSAndroid Build Coastguard Worker if (data[2] != 0) return;
1898*dfc6aa5cSAndroid Build Coastguard Worker if (data[3] != 0x2A) return;
1899*dfc6aa5cSAndroid Build Coastguard Worker } else {
1900*dfc6aa5cSAndroid Build Coastguard Worker if (data[3] != 0) return;
1901*dfc6aa5cSAndroid Build Coastguard Worker if (data[2] != 0x2A) return;
1902*dfc6aa5cSAndroid Build Coastguard Worker }
1903*dfc6aa5cSAndroid Build Coastguard Worker
1904*dfc6aa5cSAndroid Build Coastguard Worker /* Get first IFD offset (offset to IFD0) */
1905*dfc6aa5cSAndroid Build Coastguard Worker if (is_motorola) {
1906*dfc6aa5cSAndroid Build Coastguard Worker if (data[4] != 0) return;
1907*dfc6aa5cSAndroid Build Coastguard Worker if (data[5] != 0) return;
1908*dfc6aa5cSAndroid Build Coastguard Worker firstoffset = data[6];
1909*dfc6aa5cSAndroid Build Coastguard Worker firstoffset <<= 8;
1910*dfc6aa5cSAndroid Build Coastguard Worker firstoffset += data[7];
1911*dfc6aa5cSAndroid Build Coastguard Worker } else {
1912*dfc6aa5cSAndroid Build Coastguard Worker if (data[7] != 0) return;
1913*dfc6aa5cSAndroid Build Coastguard Worker if (data[6] != 0) return;
1914*dfc6aa5cSAndroid Build Coastguard Worker firstoffset = data[5];
1915*dfc6aa5cSAndroid Build Coastguard Worker firstoffset <<= 8;
1916*dfc6aa5cSAndroid Build Coastguard Worker firstoffset += data[4];
1917*dfc6aa5cSAndroid Build Coastguard Worker }
1918*dfc6aa5cSAndroid Build Coastguard Worker if (firstoffset > length - 2) return; /* check end of data segment */
1919*dfc6aa5cSAndroid Build Coastguard Worker
1920*dfc6aa5cSAndroid Build Coastguard Worker /* Get the number of directory entries contained in this IFD */
1921*dfc6aa5cSAndroid Build Coastguard Worker if (is_motorola) {
1922*dfc6aa5cSAndroid Build Coastguard Worker number_of_tags = data[firstoffset];
1923*dfc6aa5cSAndroid Build Coastguard Worker number_of_tags <<= 8;
1924*dfc6aa5cSAndroid Build Coastguard Worker number_of_tags += data[firstoffset + 1];
1925*dfc6aa5cSAndroid Build Coastguard Worker } else {
1926*dfc6aa5cSAndroid Build Coastguard Worker number_of_tags = data[firstoffset + 1];
1927*dfc6aa5cSAndroid Build Coastguard Worker number_of_tags <<= 8;
1928*dfc6aa5cSAndroid Build Coastguard Worker number_of_tags += data[firstoffset];
1929*dfc6aa5cSAndroid Build Coastguard Worker }
1930*dfc6aa5cSAndroid Build Coastguard Worker if (number_of_tags == 0) return;
1931*dfc6aa5cSAndroid Build Coastguard Worker firstoffset += 2;
1932*dfc6aa5cSAndroid Build Coastguard Worker
1933*dfc6aa5cSAndroid Build Coastguard Worker /* Search for ExifSubIFD offset Tag in IFD0 */
1934*dfc6aa5cSAndroid Build Coastguard Worker for (;;) {
1935*dfc6aa5cSAndroid Build Coastguard Worker if (firstoffset > length - 12) return; /* check end of data segment */
1936*dfc6aa5cSAndroid Build Coastguard Worker /* Get Tag number */
1937*dfc6aa5cSAndroid Build Coastguard Worker if (is_motorola) {
1938*dfc6aa5cSAndroid Build Coastguard Worker tagnum = data[firstoffset];
1939*dfc6aa5cSAndroid Build Coastguard Worker tagnum <<= 8;
1940*dfc6aa5cSAndroid Build Coastguard Worker tagnum += data[firstoffset + 1];
1941*dfc6aa5cSAndroid Build Coastguard Worker } else {
1942*dfc6aa5cSAndroid Build Coastguard Worker tagnum = data[firstoffset + 1];
1943*dfc6aa5cSAndroid Build Coastguard Worker tagnum <<= 8;
1944*dfc6aa5cSAndroid Build Coastguard Worker tagnum += data[firstoffset];
1945*dfc6aa5cSAndroid Build Coastguard Worker }
1946*dfc6aa5cSAndroid Build Coastguard Worker if (tagnum == 0x8769) break; /* found ExifSubIFD offset Tag */
1947*dfc6aa5cSAndroid Build Coastguard Worker if (--number_of_tags == 0) return;
1948*dfc6aa5cSAndroid Build Coastguard Worker firstoffset += 12;
1949*dfc6aa5cSAndroid Build Coastguard Worker }
1950*dfc6aa5cSAndroid Build Coastguard Worker
1951*dfc6aa5cSAndroid Build Coastguard Worker /* Get the ExifSubIFD offset */
1952*dfc6aa5cSAndroid Build Coastguard Worker if (is_motorola) {
1953*dfc6aa5cSAndroid Build Coastguard Worker if (data[firstoffset + 8] != 0) return;
1954*dfc6aa5cSAndroid Build Coastguard Worker if (data[firstoffset + 9] != 0) return;
1955*dfc6aa5cSAndroid Build Coastguard Worker offset = data[firstoffset + 10];
1956*dfc6aa5cSAndroid Build Coastguard Worker offset <<= 8;
1957*dfc6aa5cSAndroid Build Coastguard Worker offset += data[firstoffset + 11];
1958*dfc6aa5cSAndroid Build Coastguard Worker } else {
1959*dfc6aa5cSAndroid Build Coastguard Worker if (data[firstoffset + 11] != 0) return;
1960*dfc6aa5cSAndroid Build Coastguard Worker if (data[firstoffset + 10] != 0) return;
1961*dfc6aa5cSAndroid Build Coastguard Worker offset = data[firstoffset + 9];
1962*dfc6aa5cSAndroid Build Coastguard Worker offset <<= 8;
1963*dfc6aa5cSAndroid Build Coastguard Worker offset += data[firstoffset + 8];
1964*dfc6aa5cSAndroid Build Coastguard Worker }
1965*dfc6aa5cSAndroid Build Coastguard Worker if (offset > length - 2) return; /* check end of data segment */
1966*dfc6aa5cSAndroid Build Coastguard Worker
1967*dfc6aa5cSAndroid Build Coastguard Worker /* Get the number of directory entries contained in this SubIFD */
1968*dfc6aa5cSAndroid Build Coastguard Worker if (is_motorola) {
1969*dfc6aa5cSAndroid Build Coastguard Worker number_of_tags = data[offset];
1970*dfc6aa5cSAndroid Build Coastguard Worker number_of_tags <<= 8;
1971*dfc6aa5cSAndroid Build Coastguard Worker number_of_tags += data[offset + 1];
1972*dfc6aa5cSAndroid Build Coastguard Worker } else {
1973*dfc6aa5cSAndroid Build Coastguard Worker number_of_tags = data[offset + 1];
1974*dfc6aa5cSAndroid Build Coastguard Worker number_of_tags <<= 8;
1975*dfc6aa5cSAndroid Build Coastguard Worker number_of_tags += data[offset];
1976*dfc6aa5cSAndroid Build Coastguard Worker }
1977*dfc6aa5cSAndroid Build Coastguard Worker if (number_of_tags < 2) return;
1978*dfc6aa5cSAndroid Build Coastguard Worker offset += 2;
1979*dfc6aa5cSAndroid Build Coastguard Worker
1980*dfc6aa5cSAndroid Build Coastguard Worker /* Search for ExifImageWidth and ExifImageHeight Tags in this SubIFD */
1981*dfc6aa5cSAndroid Build Coastguard Worker do {
1982*dfc6aa5cSAndroid Build Coastguard Worker if (offset > length - 12) return; /* check end of data segment */
1983*dfc6aa5cSAndroid Build Coastguard Worker /* Get Tag number */
1984*dfc6aa5cSAndroid Build Coastguard Worker if (is_motorola) {
1985*dfc6aa5cSAndroid Build Coastguard Worker tagnum = data[offset];
1986*dfc6aa5cSAndroid Build Coastguard Worker tagnum <<= 8;
1987*dfc6aa5cSAndroid Build Coastguard Worker tagnum += data[offset + 1];
1988*dfc6aa5cSAndroid Build Coastguard Worker } else {
1989*dfc6aa5cSAndroid Build Coastguard Worker tagnum = data[offset + 1];
1990*dfc6aa5cSAndroid Build Coastguard Worker tagnum <<= 8;
1991*dfc6aa5cSAndroid Build Coastguard Worker tagnum += data[offset];
1992*dfc6aa5cSAndroid Build Coastguard Worker }
1993*dfc6aa5cSAndroid Build Coastguard Worker if (tagnum == 0xA002 || tagnum == 0xA003) {
1994*dfc6aa5cSAndroid Build Coastguard Worker if (tagnum == 0xA002)
1995*dfc6aa5cSAndroid Build Coastguard Worker new_value = new_width; /* ExifImageWidth Tag */
1996*dfc6aa5cSAndroid Build Coastguard Worker else
1997*dfc6aa5cSAndroid Build Coastguard Worker new_value = new_height; /* ExifImageHeight Tag */
1998*dfc6aa5cSAndroid Build Coastguard Worker if (is_motorola) {
1999*dfc6aa5cSAndroid Build Coastguard Worker data[offset + 2] = 0; /* Format = unsigned long (4 octets) */
2000*dfc6aa5cSAndroid Build Coastguard Worker data[offset + 3] = 4;
2001*dfc6aa5cSAndroid Build Coastguard Worker data[offset + 4] = 0; /* Number Of Components = 1 */
2002*dfc6aa5cSAndroid Build Coastguard Worker data[offset + 5] = 0;
2003*dfc6aa5cSAndroid Build Coastguard Worker data[offset + 6] = 0;
2004*dfc6aa5cSAndroid Build Coastguard Worker data[offset + 7] = 1;
2005*dfc6aa5cSAndroid Build Coastguard Worker data[offset + 8] = 0;
2006*dfc6aa5cSAndroid Build Coastguard Worker data[offset + 9] = 0;
2007*dfc6aa5cSAndroid Build Coastguard Worker data[offset + 10] = (JOCTET)((new_value >> 8) & 0xFF);
2008*dfc6aa5cSAndroid Build Coastguard Worker data[offset + 11] = (JOCTET)(new_value & 0xFF);
2009*dfc6aa5cSAndroid Build Coastguard Worker } else {
2010*dfc6aa5cSAndroid Build Coastguard Worker data[offset + 2] = 4; /* Format = unsigned long (4 octets) */
2011*dfc6aa5cSAndroid Build Coastguard Worker data[offset + 3] = 0;
2012*dfc6aa5cSAndroid Build Coastguard Worker data[offset + 4] = 1; /* Number Of Components = 1 */
2013*dfc6aa5cSAndroid Build Coastguard Worker data[offset + 5] = 0;
2014*dfc6aa5cSAndroid Build Coastguard Worker data[offset + 6] = 0;
2015*dfc6aa5cSAndroid Build Coastguard Worker data[offset + 7] = 0;
2016*dfc6aa5cSAndroid Build Coastguard Worker data[offset + 8] = (JOCTET)(new_value & 0xFF);
2017*dfc6aa5cSAndroid Build Coastguard Worker data[offset + 9] = (JOCTET)((new_value >> 8) & 0xFF);
2018*dfc6aa5cSAndroid Build Coastguard Worker data[offset + 10] = 0;
2019*dfc6aa5cSAndroid Build Coastguard Worker data[offset + 11] = 0;
2020*dfc6aa5cSAndroid Build Coastguard Worker }
2021*dfc6aa5cSAndroid Build Coastguard Worker }
2022*dfc6aa5cSAndroid Build Coastguard Worker offset += 12;
2023*dfc6aa5cSAndroid Build Coastguard Worker } while (--number_of_tags);
2024*dfc6aa5cSAndroid Build Coastguard Worker }
2025*dfc6aa5cSAndroid Build Coastguard Worker
2026*dfc6aa5cSAndroid Build Coastguard Worker
2027*dfc6aa5cSAndroid Build Coastguard Worker /* Adjust output image parameters as needed.
2028*dfc6aa5cSAndroid Build Coastguard Worker *
2029*dfc6aa5cSAndroid Build Coastguard Worker * This must be called after jpeg_copy_critical_parameters()
2030*dfc6aa5cSAndroid Build Coastguard Worker * and before jpeg_write_coefficients().
2031*dfc6aa5cSAndroid Build Coastguard Worker *
2032*dfc6aa5cSAndroid Build Coastguard Worker * The return value is the set of virtual coefficient arrays to be written
2033*dfc6aa5cSAndroid Build Coastguard Worker * (either the ones allocated by jtransform_request_workspace, or the
2034*dfc6aa5cSAndroid Build Coastguard Worker * original source data arrays). The caller will need to pass this value
2035*dfc6aa5cSAndroid Build Coastguard Worker * to jpeg_write_coefficients().
2036*dfc6aa5cSAndroid Build Coastguard Worker */
2037*dfc6aa5cSAndroid Build Coastguard Worker
2038*dfc6aa5cSAndroid Build Coastguard Worker GLOBAL(jvirt_barray_ptr *)
jtransform_adjust_parameters(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,jvirt_barray_ptr * src_coef_arrays,jpeg_transform_info * info)2039*dfc6aa5cSAndroid Build Coastguard Worker jtransform_adjust_parameters(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
2040*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *src_coef_arrays,
2041*dfc6aa5cSAndroid Build Coastguard Worker jpeg_transform_info *info)
2042*dfc6aa5cSAndroid Build Coastguard Worker {
2043*dfc6aa5cSAndroid Build Coastguard Worker /* If force-to-grayscale is requested, adjust destination parameters */
2044*dfc6aa5cSAndroid Build Coastguard Worker if (info->force_grayscale) {
2045*dfc6aa5cSAndroid Build Coastguard Worker /* First, ensure we have YCbCr or grayscale data, and that the source's
2046*dfc6aa5cSAndroid Build Coastguard Worker * Y channel is full resolution. (No reasonable person would make Y
2047*dfc6aa5cSAndroid Build Coastguard Worker * be less than full resolution, so actually coping with that case
2048*dfc6aa5cSAndroid Build Coastguard Worker * isn't worth extra code space. But we check it to avoid crashing.)
2049*dfc6aa5cSAndroid Build Coastguard Worker */
2050*dfc6aa5cSAndroid Build Coastguard Worker if (((dstinfo->jpeg_color_space == JCS_YCbCr &&
2051*dfc6aa5cSAndroid Build Coastguard Worker dstinfo->num_components == 3) ||
2052*dfc6aa5cSAndroid Build Coastguard Worker (dstinfo->jpeg_color_space == JCS_GRAYSCALE &&
2053*dfc6aa5cSAndroid Build Coastguard Worker dstinfo->num_components == 1)) &&
2054*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->comp_info[0].h_samp_factor == srcinfo->max_h_samp_factor &&
2055*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->comp_info[0].v_samp_factor == srcinfo->max_v_samp_factor) {
2056*dfc6aa5cSAndroid Build Coastguard Worker /* We use jpeg_set_colorspace to make sure subsidiary settings get fixed
2057*dfc6aa5cSAndroid Build Coastguard Worker * properly. Among other things, it sets the target h_samp_factor &
2058*dfc6aa5cSAndroid Build Coastguard Worker * v_samp_factor to 1, which typically won't match the source.
2059*dfc6aa5cSAndroid Build Coastguard Worker * We have to preserve the source's quantization table number, however.
2060*dfc6aa5cSAndroid Build Coastguard Worker */
2061*dfc6aa5cSAndroid Build Coastguard Worker int sv_quant_tbl_no = dstinfo->comp_info[0].quant_tbl_no;
2062*dfc6aa5cSAndroid Build Coastguard Worker jpeg_set_colorspace(dstinfo, JCS_GRAYSCALE);
2063*dfc6aa5cSAndroid Build Coastguard Worker dstinfo->comp_info[0].quant_tbl_no = sv_quant_tbl_no;
2064*dfc6aa5cSAndroid Build Coastguard Worker } else {
2065*dfc6aa5cSAndroid Build Coastguard Worker /* Sorry, can't do it */
2066*dfc6aa5cSAndroid Build Coastguard Worker ERREXIT(dstinfo, JERR_CONVERSION_NOTIMPL);
2067*dfc6aa5cSAndroid Build Coastguard Worker }
2068*dfc6aa5cSAndroid Build Coastguard Worker } else if (info->num_components == 1) {
2069*dfc6aa5cSAndroid Build Coastguard Worker /* For a single-component source, we force the destination sampling factors
2070*dfc6aa5cSAndroid Build Coastguard Worker * to 1x1, with or without force_grayscale. This is useful because some
2071*dfc6aa5cSAndroid Build Coastguard Worker * decoders choke on grayscale images with other sampling factors.
2072*dfc6aa5cSAndroid Build Coastguard Worker */
2073*dfc6aa5cSAndroid Build Coastguard Worker dstinfo->comp_info[0].h_samp_factor = 1;
2074*dfc6aa5cSAndroid Build Coastguard Worker dstinfo->comp_info[0].v_samp_factor = 1;
2075*dfc6aa5cSAndroid Build Coastguard Worker }
2076*dfc6aa5cSAndroid Build Coastguard Worker
2077*dfc6aa5cSAndroid Build Coastguard Worker /* Correct the destination's image dimensions as necessary
2078*dfc6aa5cSAndroid Build Coastguard Worker * for rotate/flip, resize, and crop operations.
2079*dfc6aa5cSAndroid Build Coastguard Worker */
2080*dfc6aa5cSAndroid Build Coastguard Worker #if JPEG_LIB_VERSION >= 80
2081*dfc6aa5cSAndroid Build Coastguard Worker dstinfo->jpeg_width = info->output_width;
2082*dfc6aa5cSAndroid Build Coastguard Worker dstinfo->jpeg_height = info->output_height;
2083*dfc6aa5cSAndroid Build Coastguard Worker #endif
2084*dfc6aa5cSAndroid Build Coastguard Worker
2085*dfc6aa5cSAndroid Build Coastguard Worker /* Transpose destination image parameters, adjust quantization */
2086*dfc6aa5cSAndroid Build Coastguard Worker switch (info->transform) {
2087*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_TRANSPOSE:
2088*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_TRANSVERSE:
2089*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_ROT_90:
2090*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_ROT_270:
2091*dfc6aa5cSAndroid Build Coastguard Worker #if JPEG_LIB_VERSION < 80
2092*dfc6aa5cSAndroid Build Coastguard Worker dstinfo->image_width = info->output_height;
2093*dfc6aa5cSAndroid Build Coastguard Worker dstinfo->image_height = info->output_width;
2094*dfc6aa5cSAndroid Build Coastguard Worker #endif
2095*dfc6aa5cSAndroid Build Coastguard Worker transpose_critical_parameters(dstinfo);
2096*dfc6aa5cSAndroid Build Coastguard Worker break;
2097*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_DROP:
2098*dfc6aa5cSAndroid Build Coastguard Worker if (info->drop_width != 0 && info->drop_height != 0)
2099*dfc6aa5cSAndroid Build Coastguard Worker adjust_quant(srcinfo, src_coef_arrays,
2100*dfc6aa5cSAndroid Build Coastguard Worker info->drop_ptr, info->drop_coef_arrays,
2101*dfc6aa5cSAndroid Build Coastguard Worker info->trim, dstinfo);
2102*dfc6aa5cSAndroid Build Coastguard Worker break;
2103*dfc6aa5cSAndroid Build Coastguard Worker default:
2104*dfc6aa5cSAndroid Build Coastguard Worker #if JPEG_LIB_VERSION < 80
2105*dfc6aa5cSAndroid Build Coastguard Worker dstinfo->image_width = info->output_width;
2106*dfc6aa5cSAndroid Build Coastguard Worker dstinfo->image_height = info->output_height;
2107*dfc6aa5cSAndroid Build Coastguard Worker #endif
2108*dfc6aa5cSAndroid Build Coastguard Worker break;
2109*dfc6aa5cSAndroid Build Coastguard Worker }
2110*dfc6aa5cSAndroid Build Coastguard Worker
2111*dfc6aa5cSAndroid Build Coastguard Worker /* Adjust Exif properties */
2112*dfc6aa5cSAndroid Build Coastguard Worker if (srcinfo->marker_list != NULL &&
2113*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->marker_list->marker == JPEG_APP0 + 1 &&
2114*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->marker_list->data_length >= 6 &&
2115*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->marker_list->data[0] == 0x45 &&
2116*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->marker_list->data[1] == 0x78 &&
2117*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->marker_list->data[2] == 0x69 &&
2118*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->marker_list->data[3] == 0x66 &&
2119*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->marker_list->data[4] == 0 &&
2120*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->marker_list->data[5] == 0) {
2121*dfc6aa5cSAndroid Build Coastguard Worker /* Suppress output of JFIF marker */
2122*dfc6aa5cSAndroid Build Coastguard Worker dstinfo->write_JFIF_header = FALSE;
2123*dfc6aa5cSAndroid Build Coastguard Worker /* Adjust Exif image parameters */
2124*dfc6aa5cSAndroid Build Coastguard Worker #if JPEG_LIB_VERSION >= 80
2125*dfc6aa5cSAndroid Build Coastguard Worker if (dstinfo->jpeg_width != srcinfo->image_width ||
2126*dfc6aa5cSAndroid Build Coastguard Worker dstinfo->jpeg_height != srcinfo->image_height)
2127*dfc6aa5cSAndroid Build Coastguard Worker /* Align data segment to start of TIFF structure for parsing */
2128*dfc6aa5cSAndroid Build Coastguard Worker adjust_exif_parameters(srcinfo->marker_list->data + 6,
2129*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->marker_list->data_length - 6,
2130*dfc6aa5cSAndroid Build Coastguard Worker dstinfo->jpeg_width, dstinfo->jpeg_height);
2131*dfc6aa5cSAndroid Build Coastguard Worker #else
2132*dfc6aa5cSAndroid Build Coastguard Worker if (dstinfo->image_width != srcinfo->image_width ||
2133*dfc6aa5cSAndroid Build Coastguard Worker dstinfo->image_height != srcinfo->image_height)
2134*dfc6aa5cSAndroid Build Coastguard Worker /* Align data segment to start of TIFF structure for parsing */
2135*dfc6aa5cSAndroid Build Coastguard Worker adjust_exif_parameters(srcinfo->marker_list->data + 6,
2136*dfc6aa5cSAndroid Build Coastguard Worker srcinfo->marker_list->data_length - 6,
2137*dfc6aa5cSAndroid Build Coastguard Worker dstinfo->image_width, dstinfo->image_height);
2138*dfc6aa5cSAndroid Build Coastguard Worker #endif
2139*dfc6aa5cSAndroid Build Coastguard Worker }
2140*dfc6aa5cSAndroid Build Coastguard Worker
2141*dfc6aa5cSAndroid Build Coastguard Worker /* Return the appropriate output data set */
2142*dfc6aa5cSAndroid Build Coastguard Worker if (info->workspace_coef_arrays != NULL)
2143*dfc6aa5cSAndroid Build Coastguard Worker return info->workspace_coef_arrays;
2144*dfc6aa5cSAndroid Build Coastguard Worker return src_coef_arrays;
2145*dfc6aa5cSAndroid Build Coastguard Worker }
2146*dfc6aa5cSAndroid Build Coastguard Worker
2147*dfc6aa5cSAndroid Build Coastguard Worker
2148*dfc6aa5cSAndroid Build Coastguard Worker /* Execute the actual transformation, if any.
2149*dfc6aa5cSAndroid Build Coastguard Worker *
2150*dfc6aa5cSAndroid Build Coastguard Worker * This must be called *after* jpeg_write_coefficients, because it depends
2151*dfc6aa5cSAndroid Build Coastguard Worker * on jpeg_write_coefficients to have computed subsidiary values such as
2152*dfc6aa5cSAndroid Build Coastguard Worker * the per-component width and height fields in the destination object.
2153*dfc6aa5cSAndroid Build Coastguard Worker *
2154*dfc6aa5cSAndroid Build Coastguard Worker * Note that some transformations will modify the source data arrays!
2155*dfc6aa5cSAndroid Build Coastguard Worker */
2156*dfc6aa5cSAndroid Build Coastguard Worker
2157*dfc6aa5cSAndroid Build Coastguard Worker GLOBAL(void)
jtransform_execute_transform(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,jvirt_barray_ptr * src_coef_arrays,jpeg_transform_info * info)2158*dfc6aa5cSAndroid Build Coastguard Worker jtransform_execute_transform(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
2159*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *src_coef_arrays,
2160*dfc6aa5cSAndroid Build Coastguard Worker jpeg_transform_info *info)
2161*dfc6aa5cSAndroid Build Coastguard Worker {
2162*dfc6aa5cSAndroid Build Coastguard Worker jvirt_barray_ptr *dst_coef_arrays = info->workspace_coef_arrays;
2163*dfc6aa5cSAndroid Build Coastguard Worker
2164*dfc6aa5cSAndroid Build Coastguard Worker /* Note: conditions tested here should match those in switch statement
2165*dfc6aa5cSAndroid Build Coastguard Worker * in jtransform_request_workspace()
2166*dfc6aa5cSAndroid Build Coastguard Worker */
2167*dfc6aa5cSAndroid Build Coastguard Worker switch (info->transform) {
2168*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_NONE:
2169*dfc6aa5cSAndroid Build Coastguard Worker if (info->output_width > srcinfo->output_width ||
2170*dfc6aa5cSAndroid Build Coastguard Worker info->output_height > srcinfo->output_height) {
2171*dfc6aa5cSAndroid Build Coastguard Worker if (info->output_width > srcinfo->output_width &&
2172*dfc6aa5cSAndroid Build Coastguard Worker info->crop_width_set == JCROP_REFLECT)
2173*dfc6aa5cSAndroid Build Coastguard Worker do_crop_ext_reflect(srcinfo, dstinfo,
2174*dfc6aa5cSAndroid Build Coastguard Worker info->x_crop_offset, info->y_crop_offset,
2175*dfc6aa5cSAndroid Build Coastguard Worker src_coef_arrays, dst_coef_arrays);
2176*dfc6aa5cSAndroid Build Coastguard Worker else if (info->output_width > srcinfo->output_width &&
2177*dfc6aa5cSAndroid Build Coastguard Worker info->crop_width_set == JCROP_FORCE)
2178*dfc6aa5cSAndroid Build Coastguard Worker do_crop_ext_flat(srcinfo, dstinfo,
2179*dfc6aa5cSAndroid Build Coastguard Worker info->x_crop_offset, info->y_crop_offset,
2180*dfc6aa5cSAndroid Build Coastguard Worker src_coef_arrays, dst_coef_arrays);
2181*dfc6aa5cSAndroid Build Coastguard Worker else
2182*dfc6aa5cSAndroid Build Coastguard Worker do_crop_ext_zero(srcinfo, dstinfo,
2183*dfc6aa5cSAndroid Build Coastguard Worker info->x_crop_offset, info->y_crop_offset,
2184*dfc6aa5cSAndroid Build Coastguard Worker src_coef_arrays, dst_coef_arrays);
2185*dfc6aa5cSAndroid Build Coastguard Worker } else if (info->x_crop_offset != 0 || info->y_crop_offset != 0)
2186*dfc6aa5cSAndroid Build Coastguard Worker do_crop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2187*dfc6aa5cSAndroid Build Coastguard Worker src_coef_arrays, dst_coef_arrays);
2188*dfc6aa5cSAndroid Build Coastguard Worker break;
2189*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_FLIP_H:
2190*dfc6aa5cSAndroid Build Coastguard Worker if (info->y_crop_offset != 0 || info->slow_hflip)
2191*dfc6aa5cSAndroid Build Coastguard Worker do_flip_h(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2192*dfc6aa5cSAndroid Build Coastguard Worker src_coef_arrays, dst_coef_arrays);
2193*dfc6aa5cSAndroid Build Coastguard Worker else
2194*dfc6aa5cSAndroid Build Coastguard Worker do_flip_h_no_crop(srcinfo, dstinfo, info->x_crop_offset,
2195*dfc6aa5cSAndroid Build Coastguard Worker src_coef_arrays);
2196*dfc6aa5cSAndroid Build Coastguard Worker break;
2197*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_FLIP_V:
2198*dfc6aa5cSAndroid Build Coastguard Worker do_flip_v(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2199*dfc6aa5cSAndroid Build Coastguard Worker src_coef_arrays, dst_coef_arrays);
2200*dfc6aa5cSAndroid Build Coastguard Worker break;
2201*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_TRANSPOSE:
2202*dfc6aa5cSAndroid Build Coastguard Worker do_transpose(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2203*dfc6aa5cSAndroid Build Coastguard Worker src_coef_arrays, dst_coef_arrays);
2204*dfc6aa5cSAndroid Build Coastguard Worker break;
2205*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_TRANSVERSE:
2206*dfc6aa5cSAndroid Build Coastguard Worker do_transverse(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2207*dfc6aa5cSAndroid Build Coastguard Worker src_coef_arrays, dst_coef_arrays);
2208*dfc6aa5cSAndroid Build Coastguard Worker break;
2209*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_ROT_90:
2210*dfc6aa5cSAndroid Build Coastguard Worker do_rot_90(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2211*dfc6aa5cSAndroid Build Coastguard Worker src_coef_arrays, dst_coef_arrays);
2212*dfc6aa5cSAndroid Build Coastguard Worker break;
2213*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_ROT_180:
2214*dfc6aa5cSAndroid Build Coastguard Worker do_rot_180(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2215*dfc6aa5cSAndroid Build Coastguard Worker src_coef_arrays, dst_coef_arrays);
2216*dfc6aa5cSAndroid Build Coastguard Worker break;
2217*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_ROT_270:
2218*dfc6aa5cSAndroid Build Coastguard Worker do_rot_270(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2219*dfc6aa5cSAndroid Build Coastguard Worker src_coef_arrays, dst_coef_arrays);
2220*dfc6aa5cSAndroid Build Coastguard Worker break;
2221*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_WIPE:
2222*dfc6aa5cSAndroid Build Coastguard Worker if (info->crop_width_set == JCROP_REFLECT &&
2223*dfc6aa5cSAndroid Build Coastguard Worker info->y_crop_offset == 0 && info->drop_height ==
2224*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)jdiv_round_up
2225*dfc6aa5cSAndroid Build Coastguard Worker ((long)info->output_height, (long)info->iMCU_sample_height) &&
2226*dfc6aa5cSAndroid Build Coastguard Worker (info->x_crop_offset == 0 ||
2227*dfc6aa5cSAndroid Build Coastguard Worker info->x_crop_offset + info->drop_width ==
2228*dfc6aa5cSAndroid Build Coastguard Worker (JDIMENSION)jdiv_round_up
2229*dfc6aa5cSAndroid Build Coastguard Worker ((long)info->output_width, (long)info->iMCU_sample_width)))
2230*dfc6aa5cSAndroid Build Coastguard Worker do_reflect(srcinfo, dstinfo, info->x_crop_offset,
2231*dfc6aa5cSAndroid Build Coastguard Worker src_coef_arrays, info->drop_width, info->drop_height);
2232*dfc6aa5cSAndroid Build Coastguard Worker else if (info->crop_width_set == JCROP_FORCE)
2233*dfc6aa5cSAndroid Build Coastguard Worker do_flatten(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2234*dfc6aa5cSAndroid Build Coastguard Worker src_coef_arrays, info->drop_width, info->drop_height);
2235*dfc6aa5cSAndroid Build Coastguard Worker else
2236*dfc6aa5cSAndroid Build Coastguard Worker do_wipe(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2237*dfc6aa5cSAndroid Build Coastguard Worker src_coef_arrays, info->drop_width, info->drop_height);
2238*dfc6aa5cSAndroid Build Coastguard Worker break;
2239*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_DROP:
2240*dfc6aa5cSAndroid Build Coastguard Worker if (info->drop_width != 0 && info->drop_height != 0)
2241*dfc6aa5cSAndroid Build Coastguard Worker do_drop(srcinfo, dstinfo, info->x_crop_offset, info->y_crop_offset,
2242*dfc6aa5cSAndroid Build Coastguard Worker src_coef_arrays, info->drop_ptr, info->drop_coef_arrays,
2243*dfc6aa5cSAndroid Build Coastguard Worker info->drop_width, info->drop_height);
2244*dfc6aa5cSAndroid Build Coastguard Worker break;
2245*dfc6aa5cSAndroid Build Coastguard Worker }
2246*dfc6aa5cSAndroid Build Coastguard Worker }
2247*dfc6aa5cSAndroid Build Coastguard Worker
2248*dfc6aa5cSAndroid Build Coastguard Worker /* jtransform_perfect_transform
2249*dfc6aa5cSAndroid Build Coastguard Worker *
2250*dfc6aa5cSAndroid Build Coastguard Worker * Determine whether lossless transformation is perfectly
2251*dfc6aa5cSAndroid Build Coastguard Worker * possible for a specified image and transformation.
2252*dfc6aa5cSAndroid Build Coastguard Worker *
2253*dfc6aa5cSAndroid Build Coastguard Worker * Inputs:
2254*dfc6aa5cSAndroid Build Coastguard Worker * image_width, image_height: source image dimensions.
2255*dfc6aa5cSAndroid Build Coastguard Worker * MCU_width, MCU_height: pixel dimensions of MCU.
2256*dfc6aa5cSAndroid Build Coastguard Worker * transform: transformation identifier.
2257*dfc6aa5cSAndroid Build Coastguard Worker * Parameter sources from initialized jpeg_struct
2258*dfc6aa5cSAndroid Build Coastguard Worker * (after reading source header):
2259*dfc6aa5cSAndroid Build Coastguard Worker * image_width = cinfo.image_width
2260*dfc6aa5cSAndroid Build Coastguard Worker * image_height = cinfo.image_height
2261*dfc6aa5cSAndroid Build Coastguard Worker * MCU_width = cinfo.max_h_samp_factor * cinfo.block_size
2262*dfc6aa5cSAndroid Build Coastguard Worker * MCU_height = cinfo.max_v_samp_factor * cinfo.block_size
2263*dfc6aa5cSAndroid Build Coastguard Worker * Result:
2264*dfc6aa5cSAndroid Build Coastguard Worker * TRUE = perfect transformation possible
2265*dfc6aa5cSAndroid Build Coastguard Worker * FALSE = perfect transformation not possible
2266*dfc6aa5cSAndroid Build Coastguard Worker * (may use custom action then)
2267*dfc6aa5cSAndroid Build Coastguard Worker */
2268*dfc6aa5cSAndroid Build Coastguard Worker
2269*dfc6aa5cSAndroid Build Coastguard Worker GLOBAL(boolean)
jtransform_perfect_transform(JDIMENSION image_width,JDIMENSION image_height,int MCU_width,int MCU_height,JXFORM_CODE transform)2270*dfc6aa5cSAndroid Build Coastguard Worker jtransform_perfect_transform(JDIMENSION image_width, JDIMENSION image_height,
2271*dfc6aa5cSAndroid Build Coastguard Worker int MCU_width, int MCU_height,
2272*dfc6aa5cSAndroid Build Coastguard Worker JXFORM_CODE transform)
2273*dfc6aa5cSAndroid Build Coastguard Worker {
2274*dfc6aa5cSAndroid Build Coastguard Worker boolean result = TRUE; /* initialize TRUE */
2275*dfc6aa5cSAndroid Build Coastguard Worker
2276*dfc6aa5cSAndroid Build Coastguard Worker switch (transform) {
2277*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_FLIP_H:
2278*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_ROT_270:
2279*dfc6aa5cSAndroid Build Coastguard Worker if (image_width % (JDIMENSION)MCU_width)
2280*dfc6aa5cSAndroid Build Coastguard Worker result = FALSE;
2281*dfc6aa5cSAndroid Build Coastguard Worker break;
2282*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_FLIP_V:
2283*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_ROT_90:
2284*dfc6aa5cSAndroid Build Coastguard Worker if (image_height % (JDIMENSION)MCU_height)
2285*dfc6aa5cSAndroid Build Coastguard Worker result = FALSE;
2286*dfc6aa5cSAndroid Build Coastguard Worker break;
2287*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_TRANSVERSE:
2288*dfc6aa5cSAndroid Build Coastguard Worker case JXFORM_ROT_180:
2289*dfc6aa5cSAndroid Build Coastguard Worker if (image_width % (JDIMENSION)MCU_width)
2290*dfc6aa5cSAndroid Build Coastguard Worker result = FALSE;
2291*dfc6aa5cSAndroid Build Coastguard Worker if (image_height % (JDIMENSION)MCU_height)
2292*dfc6aa5cSAndroid Build Coastguard Worker result = FALSE;
2293*dfc6aa5cSAndroid Build Coastguard Worker break;
2294*dfc6aa5cSAndroid Build Coastguard Worker default:
2295*dfc6aa5cSAndroid Build Coastguard Worker break;
2296*dfc6aa5cSAndroid Build Coastguard Worker }
2297*dfc6aa5cSAndroid Build Coastguard Worker
2298*dfc6aa5cSAndroid Build Coastguard Worker return result;
2299*dfc6aa5cSAndroid Build Coastguard Worker }
2300*dfc6aa5cSAndroid Build Coastguard Worker
2301*dfc6aa5cSAndroid Build Coastguard Worker #endif /* TRANSFORMS_SUPPORTED */
2302*dfc6aa5cSAndroid Build Coastguard Worker
2303*dfc6aa5cSAndroid Build Coastguard Worker
2304*dfc6aa5cSAndroid Build Coastguard Worker /* Setup decompression object to save desired markers in memory.
2305*dfc6aa5cSAndroid Build Coastguard Worker * This must be called before jpeg_read_header() to have the desired effect.
2306*dfc6aa5cSAndroid Build Coastguard Worker */
2307*dfc6aa5cSAndroid Build Coastguard Worker
2308*dfc6aa5cSAndroid Build Coastguard Worker GLOBAL(void)
jcopy_markers_setup(j_decompress_ptr srcinfo,JCOPY_OPTION option)2309*dfc6aa5cSAndroid Build Coastguard Worker jcopy_markers_setup(j_decompress_ptr srcinfo, JCOPY_OPTION option)
2310*dfc6aa5cSAndroid Build Coastguard Worker {
2311*dfc6aa5cSAndroid Build Coastguard Worker #ifdef SAVE_MARKERS_SUPPORTED
2312*dfc6aa5cSAndroid Build Coastguard Worker int m;
2313*dfc6aa5cSAndroid Build Coastguard Worker
2314*dfc6aa5cSAndroid Build Coastguard Worker /* Save comments except under NONE option */
2315*dfc6aa5cSAndroid Build Coastguard Worker if (option != JCOPYOPT_NONE && option != JCOPYOPT_ICC) {
2316*dfc6aa5cSAndroid Build Coastguard Worker jpeg_save_markers(srcinfo, JPEG_COM, 0xFFFF);
2317*dfc6aa5cSAndroid Build Coastguard Worker }
2318*dfc6aa5cSAndroid Build Coastguard Worker /* Save all types of APPn markers iff ALL option */
2319*dfc6aa5cSAndroid Build Coastguard Worker if (option == JCOPYOPT_ALL || option == JCOPYOPT_ALL_EXCEPT_ICC) {
2320*dfc6aa5cSAndroid Build Coastguard Worker for (m = 0; m < 16; m++) {
2321*dfc6aa5cSAndroid Build Coastguard Worker if (option == JCOPYOPT_ALL_EXCEPT_ICC && m == 2)
2322*dfc6aa5cSAndroid Build Coastguard Worker continue;
2323*dfc6aa5cSAndroid Build Coastguard Worker jpeg_save_markers(srcinfo, JPEG_APP0 + m, 0xFFFF);
2324*dfc6aa5cSAndroid Build Coastguard Worker }
2325*dfc6aa5cSAndroid Build Coastguard Worker }
2326*dfc6aa5cSAndroid Build Coastguard Worker /* Save only APP2 markers if ICC option selected */
2327*dfc6aa5cSAndroid Build Coastguard Worker if (option == JCOPYOPT_ICC) {
2328*dfc6aa5cSAndroid Build Coastguard Worker jpeg_save_markers(srcinfo, JPEG_APP0 + 2, 0xFFFF);
2329*dfc6aa5cSAndroid Build Coastguard Worker }
2330*dfc6aa5cSAndroid Build Coastguard Worker #endif /* SAVE_MARKERS_SUPPORTED */
2331*dfc6aa5cSAndroid Build Coastguard Worker }
2332*dfc6aa5cSAndroid Build Coastguard Worker
2333*dfc6aa5cSAndroid Build Coastguard Worker /* Copy markers saved in the given source object to the destination object.
2334*dfc6aa5cSAndroid Build Coastguard Worker * This should be called just after jpeg_start_compress() or
2335*dfc6aa5cSAndroid Build Coastguard Worker * jpeg_write_coefficients().
2336*dfc6aa5cSAndroid Build Coastguard Worker * Note that those routines will have written the SOI, and also the
2337*dfc6aa5cSAndroid Build Coastguard Worker * JFIF APP0 or Adobe APP14 markers if selected.
2338*dfc6aa5cSAndroid Build Coastguard Worker */
2339*dfc6aa5cSAndroid Build Coastguard Worker
2340*dfc6aa5cSAndroid Build Coastguard Worker GLOBAL(void)
jcopy_markers_execute(j_decompress_ptr srcinfo,j_compress_ptr dstinfo,JCOPY_OPTION option)2341*dfc6aa5cSAndroid Build Coastguard Worker jcopy_markers_execute(j_decompress_ptr srcinfo, j_compress_ptr dstinfo,
2342*dfc6aa5cSAndroid Build Coastguard Worker JCOPY_OPTION option)
2343*dfc6aa5cSAndroid Build Coastguard Worker {
2344*dfc6aa5cSAndroid Build Coastguard Worker jpeg_saved_marker_ptr marker;
2345*dfc6aa5cSAndroid Build Coastguard Worker
2346*dfc6aa5cSAndroid Build Coastguard Worker /* In the current implementation, we don't actually need to examine the
2347*dfc6aa5cSAndroid Build Coastguard Worker * option flag here; we just copy everything that got saved.
2348*dfc6aa5cSAndroid Build Coastguard Worker * But to avoid confusion, we do not output JFIF and Adobe APP14 markers
2349*dfc6aa5cSAndroid Build Coastguard Worker * if the encoder library already wrote one.
2350*dfc6aa5cSAndroid Build Coastguard Worker */
2351*dfc6aa5cSAndroid Build Coastguard Worker for (marker = srcinfo->marker_list; marker != NULL; marker = marker->next) {
2352*dfc6aa5cSAndroid Build Coastguard Worker if (dstinfo->write_JFIF_header &&
2353*dfc6aa5cSAndroid Build Coastguard Worker marker->marker == JPEG_APP0 &&
2354*dfc6aa5cSAndroid Build Coastguard Worker marker->data_length >= 5 &&
2355*dfc6aa5cSAndroid Build Coastguard Worker marker->data[0] == 0x4A &&
2356*dfc6aa5cSAndroid Build Coastguard Worker marker->data[1] == 0x46 &&
2357*dfc6aa5cSAndroid Build Coastguard Worker marker->data[2] == 0x49 &&
2358*dfc6aa5cSAndroid Build Coastguard Worker marker->data[3] == 0x46 &&
2359*dfc6aa5cSAndroid Build Coastguard Worker marker->data[4] == 0)
2360*dfc6aa5cSAndroid Build Coastguard Worker continue; /* reject duplicate JFIF */
2361*dfc6aa5cSAndroid Build Coastguard Worker if (dstinfo->write_Adobe_marker &&
2362*dfc6aa5cSAndroid Build Coastguard Worker marker->marker == JPEG_APP0 + 14 &&
2363*dfc6aa5cSAndroid Build Coastguard Worker marker->data_length >= 5 &&
2364*dfc6aa5cSAndroid Build Coastguard Worker marker->data[0] == 0x41 &&
2365*dfc6aa5cSAndroid Build Coastguard Worker marker->data[1] == 0x64 &&
2366*dfc6aa5cSAndroid Build Coastguard Worker marker->data[2] == 0x6F &&
2367*dfc6aa5cSAndroid Build Coastguard Worker marker->data[3] == 0x62 &&
2368*dfc6aa5cSAndroid Build Coastguard Worker marker->data[4] == 0x65)
2369*dfc6aa5cSAndroid Build Coastguard Worker continue; /* reject duplicate Adobe */
2370*dfc6aa5cSAndroid Build Coastguard Worker jpeg_write_marker(dstinfo, marker->marker,
2371*dfc6aa5cSAndroid Build Coastguard Worker marker->data, marker->data_length);
2372*dfc6aa5cSAndroid Build Coastguard Worker }
2373*dfc6aa5cSAndroid Build Coastguard Worker }
2374