1*3ac0a46fSAndroid Build Coastguard Worker /*
2*3ac0a46fSAndroid Build Coastguard Worker * Copyright (c) 1988-1997 Sam Leffler
3*3ac0a46fSAndroid Build Coastguard Worker * Copyright (c) 1991-1997 Silicon Graphics, Inc.
4*3ac0a46fSAndroid Build Coastguard Worker *
5*3ac0a46fSAndroid Build Coastguard Worker * Permission to use, copy, modify, distribute, and sell this software and
6*3ac0a46fSAndroid Build Coastguard Worker * its documentation for any purpose is hereby granted without fee, provided
7*3ac0a46fSAndroid Build Coastguard Worker * that (i) the above copyright notices and this permission notice appear in
8*3ac0a46fSAndroid Build Coastguard Worker * all copies of the software and related documentation, and (ii) the names of
9*3ac0a46fSAndroid Build Coastguard Worker * Sam Leffler and Silicon Graphics may not be used in any advertising or
10*3ac0a46fSAndroid Build Coastguard Worker * publicity relating to the software without the specific, prior written
11*3ac0a46fSAndroid Build Coastguard Worker * permission of Sam Leffler and Silicon Graphics.
12*3ac0a46fSAndroid Build Coastguard Worker *
13*3ac0a46fSAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
14*3ac0a46fSAndroid Build Coastguard Worker * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
15*3ac0a46fSAndroid Build Coastguard Worker * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
16*3ac0a46fSAndroid Build Coastguard Worker *
17*3ac0a46fSAndroid Build Coastguard Worker * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
18*3ac0a46fSAndroid Build Coastguard Worker * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19*3ac0a46fSAndroid Build Coastguard Worker * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20*3ac0a46fSAndroid Build Coastguard Worker * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
21*3ac0a46fSAndroid Build Coastguard Worker * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22*3ac0a46fSAndroid Build Coastguard Worker * OF THIS SOFTWARE.
23*3ac0a46fSAndroid Build Coastguard Worker */
24*3ac0a46fSAndroid Build Coastguard Worker
25*3ac0a46fSAndroid Build Coastguard Worker /*
26*3ac0a46fSAndroid Build Coastguard Worker * TIFF Library.
27*3ac0a46fSAndroid Build Coastguard Worker *
28*3ac0a46fSAndroid Build Coastguard Worker * Predictor Tag Support (used by multiple codecs).
29*3ac0a46fSAndroid Build Coastguard Worker */
30*3ac0a46fSAndroid Build Coastguard Worker #include "tif_predict.h"
31*3ac0a46fSAndroid Build Coastguard Worker #include "tiffiop.h"
32*3ac0a46fSAndroid Build Coastguard Worker
33*3ac0a46fSAndroid Build Coastguard Worker #define PredictorState(tif) ((TIFFPredictorState *)(tif)->tif_data)
34*3ac0a46fSAndroid Build Coastguard Worker
35*3ac0a46fSAndroid Build Coastguard Worker static int horAcc8(TIFF *tif, uint8_t *cp0, tmsize_t cc);
36*3ac0a46fSAndroid Build Coastguard Worker static int horAcc16(TIFF *tif, uint8_t *cp0, tmsize_t cc);
37*3ac0a46fSAndroid Build Coastguard Worker static int horAcc32(TIFF *tif, uint8_t *cp0, tmsize_t cc);
38*3ac0a46fSAndroid Build Coastguard Worker static int horAcc64(TIFF *tif, uint8_t *cp0, tmsize_t cc);
39*3ac0a46fSAndroid Build Coastguard Worker static int swabHorAcc16(TIFF *tif, uint8_t *cp0, tmsize_t cc);
40*3ac0a46fSAndroid Build Coastguard Worker static int swabHorAcc32(TIFF *tif, uint8_t *cp0, tmsize_t cc);
41*3ac0a46fSAndroid Build Coastguard Worker static int swabHorAcc64(TIFF *tif, uint8_t *cp0, tmsize_t cc);
42*3ac0a46fSAndroid Build Coastguard Worker static int horDiff8(TIFF *tif, uint8_t *cp0, tmsize_t cc);
43*3ac0a46fSAndroid Build Coastguard Worker static int horDiff16(TIFF *tif, uint8_t *cp0, tmsize_t cc);
44*3ac0a46fSAndroid Build Coastguard Worker static int horDiff32(TIFF *tif, uint8_t *cp0, tmsize_t cc);
45*3ac0a46fSAndroid Build Coastguard Worker static int horDiff64(TIFF *tif, uint8_t *cp0, tmsize_t cc);
46*3ac0a46fSAndroid Build Coastguard Worker static int swabHorDiff16(TIFF *tif, uint8_t *cp0, tmsize_t cc);
47*3ac0a46fSAndroid Build Coastguard Worker static int swabHorDiff32(TIFF *tif, uint8_t *cp0, tmsize_t cc);
48*3ac0a46fSAndroid Build Coastguard Worker static int swabHorDiff64(TIFF *tif, uint8_t *cp0, tmsize_t cc);
49*3ac0a46fSAndroid Build Coastguard Worker static int fpAcc(TIFF *tif, uint8_t *cp0, tmsize_t cc);
50*3ac0a46fSAndroid Build Coastguard Worker static int fpDiff(TIFF *tif, uint8_t *cp0, tmsize_t cc);
51*3ac0a46fSAndroid Build Coastguard Worker static int PredictorDecodeRow(TIFF *tif, uint8_t *op0, tmsize_t occ0,
52*3ac0a46fSAndroid Build Coastguard Worker uint16_t s);
53*3ac0a46fSAndroid Build Coastguard Worker static int PredictorDecodeTile(TIFF *tif, uint8_t *op0, tmsize_t occ0,
54*3ac0a46fSAndroid Build Coastguard Worker uint16_t s);
55*3ac0a46fSAndroid Build Coastguard Worker static int PredictorEncodeRow(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s);
56*3ac0a46fSAndroid Build Coastguard Worker static int PredictorEncodeTile(TIFF *tif, uint8_t *bp0, tmsize_t cc0,
57*3ac0a46fSAndroid Build Coastguard Worker uint16_t s);
58*3ac0a46fSAndroid Build Coastguard Worker
PredictorSetup(TIFF * tif)59*3ac0a46fSAndroid Build Coastguard Worker static int PredictorSetup(TIFF *tif)
60*3ac0a46fSAndroid Build Coastguard Worker {
61*3ac0a46fSAndroid Build Coastguard Worker static const char module[] = "PredictorSetup";
62*3ac0a46fSAndroid Build Coastguard Worker
63*3ac0a46fSAndroid Build Coastguard Worker TIFFPredictorState *sp = PredictorState(tif);
64*3ac0a46fSAndroid Build Coastguard Worker TIFFDirectory *td = &tif->tif_dir;
65*3ac0a46fSAndroid Build Coastguard Worker
66*3ac0a46fSAndroid Build Coastguard Worker switch (sp->predictor) /* no differencing */
67*3ac0a46fSAndroid Build Coastguard Worker {
68*3ac0a46fSAndroid Build Coastguard Worker case PREDICTOR_NONE:
69*3ac0a46fSAndroid Build Coastguard Worker return 1;
70*3ac0a46fSAndroid Build Coastguard Worker case PREDICTOR_HORIZONTAL:
71*3ac0a46fSAndroid Build Coastguard Worker if (td->td_bitspersample != 8 && td->td_bitspersample != 16 &&
72*3ac0a46fSAndroid Build Coastguard Worker td->td_bitspersample != 32 && td->td_bitspersample != 64)
73*3ac0a46fSAndroid Build Coastguard Worker {
74*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module,
75*3ac0a46fSAndroid Build Coastguard Worker "Horizontal differencing \"Predictor\" not "
76*3ac0a46fSAndroid Build Coastguard Worker "supported with %" PRIu16 "-bit samples",
77*3ac0a46fSAndroid Build Coastguard Worker td->td_bitspersample);
78*3ac0a46fSAndroid Build Coastguard Worker return 0;
79*3ac0a46fSAndroid Build Coastguard Worker }
80*3ac0a46fSAndroid Build Coastguard Worker break;
81*3ac0a46fSAndroid Build Coastguard Worker case PREDICTOR_FLOATINGPOINT:
82*3ac0a46fSAndroid Build Coastguard Worker if (td->td_sampleformat != SAMPLEFORMAT_IEEEFP)
83*3ac0a46fSAndroid Build Coastguard Worker {
84*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(
85*3ac0a46fSAndroid Build Coastguard Worker tif, module,
86*3ac0a46fSAndroid Build Coastguard Worker "Floating point \"Predictor\" not supported with %" PRIu16
87*3ac0a46fSAndroid Build Coastguard Worker " data format",
88*3ac0a46fSAndroid Build Coastguard Worker td->td_sampleformat);
89*3ac0a46fSAndroid Build Coastguard Worker return 0;
90*3ac0a46fSAndroid Build Coastguard Worker }
91*3ac0a46fSAndroid Build Coastguard Worker if (td->td_bitspersample != 16 && td->td_bitspersample != 24 &&
92*3ac0a46fSAndroid Build Coastguard Worker td->td_bitspersample != 32 && td->td_bitspersample != 64)
93*3ac0a46fSAndroid Build Coastguard Worker { /* Should 64 be allowed? */
94*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(
95*3ac0a46fSAndroid Build Coastguard Worker tif, module,
96*3ac0a46fSAndroid Build Coastguard Worker "Floating point \"Predictor\" not supported with %" PRIu16
97*3ac0a46fSAndroid Build Coastguard Worker "-bit samples",
98*3ac0a46fSAndroid Build Coastguard Worker td->td_bitspersample);
99*3ac0a46fSAndroid Build Coastguard Worker return 0;
100*3ac0a46fSAndroid Build Coastguard Worker }
101*3ac0a46fSAndroid Build Coastguard Worker break;
102*3ac0a46fSAndroid Build Coastguard Worker default:
103*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module, "\"Predictor\" value %d not supported",
104*3ac0a46fSAndroid Build Coastguard Worker sp->predictor);
105*3ac0a46fSAndroid Build Coastguard Worker return 0;
106*3ac0a46fSAndroid Build Coastguard Worker }
107*3ac0a46fSAndroid Build Coastguard Worker sp->stride =
108*3ac0a46fSAndroid Build Coastguard Worker (td->td_planarconfig == PLANARCONFIG_CONTIG ? td->td_samplesperpixel
109*3ac0a46fSAndroid Build Coastguard Worker : 1);
110*3ac0a46fSAndroid Build Coastguard Worker /*
111*3ac0a46fSAndroid Build Coastguard Worker * Calculate the scanline/tile-width size in bytes.
112*3ac0a46fSAndroid Build Coastguard Worker */
113*3ac0a46fSAndroid Build Coastguard Worker if (isTiled(tif))
114*3ac0a46fSAndroid Build Coastguard Worker sp->rowsize = TIFFTileRowSize(tif);
115*3ac0a46fSAndroid Build Coastguard Worker else
116*3ac0a46fSAndroid Build Coastguard Worker sp->rowsize = TIFFScanlineSize(tif);
117*3ac0a46fSAndroid Build Coastguard Worker if (sp->rowsize == 0)
118*3ac0a46fSAndroid Build Coastguard Worker return 0;
119*3ac0a46fSAndroid Build Coastguard Worker
120*3ac0a46fSAndroid Build Coastguard Worker return 1;
121*3ac0a46fSAndroid Build Coastguard Worker }
122*3ac0a46fSAndroid Build Coastguard Worker
PredictorSetupDecode(TIFF * tif)123*3ac0a46fSAndroid Build Coastguard Worker static int PredictorSetupDecode(TIFF *tif)
124*3ac0a46fSAndroid Build Coastguard Worker {
125*3ac0a46fSAndroid Build Coastguard Worker TIFFPredictorState *sp = PredictorState(tif);
126*3ac0a46fSAndroid Build Coastguard Worker TIFFDirectory *td = &tif->tif_dir;
127*3ac0a46fSAndroid Build Coastguard Worker
128*3ac0a46fSAndroid Build Coastguard Worker /* Note: when PredictorSetup() fails, the effets of setupdecode() */
129*3ac0a46fSAndroid Build Coastguard Worker /* will not be "canceled" so setupdecode() might be robust to */
130*3ac0a46fSAndroid Build Coastguard Worker /* be called several times. */
131*3ac0a46fSAndroid Build Coastguard Worker if (!(*sp->setupdecode)(tif) || !PredictorSetup(tif))
132*3ac0a46fSAndroid Build Coastguard Worker return 0;
133*3ac0a46fSAndroid Build Coastguard Worker
134*3ac0a46fSAndroid Build Coastguard Worker if (sp->predictor == 2)
135*3ac0a46fSAndroid Build Coastguard Worker {
136*3ac0a46fSAndroid Build Coastguard Worker switch (td->td_bitspersample)
137*3ac0a46fSAndroid Build Coastguard Worker {
138*3ac0a46fSAndroid Build Coastguard Worker case 8:
139*3ac0a46fSAndroid Build Coastguard Worker sp->decodepfunc = horAcc8;
140*3ac0a46fSAndroid Build Coastguard Worker break;
141*3ac0a46fSAndroid Build Coastguard Worker case 16:
142*3ac0a46fSAndroid Build Coastguard Worker sp->decodepfunc = horAcc16;
143*3ac0a46fSAndroid Build Coastguard Worker break;
144*3ac0a46fSAndroid Build Coastguard Worker case 32:
145*3ac0a46fSAndroid Build Coastguard Worker sp->decodepfunc = horAcc32;
146*3ac0a46fSAndroid Build Coastguard Worker break;
147*3ac0a46fSAndroid Build Coastguard Worker case 64:
148*3ac0a46fSAndroid Build Coastguard Worker sp->decodepfunc = horAcc64;
149*3ac0a46fSAndroid Build Coastguard Worker break;
150*3ac0a46fSAndroid Build Coastguard Worker }
151*3ac0a46fSAndroid Build Coastguard Worker /*
152*3ac0a46fSAndroid Build Coastguard Worker * Override default decoding method with one that does the
153*3ac0a46fSAndroid Build Coastguard Worker * predictor stuff.
154*3ac0a46fSAndroid Build Coastguard Worker */
155*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_decoderow != PredictorDecodeRow)
156*3ac0a46fSAndroid Build Coastguard Worker {
157*3ac0a46fSAndroid Build Coastguard Worker sp->decoderow = tif->tif_decoderow;
158*3ac0a46fSAndroid Build Coastguard Worker tif->tif_decoderow = PredictorDecodeRow;
159*3ac0a46fSAndroid Build Coastguard Worker sp->decodestrip = tif->tif_decodestrip;
160*3ac0a46fSAndroid Build Coastguard Worker tif->tif_decodestrip = PredictorDecodeTile;
161*3ac0a46fSAndroid Build Coastguard Worker sp->decodetile = tif->tif_decodetile;
162*3ac0a46fSAndroid Build Coastguard Worker tif->tif_decodetile = PredictorDecodeTile;
163*3ac0a46fSAndroid Build Coastguard Worker }
164*3ac0a46fSAndroid Build Coastguard Worker
165*3ac0a46fSAndroid Build Coastguard Worker /*
166*3ac0a46fSAndroid Build Coastguard Worker * If the data is horizontally differenced 16-bit data that
167*3ac0a46fSAndroid Build Coastguard Worker * requires byte-swapping, then it must be byte swapped before
168*3ac0a46fSAndroid Build Coastguard Worker * the accumulation step. We do this with a special-purpose
169*3ac0a46fSAndroid Build Coastguard Worker * routine and override the normal post decoding logic that
170*3ac0a46fSAndroid Build Coastguard Worker * the library setup when the directory was read.
171*3ac0a46fSAndroid Build Coastguard Worker */
172*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_flags & TIFF_SWAB)
173*3ac0a46fSAndroid Build Coastguard Worker {
174*3ac0a46fSAndroid Build Coastguard Worker if (sp->decodepfunc == horAcc16)
175*3ac0a46fSAndroid Build Coastguard Worker {
176*3ac0a46fSAndroid Build Coastguard Worker sp->decodepfunc = swabHorAcc16;
177*3ac0a46fSAndroid Build Coastguard Worker tif->tif_postdecode = _TIFFNoPostDecode;
178*3ac0a46fSAndroid Build Coastguard Worker }
179*3ac0a46fSAndroid Build Coastguard Worker else if (sp->decodepfunc == horAcc32)
180*3ac0a46fSAndroid Build Coastguard Worker {
181*3ac0a46fSAndroid Build Coastguard Worker sp->decodepfunc = swabHorAcc32;
182*3ac0a46fSAndroid Build Coastguard Worker tif->tif_postdecode = _TIFFNoPostDecode;
183*3ac0a46fSAndroid Build Coastguard Worker }
184*3ac0a46fSAndroid Build Coastguard Worker else if (sp->decodepfunc == horAcc64)
185*3ac0a46fSAndroid Build Coastguard Worker {
186*3ac0a46fSAndroid Build Coastguard Worker sp->decodepfunc = swabHorAcc64;
187*3ac0a46fSAndroid Build Coastguard Worker tif->tif_postdecode = _TIFFNoPostDecode;
188*3ac0a46fSAndroid Build Coastguard Worker }
189*3ac0a46fSAndroid Build Coastguard Worker }
190*3ac0a46fSAndroid Build Coastguard Worker }
191*3ac0a46fSAndroid Build Coastguard Worker
192*3ac0a46fSAndroid Build Coastguard Worker else if (sp->predictor == 3)
193*3ac0a46fSAndroid Build Coastguard Worker {
194*3ac0a46fSAndroid Build Coastguard Worker sp->decodepfunc = fpAcc;
195*3ac0a46fSAndroid Build Coastguard Worker /*
196*3ac0a46fSAndroid Build Coastguard Worker * Override default decoding method with one that does the
197*3ac0a46fSAndroid Build Coastguard Worker * predictor stuff.
198*3ac0a46fSAndroid Build Coastguard Worker */
199*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_decoderow != PredictorDecodeRow)
200*3ac0a46fSAndroid Build Coastguard Worker {
201*3ac0a46fSAndroid Build Coastguard Worker sp->decoderow = tif->tif_decoderow;
202*3ac0a46fSAndroid Build Coastguard Worker tif->tif_decoderow = PredictorDecodeRow;
203*3ac0a46fSAndroid Build Coastguard Worker sp->decodestrip = tif->tif_decodestrip;
204*3ac0a46fSAndroid Build Coastguard Worker tif->tif_decodestrip = PredictorDecodeTile;
205*3ac0a46fSAndroid Build Coastguard Worker sp->decodetile = tif->tif_decodetile;
206*3ac0a46fSAndroid Build Coastguard Worker tif->tif_decodetile = PredictorDecodeTile;
207*3ac0a46fSAndroid Build Coastguard Worker }
208*3ac0a46fSAndroid Build Coastguard Worker /*
209*3ac0a46fSAndroid Build Coastguard Worker * The data should not be swapped outside of the floating
210*3ac0a46fSAndroid Build Coastguard Worker * point predictor, the accumulation routine should return
211*3ac0a46fSAndroid Build Coastguard Worker * byres in the native order.
212*3ac0a46fSAndroid Build Coastguard Worker */
213*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_flags & TIFF_SWAB)
214*3ac0a46fSAndroid Build Coastguard Worker {
215*3ac0a46fSAndroid Build Coastguard Worker tif->tif_postdecode = _TIFFNoPostDecode;
216*3ac0a46fSAndroid Build Coastguard Worker }
217*3ac0a46fSAndroid Build Coastguard Worker /*
218*3ac0a46fSAndroid Build Coastguard Worker * Allocate buffer to keep the decoded bytes before
219*3ac0a46fSAndroid Build Coastguard Worker * rearranging in the right order
220*3ac0a46fSAndroid Build Coastguard Worker */
221*3ac0a46fSAndroid Build Coastguard Worker }
222*3ac0a46fSAndroid Build Coastguard Worker
223*3ac0a46fSAndroid Build Coastguard Worker return 1;
224*3ac0a46fSAndroid Build Coastguard Worker }
225*3ac0a46fSAndroid Build Coastguard Worker
PredictorSetupEncode(TIFF * tif)226*3ac0a46fSAndroid Build Coastguard Worker static int PredictorSetupEncode(TIFF *tif)
227*3ac0a46fSAndroid Build Coastguard Worker {
228*3ac0a46fSAndroid Build Coastguard Worker TIFFPredictorState *sp = PredictorState(tif);
229*3ac0a46fSAndroid Build Coastguard Worker TIFFDirectory *td = &tif->tif_dir;
230*3ac0a46fSAndroid Build Coastguard Worker
231*3ac0a46fSAndroid Build Coastguard Worker if (!(*sp->setupencode)(tif) || !PredictorSetup(tif))
232*3ac0a46fSAndroid Build Coastguard Worker return 0;
233*3ac0a46fSAndroid Build Coastguard Worker
234*3ac0a46fSAndroid Build Coastguard Worker if (sp->predictor == 2)
235*3ac0a46fSAndroid Build Coastguard Worker {
236*3ac0a46fSAndroid Build Coastguard Worker switch (td->td_bitspersample)
237*3ac0a46fSAndroid Build Coastguard Worker {
238*3ac0a46fSAndroid Build Coastguard Worker case 8:
239*3ac0a46fSAndroid Build Coastguard Worker sp->encodepfunc = horDiff8;
240*3ac0a46fSAndroid Build Coastguard Worker break;
241*3ac0a46fSAndroid Build Coastguard Worker case 16:
242*3ac0a46fSAndroid Build Coastguard Worker sp->encodepfunc = horDiff16;
243*3ac0a46fSAndroid Build Coastguard Worker break;
244*3ac0a46fSAndroid Build Coastguard Worker case 32:
245*3ac0a46fSAndroid Build Coastguard Worker sp->encodepfunc = horDiff32;
246*3ac0a46fSAndroid Build Coastguard Worker break;
247*3ac0a46fSAndroid Build Coastguard Worker case 64:
248*3ac0a46fSAndroid Build Coastguard Worker sp->encodepfunc = horDiff64;
249*3ac0a46fSAndroid Build Coastguard Worker break;
250*3ac0a46fSAndroid Build Coastguard Worker }
251*3ac0a46fSAndroid Build Coastguard Worker /*
252*3ac0a46fSAndroid Build Coastguard Worker * Override default encoding method with one that does the
253*3ac0a46fSAndroid Build Coastguard Worker * predictor stuff.
254*3ac0a46fSAndroid Build Coastguard Worker */
255*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_encoderow != PredictorEncodeRow)
256*3ac0a46fSAndroid Build Coastguard Worker {
257*3ac0a46fSAndroid Build Coastguard Worker sp->encoderow = tif->tif_encoderow;
258*3ac0a46fSAndroid Build Coastguard Worker tif->tif_encoderow = PredictorEncodeRow;
259*3ac0a46fSAndroid Build Coastguard Worker sp->encodestrip = tif->tif_encodestrip;
260*3ac0a46fSAndroid Build Coastguard Worker tif->tif_encodestrip = PredictorEncodeTile;
261*3ac0a46fSAndroid Build Coastguard Worker sp->encodetile = tif->tif_encodetile;
262*3ac0a46fSAndroid Build Coastguard Worker tif->tif_encodetile = PredictorEncodeTile;
263*3ac0a46fSAndroid Build Coastguard Worker }
264*3ac0a46fSAndroid Build Coastguard Worker
265*3ac0a46fSAndroid Build Coastguard Worker /*
266*3ac0a46fSAndroid Build Coastguard Worker * If the data is horizontally differenced 16-bit data that
267*3ac0a46fSAndroid Build Coastguard Worker * requires byte-swapping, then it must be byte swapped after
268*3ac0a46fSAndroid Build Coastguard Worker * the differentiation step. We do this with a special-purpose
269*3ac0a46fSAndroid Build Coastguard Worker * routine and override the normal post decoding logic that
270*3ac0a46fSAndroid Build Coastguard Worker * the library setup when the directory was read.
271*3ac0a46fSAndroid Build Coastguard Worker */
272*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_flags & TIFF_SWAB)
273*3ac0a46fSAndroid Build Coastguard Worker {
274*3ac0a46fSAndroid Build Coastguard Worker if (sp->encodepfunc == horDiff16)
275*3ac0a46fSAndroid Build Coastguard Worker {
276*3ac0a46fSAndroid Build Coastguard Worker sp->encodepfunc = swabHorDiff16;
277*3ac0a46fSAndroid Build Coastguard Worker tif->tif_postdecode = _TIFFNoPostDecode;
278*3ac0a46fSAndroid Build Coastguard Worker }
279*3ac0a46fSAndroid Build Coastguard Worker else if (sp->encodepfunc == horDiff32)
280*3ac0a46fSAndroid Build Coastguard Worker {
281*3ac0a46fSAndroid Build Coastguard Worker sp->encodepfunc = swabHorDiff32;
282*3ac0a46fSAndroid Build Coastguard Worker tif->tif_postdecode = _TIFFNoPostDecode;
283*3ac0a46fSAndroid Build Coastguard Worker }
284*3ac0a46fSAndroid Build Coastguard Worker else if (sp->encodepfunc == horDiff64)
285*3ac0a46fSAndroid Build Coastguard Worker {
286*3ac0a46fSAndroid Build Coastguard Worker sp->encodepfunc = swabHorDiff64;
287*3ac0a46fSAndroid Build Coastguard Worker tif->tif_postdecode = _TIFFNoPostDecode;
288*3ac0a46fSAndroid Build Coastguard Worker }
289*3ac0a46fSAndroid Build Coastguard Worker }
290*3ac0a46fSAndroid Build Coastguard Worker }
291*3ac0a46fSAndroid Build Coastguard Worker
292*3ac0a46fSAndroid Build Coastguard Worker else if (sp->predictor == 3)
293*3ac0a46fSAndroid Build Coastguard Worker {
294*3ac0a46fSAndroid Build Coastguard Worker sp->encodepfunc = fpDiff;
295*3ac0a46fSAndroid Build Coastguard Worker /*
296*3ac0a46fSAndroid Build Coastguard Worker * Override default encoding method with one that does the
297*3ac0a46fSAndroid Build Coastguard Worker * predictor stuff.
298*3ac0a46fSAndroid Build Coastguard Worker */
299*3ac0a46fSAndroid Build Coastguard Worker if (tif->tif_encoderow != PredictorEncodeRow)
300*3ac0a46fSAndroid Build Coastguard Worker {
301*3ac0a46fSAndroid Build Coastguard Worker sp->encoderow = tif->tif_encoderow;
302*3ac0a46fSAndroid Build Coastguard Worker tif->tif_encoderow = PredictorEncodeRow;
303*3ac0a46fSAndroid Build Coastguard Worker sp->encodestrip = tif->tif_encodestrip;
304*3ac0a46fSAndroid Build Coastguard Worker tif->tif_encodestrip = PredictorEncodeTile;
305*3ac0a46fSAndroid Build Coastguard Worker sp->encodetile = tif->tif_encodetile;
306*3ac0a46fSAndroid Build Coastguard Worker tif->tif_encodetile = PredictorEncodeTile;
307*3ac0a46fSAndroid Build Coastguard Worker }
308*3ac0a46fSAndroid Build Coastguard Worker }
309*3ac0a46fSAndroid Build Coastguard Worker
310*3ac0a46fSAndroid Build Coastguard Worker return 1;
311*3ac0a46fSAndroid Build Coastguard Worker }
312*3ac0a46fSAndroid Build Coastguard Worker
313*3ac0a46fSAndroid Build Coastguard Worker #define REPEAT4(n, op) \
314*3ac0a46fSAndroid Build Coastguard Worker switch (n) \
315*3ac0a46fSAndroid Build Coastguard Worker { \
316*3ac0a46fSAndroid Build Coastguard Worker default: \
317*3ac0a46fSAndroid Build Coastguard Worker { \
318*3ac0a46fSAndroid Build Coastguard Worker tmsize_t i; \
319*3ac0a46fSAndroid Build Coastguard Worker for (i = n - 4; i > 0; i--) \
320*3ac0a46fSAndroid Build Coastguard Worker { \
321*3ac0a46fSAndroid Build Coastguard Worker op; \
322*3ac0a46fSAndroid Build Coastguard Worker } \
323*3ac0a46fSAndroid Build Coastguard Worker } /*-fallthrough*/ \
324*3ac0a46fSAndroid Build Coastguard Worker case 4: \
325*3ac0a46fSAndroid Build Coastguard Worker op; /*-fallthrough*/ \
326*3ac0a46fSAndroid Build Coastguard Worker case 3: \
327*3ac0a46fSAndroid Build Coastguard Worker op; /*-fallthrough*/ \
328*3ac0a46fSAndroid Build Coastguard Worker case 2: \
329*3ac0a46fSAndroid Build Coastguard Worker op; /*-fallthrough*/ \
330*3ac0a46fSAndroid Build Coastguard Worker case 1: \
331*3ac0a46fSAndroid Build Coastguard Worker op; /*-fallthrough*/ \
332*3ac0a46fSAndroid Build Coastguard Worker case 0:; \
333*3ac0a46fSAndroid Build Coastguard Worker }
334*3ac0a46fSAndroid Build Coastguard Worker
335*3ac0a46fSAndroid Build Coastguard Worker /* Remarks related to C standard compliance in all below functions : */
336*3ac0a46fSAndroid Build Coastguard Worker /* - to avoid any undefined behavior, we only operate on unsigned types */
337*3ac0a46fSAndroid Build Coastguard Worker /* since the behavior of "overflows" is defined (wrap over) */
338*3ac0a46fSAndroid Build Coastguard Worker /* - when storing into the byte stream, we explicitly mask with 0xff so */
339*3ac0a46fSAndroid Build Coastguard Worker /* as to make icc -check=conversions happy (not necessary by the standard) */
340*3ac0a46fSAndroid Build Coastguard Worker
341*3ac0a46fSAndroid Build Coastguard Worker TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW
horAcc8(TIFF * tif,uint8_t * cp0,tmsize_t cc)342*3ac0a46fSAndroid Build Coastguard Worker static int horAcc8(TIFF *tif, uint8_t *cp0, tmsize_t cc)
343*3ac0a46fSAndroid Build Coastguard Worker {
344*3ac0a46fSAndroid Build Coastguard Worker tmsize_t stride = PredictorState(tif)->stride;
345*3ac0a46fSAndroid Build Coastguard Worker
346*3ac0a46fSAndroid Build Coastguard Worker unsigned char *cp = (unsigned char *)cp0;
347*3ac0a46fSAndroid Build Coastguard Worker if ((cc % stride) != 0)
348*3ac0a46fSAndroid Build Coastguard Worker {
349*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, "horAcc8", "%s", "(cc%stride)!=0");
350*3ac0a46fSAndroid Build Coastguard Worker return 0;
351*3ac0a46fSAndroid Build Coastguard Worker }
352*3ac0a46fSAndroid Build Coastguard Worker
353*3ac0a46fSAndroid Build Coastguard Worker if (cc > stride)
354*3ac0a46fSAndroid Build Coastguard Worker {
355*3ac0a46fSAndroid Build Coastguard Worker /*
356*3ac0a46fSAndroid Build Coastguard Worker * Pipeline the most common cases.
357*3ac0a46fSAndroid Build Coastguard Worker */
358*3ac0a46fSAndroid Build Coastguard Worker if (stride == 3)
359*3ac0a46fSAndroid Build Coastguard Worker {
360*3ac0a46fSAndroid Build Coastguard Worker unsigned int cr = cp[0];
361*3ac0a46fSAndroid Build Coastguard Worker unsigned int cg = cp[1];
362*3ac0a46fSAndroid Build Coastguard Worker unsigned int cb = cp[2];
363*3ac0a46fSAndroid Build Coastguard Worker tmsize_t i = stride;
364*3ac0a46fSAndroid Build Coastguard Worker for (; i < cc; i += stride)
365*3ac0a46fSAndroid Build Coastguard Worker {
366*3ac0a46fSAndroid Build Coastguard Worker cp[i + 0] = (unsigned char)((cr += cp[i + 0]) & 0xff);
367*3ac0a46fSAndroid Build Coastguard Worker cp[i + 1] = (unsigned char)((cg += cp[i + 1]) & 0xff);
368*3ac0a46fSAndroid Build Coastguard Worker cp[i + 2] = (unsigned char)((cb += cp[i + 2]) & 0xff);
369*3ac0a46fSAndroid Build Coastguard Worker }
370*3ac0a46fSAndroid Build Coastguard Worker }
371*3ac0a46fSAndroid Build Coastguard Worker else if (stride == 4)
372*3ac0a46fSAndroid Build Coastguard Worker {
373*3ac0a46fSAndroid Build Coastguard Worker unsigned int cr = cp[0];
374*3ac0a46fSAndroid Build Coastguard Worker unsigned int cg = cp[1];
375*3ac0a46fSAndroid Build Coastguard Worker unsigned int cb = cp[2];
376*3ac0a46fSAndroid Build Coastguard Worker unsigned int ca = cp[3];
377*3ac0a46fSAndroid Build Coastguard Worker tmsize_t i = stride;
378*3ac0a46fSAndroid Build Coastguard Worker for (; i < cc; i += stride)
379*3ac0a46fSAndroid Build Coastguard Worker {
380*3ac0a46fSAndroid Build Coastguard Worker cp[i + 0] = (unsigned char)((cr += cp[i + 0]) & 0xff);
381*3ac0a46fSAndroid Build Coastguard Worker cp[i + 1] = (unsigned char)((cg += cp[i + 1]) & 0xff);
382*3ac0a46fSAndroid Build Coastguard Worker cp[i + 2] = (unsigned char)((cb += cp[i + 2]) & 0xff);
383*3ac0a46fSAndroid Build Coastguard Worker cp[i + 3] = (unsigned char)((ca += cp[i + 3]) & 0xff);
384*3ac0a46fSAndroid Build Coastguard Worker }
385*3ac0a46fSAndroid Build Coastguard Worker }
386*3ac0a46fSAndroid Build Coastguard Worker else
387*3ac0a46fSAndroid Build Coastguard Worker {
388*3ac0a46fSAndroid Build Coastguard Worker cc -= stride;
389*3ac0a46fSAndroid Build Coastguard Worker do
390*3ac0a46fSAndroid Build Coastguard Worker {
391*3ac0a46fSAndroid Build Coastguard Worker REPEAT4(stride,
392*3ac0a46fSAndroid Build Coastguard Worker cp[stride] = (unsigned char)((cp[stride] + *cp) & 0xff);
393*3ac0a46fSAndroid Build Coastguard Worker cp++)
394*3ac0a46fSAndroid Build Coastguard Worker cc -= stride;
395*3ac0a46fSAndroid Build Coastguard Worker } while (cc > 0);
396*3ac0a46fSAndroid Build Coastguard Worker }
397*3ac0a46fSAndroid Build Coastguard Worker }
398*3ac0a46fSAndroid Build Coastguard Worker return 1;
399*3ac0a46fSAndroid Build Coastguard Worker }
400*3ac0a46fSAndroid Build Coastguard Worker
swabHorAcc16(TIFF * tif,uint8_t * cp0,tmsize_t cc)401*3ac0a46fSAndroid Build Coastguard Worker static int swabHorAcc16(TIFF *tif, uint8_t *cp0, tmsize_t cc)
402*3ac0a46fSAndroid Build Coastguard Worker {
403*3ac0a46fSAndroid Build Coastguard Worker uint16_t *wp = (uint16_t *)cp0;
404*3ac0a46fSAndroid Build Coastguard Worker tmsize_t wc = cc / 2;
405*3ac0a46fSAndroid Build Coastguard Worker
406*3ac0a46fSAndroid Build Coastguard Worker TIFFSwabArrayOfShort(wp, wc);
407*3ac0a46fSAndroid Build Coastguard Worker return horAcc16(tif, cp0, cc);
408*3ac0a46fSAndroid Build Coastguard Worker }
409*3ac0a46fSAndroid Build Coastguard Worker
410*3ac0a46fSAndroid Build Coastguard Worker TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW
horAcc16(TIFF * tif,uint8_t * cp0,tmsize_t cc)411*3ac0a46fSAndroid Build Coastguard Worker static int horAcc16(TIFF *tif, uint8_t *cp0, tmsize_t cc)
412*3ac0a46fSAndroid Build Coastguard Worker {
413*3ac0a46fSAndroid Build Coastguard Worker tmsize_t stride = PredictorState(tif)->stride;
414*3ac0a46fSAndroid Build Coastguard Worker uint16_t *wp = (uint16_t *)cp0;
415*3ac0a46fSAndroid Build Coastguard Worker tmsize_t wc = cc / 2;
416*3ac0a46fSAndroid Build Coastguard Worker
417*3ac0a46fSAndroid Build Coastguard Worker if ((cc % (2 * stride)) != 0)
418*3ac0a46fSAndroid Build Coastguard Worker {
419*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, "horAcc16", "%s", "cc%(2*stride))!=0");
420*3ac0a46fSAndroid Build Coastguard Worker return 0;
421*3ac0a46fSAndroid Build Coastguard Worker }
422*3ac0a46fSAndroid Build Coastguard Worker
423*3ac0a46fSAndroid Build Coastguard Worker if (wc > stride)
424*3ac0a46fSAndroid Build Coastguard Worker {
425*3ac0a46fSAndroid Build Coastguard Worker wc -= stride;
426*3ac0a46fSAndroid Build Coastguard Worker do
427*3ac0a46fSAndroid Build Coastguard Worker {
428*3ac0a46fSAndroid Build Coastguard Worker REPEAT4(stride, wp[stride] = (uint16_t)(((unsigned int)wp[stride] +
429*3ac0a46fSAndroid Build Coastguard Worker (unsigned int)wp[0]) &
430*3ac0a46fSAndroid Build Coastguard Worker 0xffff);
431*3ac0a46fSAndroid Build Coastguard Worker wp++)
432*3ac0a46fSAndroid Build Coastguard Worker wc -= stride;
433*3ac0a46fSAndroid Build Coastguard Worker } while (wc > 0);
434*3ac0a46fSAndroid Build Coastguard Worker }
435*3ac0a46fSAndroid Build Coastguard Worker return 1;
436*3ac0a46fSAndroid Build Coastguard Worker }
437*3ac0a46fSAndroid Build Coastguard Worker
swabHorAcc32(TIFF * tif,uint8_t * cp0,tmsize_t cc)438*3ac0a46fSAndroid Build Coastguard Worker static int swabHorAcc32(TIFF *tif, uint8_t *cp0, tmsize_t cc)
439*3ac0a46fSAndroid Build Coastguard Worker {
440*3ac0a46fSAndroid Build Coastguard Worker uint32_t *wp = (uint32_t *)cp0;
441*3ac0a46fSAndroid Build Coastguard Worker tmsize_t wc = cc / 4;
442*3ac0a46fSAndroid Build Coastguard Worker
443*3ac0a46fSAndroid Build Coastguard Worker TIFFSwabArrayOfLong(wp, wc);
444*3ac0a46fSAndroid Build Coastguard Worker return horAcc32(tif, cp0, cc);
445*3ac0a46fSAndroid Build Coastguard Worker }
446*3ac0a46fSAndroid Build Coastguard Worker
447*3ac0a46fSAndroid Build Coastguard Worker TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW
horAcc32(TIFF * tif,uint8_t * cp0,tmsize_t cc)448*3ac0a46fSAndroid Build Coastguard Worker static int horAcc32(TIFF *tif, uint8_t *cp0, tmsize_t cc)
449*3ac0a46fSAndroid Build Coastguard Worker {
450*3ac0a46fSAndroid Build Coastguard Worker tmsize_t stride = PredictorState(tif)->stride;
451*3ac0a46fSAndroid Build Coastguard Worker uint32_t *wp = (uint32_t *)cp0;
452*3ac0a46fSAndroid Build Coastguard Worker tmsize_t wc = cc / 4;
453*3ac0a46fSAndroid Build Coastguard Worker
454*3ac0a46fSAndroid Build Coastguard Worker if ((cc % (4 * stride)) != 0)
455*3ac0a46fSAndroid Build Coastguard Worker {
456*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, "horAcc32", "%s", "cc%(4*stride))!=0");
457*3ac0a46fSAndroid Build Coastguard Worker return 0;
458*3ac0a46fSAndroid Build Coastguard Worker }
459*3ac0a46fSAndroid Build Coastguard Worker
460*3ac0a46fSAndroid Build Coastguard Worker if (wc > stride)
461*3ac0a46fSAndroid Build Coastguard Worker {
462*3ac0a46fSAndroid Build Coastguard Worker wc -= stride;
463*3ac0a46fSAndroid Build Coastguard Worker do
464*3ac0a46fSAndroid Build Coastguard Worker {
465*3ac0a46fSAndroid Build Coastguard Worker REPEAT4(stride, wp[stride] += wp[0]; wp++)
466*3ac0a46fSAndroid Build Coastguard Worker wc -= stride;
467*3ac0a46fSAndroid Build Coastguard Worker } while (wc > 0);
468*3ac0a46fSAndroid Build Coastguard Worker }
469*3ac0a46fSAndroid Build Coastguard Worker return 1;
470*3ac0a46fSAndroid Build Coastguard Worker }
471*3ac0a46fSAndroid Build Coastguard Worker
swabHorAcc64(TIFF * tif,uint8_t * cp0,tmsize_t cc)472*3ac0a46fSAndroid Build Coastguard Worker static int swabHorAcc64(TIFF *tif, uint8_t *cp0, tmsize_t cc)
473*3ac0a46fSAndroid Build Coastguard Worker {
474*3ac0a46fSAndroid Build Coastguard Worker uint64_t *wp = (uint64_t *)cp0;
475*3ac0a46fSAndroid Build Coastguard Worker tmsize_t wc = cc / 8;
476*3ac0a46fSAndroid Build Coastguard Worker
477*3ac0a46fSAndroid Build Coastguard Worker TIFFSwabArrayOfLong8(wp, wc);
478*3ac0a46fSAndroid Build Coastguard Worker return horAcc64(tif, cp0, cc);
479*3ac0a46fSAndroid Build Coastguard Worker }
480*3ac0a46fSAndroid Build Coastguard Worker
481*3ac0a46fSAndroid Build Coastguard Worker TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW
horAcc64(TIFF * tif,uint8_t * cp0,tmsize_t cc)482*3ac0a46fSAndroid Build Coastguard Worker static int horAcc64(TIFF *tif, uint8_t *cp0, tmsize_t cc)
483*3ac0a46fSAndroid Build Coastguard Worker {
484*3ac0a46fSAndroid Build Coastguard Worker tmsize_t stride = PredictorState(tif)->stride;
485*3ac0a46fSAndroid Build Coastguard Worker uint64_t *wp = (uint64_t *)cp0;
486*3ac0a46fSAndroid Build Coastguard Worker tmsize_t wc = cc / 8;
487*3ac0a46fSAndroid Build Coastguard Worker
488*3ac0a46fSAndroid Build Coastguard Worker if ((cc % (8 * stride)) != 0)
489*3ac0a46fSAndroid Build Coastguard Worker {
490*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, "horAcc64", "%s", "cc%(8*stride))!=0");
491*3ac0a46fSAndroid Build Coastguard Worker return 0;
492*3ac0a46fSAndroid Build Coastguard Worker }
493*3ac0a46fSAndroid Build Coastguard Worker
494*3ac0a46fSAndroid Build Coastguard Worker if (wc > stride)
495*3ac0a46fSAndroid Build Coastguard Worker {
496*3ac0a46fSAndroid Build Coastguard Worker wc -= stride;
497*3ac0a46fSAndroid Build Coastguard Worker do
498*3ac0a46fSAndroid Build Coastguard Worker {
499*3ac0a46fSAndroid Build Coastguard Worker REPEAT4(stride, wp[stride] += wp[0]; wp++)
500*3ac0a46fSAndroid Build Coastguard Worker wc -= stride;
501*3ac0a46fSAndroid Build Coastguard Worker } while (wc > 0);
502*3ac0a46fSAndroid Build Coastguard Worker }
503*3ac0a46fSAndroid Build Coastguard Worker return 1;
504*3ac0a46fSAndroid Build Coastguard Worker }
505*3ac0a46fSAndroid Build Coastguard Worker
506*3ac0a46fSAndroid Build Coastguard Worker /*
507*3ac0a46fSAndroid Build Coastguard Worker * Floating point predictor accumulation routine.
508*3ac0a46fSAndroid Build Coastguard Worker */
fpAcc(TIFF * tif,uint8_t * cp0,tmsize_t cc)509*3ac0a46fSAndroid Build Coastguard Worker static int fpAcc(TIFF *tif, uint8_t *cp0, tmsize_t cc)
510*3ac0a46fSAndroid Build Coastguard Worker {
511*3ac0a46fSAndroid Build Coastguard Worker tmsize_t stride = PredictorState(tif)->stride;
512*3ac0a46fSAndroid Build Coastguard Worker uint32_t bps = tif->tif_dir.td_bitspersample / 8;
513*3ac0a46fSAndroid Build Coastguard Worker tmsize_t wc = cc / bps;
514*3ac0a46fSAndroid Build Coastguard Worker tmsize_t count = cc;
515*3ac0a46fSAndroid Build Coastguard Worker uint8_t *cp = (uint8_t *)cp0;
516*3ac0a46fSAndroid Build Coastguard Worker uint8_t *tmp;
517*3ac0a46fSAndroid Build Coastguard Worker
518*3ac0a46fSAndroid Build Coastguard Worker if (cc % (bps * stride) != 0)
519*3ac0a46fSAndroid Build Coastguard Worker {
520*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, "fpAcc", "%s", "cc%(bps*stride))!=0");
521*3ac0a46fSAndroid Build Coastguard Worker return 0;
522*3ac0a46fSAndroid Build Coastguard Worker }
523*3ac0a46fSAndroid Build Coastguard Worker
524*3ac0a46fSAndroid Build Coastguard Worker tmp = (uint8_t *)_TIFFmallocExt(tif, cc);
525*3ac0a46fSAndroid Build Coastguard Worker if (!tmp)
526*3ac0a46fSAndroid Build Coastguard Worker return 0;
527*3ac0a46fSAndroid Build Coastguard Worker
528*3ac0a46fSAndroid Build Coastguard Worker while (count > stride)
529*3ac0a46fSAndroid Build Coastguard Worker {
530*3ac0a46fSAndroid Build Coastguard Worker REPEAT4(stride,
531*3ac0a46fSAndroid Build Coastguard Worker cp[stride] = (unsigned char)((cp[stride] + cp[0]) & 0xff);
532*3ac0a46fSAndroid Build Coastguard Worker cp++)
533*3ac0a46fSAndroid Build Coastguard Worker count -= stride;
534*3ac0a46fSAndroid Build Coastguard Worker }
535*3ac0a46fSAndroid Build Coastguard Worker
536*3ac0a46fSAndroid Build Coastguard Worker _TIFFmemcpy(tmp, cp0, cc);
537*3ac0a46fSAndroid Build Coastguard Worker cp = (uint8_t *)cp0;
538*3ac0a46fSAndroid Build Coastguard Worker for (count = 0; count < wc; count++)
539*3ac0a46fSAndroid Build Coastguard Worker {
540*3ac0a46fSAndroid Build Coastguard Worker uint32_t byte;
541*3ac0a46fSAndroid Build Coastguard Worker for (byte = 0; byte < bps; byte++)
542*3ac0a46fSAndroid Build Coastguard Worker {
543*3ac0a46fSAndroid Build Coastguard Worker #if WORDS_BIGENDIAN
544*3ac0a46fSAndroid Build Coastguard Worker cp[bps * count + byte] = tmp[byte * wc + count];
545*3ac0a46fSAndroid Build Coastguard Worker #else
546*3ac0a46fSAndroid Build Coastguard Worker cp[bps * count + byte] = tmp[(bps - byte - 1) * wc + count];
547*3ac0a46fSAndroid Build Coastguard Worker #endif
548*3ac0a46fSAndroid Build Coastguard Worker }
549*3ac0a46fSAndroid Build Coastguard Worker }
550*3ac0a46fSAndroid Build Coastguard Worker _TIFFfreeExt(tif, tmp);
551*3ac0a46fSAndroid Build Coastguard Worker return 1;
552*3ac0a46fSAndroid Build Coastguard Worker }
553*3ac0a46fSAndroid Build Coastguard Worker
554*3ac0a46fSAndroid Build Coastguard Worker /*
555*3ac0a46fSAndroid Build Coastguard Worker * Decode a scanline and apply the predictor routine.
556*3ac0a46fSAndroid Build Coastguard Worker */
PredictorDecodeRow(TIFF * tif,uint8_t * op0,tmsize_t occ0,uint16_t s)557*3ac0a46fSAndroid Build Coastguard Worker static int PredictorDecodeRow(TIFF *tif, uint8_t *op0, tmsize_t occ0,
558*3ac0a46fSAndroid Build Coastguard Worker uint16_t s)
559*3ac0a46fSAndroid Build Coastguard Worker {
560*3ac0a46fSAndroid Build Coastguard Worker TIFFPredictorState *sp = PredictorState(tif);
561*3ac0a46fSAndroid Build Coastguard Worker
562*3ac0a46fSAndroid Build Coastguard Worker assert(sp != NULL);
563*3ac0a46fSAndroid Build Coastguard Worker assert(sp->decoderow != NULL);
564*3ac0a46fSAndroid Build Coastguard Worker assert(sp->decodepfunc != NULL);
565*3ac0a46fSAndroid Build Coastguard Worker
566*3ac0a46fSAndroid Build Coastguard Worker if ((*sp->decoderow)(tif, op0, occ0, s))
567*3ac0a46fSAndroid Build Coastguard Worker {
568*3ac0a46fSAndroid Build Coastguard Worker return (*sp->decodepfunc)(tif, op0, occ0);
569*3ac0a46fSAndroid Build Coastguard Worker }
570*3ac0a46fSAndroid Build Coastguard Worker else
571*3ac0a46fSAndroid Build Coastguard Worker return 0;
572*3ac0a46fSAndroid Build Coastguard Worker }
573*3ac0a46fSAndroid Build Coastguard Worker
574*3ac0a46fSAndroid Build Coastguard Worker /*
575*3ac0a46fSAndroid Build Coastguard Worker * Decode a tile/strip and apply the predictor routine.
576*3ac0a46fSAndroid Build Coastguard Worker * Note that horizontal differencing must be done on a
577*3ac0a46fSAndroid Build Coastguard Worker * row-by-row basis. The width of a "row" has already
578*3ac0a46fSAndroid Build Coastguard Worker * been calculated at pre-decode time according to the
579*3ac0a46fSAndroid Build Coastguard Worker * strip/tile dimensions.
580*3ac0a46fSAndroid Build Coastguard Worker */
PredictorDecodeTile(TIFF * tif,uint8_t * op0,tmsize_t occ0,uint16_t s)581*3ac0a46fSAndroid Build Coastguard Worker static int PredictorDecodeTile(TIFF *tif, uint8_t *op0, tmsize_t occ0,
582*3ac0a46fSAndroid Build Coastguard Worker uint16_t s)
583*3ac0a46fSAndroid Build Coastguard Worker {
584*3ac0a46fSAndroid Build Coastguard Worker TIFFPredictorState *sp = PredictorState(tif);
585*3ac0a46fSAndroid Build Coastguard Worker
586*3ac0a46fSAndroid Build Coastguard Worker assert(sp != NULL);
587*3ac0a46fSAndroid Build Coastguard Worker assert(sp->decodetile != NULL);
588*3ac0a46fSAndroid Build Coastguard Worker
589*3ac0a46fSAndroid Build Coastguard Worker if ((*sp->decodetile)(tif, op0, occ0, s))
590*3ac0a46fSAndroid Build Coastguard Worker {
591*3ac0a46fSAndroid Build Coastguard Worker tmsize_t rowsize = sp->rowsize;
592*3ac0a46fSAndroid Build Coastguard Worker assert(rowsize > 0);
593*3ac0a46fSAndroid Build Coastguard Worker if ((occ0 % rowsize) != 0)
594*3ac0a46fSAndroid Build Coastguard Worker {
595*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, "PredictorDecodeTile", "%s",
596*3ac0a46fSAndroid Build Coastguard Worker "occ0%rowsize != 0");
597*3ac0a46fSAndroid Build Coastguard Worker return 0;
598*3ac0a46fSAndroid Build Coastguard Worker }
599*3ac0a46fSAndroid Build Coastguard Worker assert(sp->decodepfunc != NULL);
600*3ac0a46fSAndroid Build Coastguard Worker while (occ0 > 0)
601*3ac0a46fSAndroid Build Coastguard Worker {
602*3ac0a46fSAndroid Build Coastguard Worker if (!(*sp->decodepfunc)(tif, op0, rowsize))
603*3ac0a46fSAndroid Build Coastguard Worker return 0;
604*3ac0a46fSAndroid Build Coastguard Worker occ0 -= rowsize;
605*3ac0a46fSAndroid Build Coastguard Worker op0 += rowsize;
606*3ac0a46fSAndroid Build Coastguard Worker }
607*3ac0a46fSAndroid Build Coastguard Worker return 1;
608*3ac0a46fSAndroid Build Coastguard Worker }
609*3ac0a46fSAndroid Build Coastguard Worker else
610*3ac0a46fSAndroid Build Coastguard Worker return 0;
611*3ac0a46fSAndroid Build Coastguard Worker }
612*3ac0a46fSAndroid Build Coastguard Worker
613*3ac0a46fSAndroid Build Coastguard Worker TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW
horDiff8(TIFF * tif,uint8_t * cp0,tmsize_t cc)614*3ac0a46fSAndroid Build Coastguard Worker static int horDiff8(TIFF *tif, uint8_t *cp0, tmsize_t cc)
615*3ac0a46fSAndroid Build Coastguard Worker {
616*3ac0a46fSAndroid Build Coastguard Worker TIFFPredictorState *sp = PredictorState(tif);
617*3ac0a46fSAndroid Build Coastguard Worker tmsize_t stride = sp->stride;
618*3ac0a46fSAndroid Build Coastguard Worker unsigned char *cp = (unsigned char *)cp0;
619*3ac0a46fSAndroid Build Coastguard Worker
620*3ac0a46fSAndroid Build Coastguard Worker if ((cc % stride) != 0)
621*3ac0a46fSAndroid Build Coastguard Worker {
622*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, "horDiff8", "%s", "(cc%stride)!=0");
623*3ac0a46fSAndroid Build Coastguard Worker return 0;
624*3ac0a46fSAndroid Build Coastguard Worker }
625*3ac0a46fSAndroid Build Coastguard Worker
626*3ac0a46fSAndroid Build Coastguard Worker if (cc > stride)
627*3ac0a46fSAndroid Build Coastguard Worker {
628*3ac0a46fSAndroid Build Coastguard Worker cc -= stride;
629*3ac0a46fSAndroid Build Coastguard Worker /*
630*3ac0a46fSAndroid Build Coastguard Worker * Pipeline the most common cases.
631*3ac0a46fSAndroid Build Coastguard Worker */
632*3ac0a46fSAndroid Build Coastguard Worker if (stride == 3)
633*3ac0a46fSAndroid Build Coastguard Worker {
634*3ac0a46fSAndroid Build Coastguard Worker unsigned int r1, g1, b1;
635*3ac0a46fSAndroid Build Coastguard Worker unsigned int r2 = cp[0];
636*3ac0a46fSAndroid Build Coastguard Worker unsigned int g2 = cp[1];
637*3ac0a46fSAndroid Build Coastguard Worker unsigned int b2 = cp[2];
638*3ac0a46fSAndroid Build Coastguard Worker do
639*3ac0a46fSAndroid Build Coastguard Worker {
640*3ac0a46fSAndroid Build Coastguard Worker r1 = cp[3];
641*3ac0a46fSAndroid Build Coastguard Worker cp[3] = (unsigned char)((r1 - r2) & 0xff);
642*3ac0a46fSAndroid Build Coastguard Worker r2 = r1;
643*3ac0a46fSAndroid Build Coastguard Worker g1 = cp[4];
644*3ac0a46fSAndroid Build Coastguard Worker cp[4] = (unsigned char)((g1 - g2) & 0xff);
645*3ac0a46fSAndroid Build Coastguard Worker g2 = g1;
646*3ac0a46fSAndroid Build Coastguard Worker b1 = cp[5];
647*3ac0a46fSAndroid Build Coastguard Worker cp[5] = (unsigned char)((b1 - b2) & 0xff);
648*3ac0a46fSAndroid Build Coastguard Worker b2 = b1;
649*3ac0a46fSAndroid Build Coastguard Worker cp += 3;
650*3ac0a46fSAndroid Build Coastguard Worker } while ((cc -= 3) > 0);
651*3ac0a46fSAndroid Build Coastguard Worker }
652*3ac0a46fSAndroid Build Coastguard Worker else if (stride == 4)
653*3ac0a46fSAndroid Build Coastguard Worker {
654*3ac0a46fSAndroid Build Coastguard Worker unsigned int r1, g1, b1, a1;
655*3ac0a46fSAndroid Build Coastguard Worker unsigned int r2 = cp[0];
656*3ac0a46fSAndroid Build Coastguard Worker unsigned int g2 = cp[1];
657*3ac0a46fSAndroid Build Coastguard Worker unsigned int b2 = cp[2];
658*3ac0a46fSAndroid Build Coastguard Worker unsigned int a2 = cp[3];
659*3ac0a46fSAndroid Build Coastguard Worker do
660*3ac0a46fSAndroid Build Coastguard Worker {
661*3ac0a46fSAndroid Build Coastguard Worker r1 = cp[4];
662*3ac0a46fSAndroid Build Coastguard Worker cp[4] = (unsigned char)((r1 - r2) & 0xff);
663*3ac0a46fSAndroid Build Coastguard Worker r2 = r1;
664*3ac0a46fSAndroid Build Coastguard Worker g1 = cp[5];
665*3ac0a46fSAndroid Build Coastguard Worker cp[5] = (unsigned char)((g1 - g2) & 0xff);
666*3ac0a46fSAndroid Build Coastguard Worker g2 = g1;
667*3ac0a46fSAndroid Build Coastguard Worker b1 = cp[6];
668*3ac0a46fSAndroid Build Coastguard Worker cp[6] = (unsigned char)((b1 - b2) & 0xff);
669*3ac0a46fSAndroid Build Coastguard Worker b2 = b1;
670*3ac0a46fSAndroid Build Coastguard Worker a1 = cp[7];
671*3ac0a46fSAndroid Build Coastguard Worker cp[7] = (unsigned char)((a1 - a2) & 0xff);
672*3ac0a46fSAndroid Build Coastguard Worker a2 = a1;
673*3ac0a46fSAndroid Build Coastguard Worker cp += 4;
674*3ac0a46fSAndroid Build Coastguard Worker } while ((cc -= 4) > 0);
675*3ac0a46fSAndroid Build Coastguard Worker }
676*3ac0a46fSAndroid Build Coastguard Worker else
677*3ac0a46fSAndroid Build Coastguard Worker {
678*3ac0a46fSAndroid Build Coastguard Worker cp += cc - 1;
679*3ac0a46fSAndroid Build Coastguard Worker do
680*3ac0a46fSAndroid Build Coastguard Worker {
681*3ac0a46fSAndroid Build Coastguard Worker REPEAT4(stride,
682*3ac0a46fSAndroid Build Coastguard Worker cp[stride] =
683*3ac0a46fSAndroid Build Coastguard Worker (unsigned char)((cp[stride] - cp[0]) & 0xff);
684*3ac0a46fSAndroid Build Coastguard Worker cp--)
685*3ac0a46fSAndroid Build Coastguard Worker } while ((cc -= stride) > 0);
686*3ac0a46fSAndroid Build Coastguard Worker }
687*3ac0a46fSAndroid Build Coastguard Worker }
688*3ac0a46fSAndroid Build Coastguard Worker return 1;
689*3ac0a46fSAndroid Build Coastguard Worker }
690*3ac0a46fSAndroid Build Coastguard Worker
691*3ac0a46fSAndroid Build Coastguard Worker TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW
horDiff16(TIFF * tif,uint8_t * cp0,tmsize_t cc)692*3ac0a46fSAndroid Build Coastguard Worker static int horDiff16(TIFF *tif, uint8_t *cp0, tmsize_t cc)
693*3ac0a46fSAndroid Build Coastguard Worker {
694*3ac0a46fSAndroid Build Coastguard Worker TIFFPredictorState *sp = PredictorState(tif);
695*3ac0a46fSAndroid Build Coastguard Worker tmsize_t stride = sp->stride;
696*3ac0a46fSAndroid Build Coastguard Worker uint16_t *wp = (uint16_t *)cp0;
697*3ac0a46fSAndroid Build Coastguard Worker tmsize_t wc = cc / 2;
698*3ac0a46fSAndroid Build Coastguard Worker
699*3ac0a46fSAndroid Build Coastguard Worker if ((cc % (2 * stride)) != 0)
700*3ac0a46fSAndroid Build Coastguard Worker {
701*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, "horDiff8", "%s", "(cc%(2*stride))!=0");
702*3ac0a46fSAndroid Build Coastguard Worker return 0;
703*3ac0a46fSAndroid Build Coastguard Worker }
704*3ac0a46fSAndroid Build Coastguard Worker
705*3ac0a46fSAndroid Build Coastguard Worker if (wc > stride)
706*3ac0a46fSAndroid Build Coastguard Worker {
707*3ac0a46fSAndroid Build Coastguard Worker wc -= stride;
708*3ac0a46fSAndroid Build Coastguard Worker wp += wc - 1;
709*3ac0a46fSAndroid Build Coastguard Worker do
710*3ac0a46fSAndroid Build Coastguard Worker {
711*3ac0a46fSAndroid Build Coastguard Worker REPEAT4(stride, wp[stride] = (uint16_t)(((unsigned int)wp[stride] -
712*3ac0a46fSAndroid Build Coastguard Worker (unsigned int)wp[0]) &
713*3ac0a46fSAndroid Build Coastguard Worker 0xffff);
714*3ac0a46fSAndroid Build Coastguard Worker wp--)
715*3ac0a46fSAndroid Build Coastguard Worker wc -= stride;
716*3ac0a46fSAndroid Build Coastguard Worker } while (wc > 0);
717*3ac0a46fSAndroid Build Coastguard Worker }
718*3ac0a46fSAndroid Build Coastguard Worker return 1;
719*3ac0a46fSAndroid Build Coastguard Worker }
720*3ac0a46fSAndroid Build Coastguard Worker
swabHorDiff16(TIFF * tif,uint8_t * cp0,tmsize_t cc)721*3ac0a46fSAndroid Build Coastguard Worker static int swabHorDiff16(TIFF *tif, uint8_t *cp0, tmsize_t cc)
722*3ac0a46fSAndroid Build Coastguard Worker {
723*3ac0a46fSAndroid Build Coastguard Worker uint16_t *wp = (uint16_t *)cp0;
724*3ac0a46fSAndroid Build Coastguard Worker tmsize_t wc = cc / 2;
725*3ac0a46fSAndroid Build Coastguard Worker
726*3ac0a46fSAndroid Build Coastguard Worker if (!horDiff16(tif, cp0, cc))
727*3ac0a46fSAndroid Build Coastguard Worker return 0;
728*3ac0a46fSAndroid Build Coastguard Worker
729*3ac0a46fSAndroid Build Coastguard Worker TIFFSwabArrayOfShort(wp, wc);
730*3ac0a46fSAndroid Build Coastguard Worker return 1;
731*3ac0a46fSAndroid Build Coastguard Worker }
732*3ac0a46fSAndroid Build Coastguard Worker
733*3ac0a46fSAndroid Build Coastguard Worker TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW
horDiff32(TIFF * tif,uint8_t * cp0,tmsize_t cc)734*3ac0a46fSAndroid Build Coastguard Worker static int horDiff32(TIFF *tif, uint8_t *cp0, tmsize_t cc)
735*3ac0a46fSAndroid Build Coastguard Worker {
736*3ac0a46fSAndroid Build Coastguard Worker TIFFPredictorState *sp = PredictorState(tif);
737*3ac0a46fSAndroid Build Coastguard Worker tmsize_t stride = sp->stride;
738*3ac0a46fSAndroid Build Coastguard Worker uint32_t *wp = (uint32_t *)cp0;
739*3ac0a46fSAndroid Build Coastguard Worker tmsize_t wc = cc / 4;
740*3ac0a46fSAndroid Build Coastguard Worker
741*3ac0a46fSAndroid Build Coastguard Worker if ((cc % (4 * stride)) != 0)
742*3ac0a46fSAndroid Build Coastguard Worker {
743*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, "horDiff32", "%s", "(cc%(4*stride))!=0");
744*3ac0a46fSAndroid Build Coastguard Worker return 0;
745*3ac0a46fSAndroid Build Coastguard Worker }
746*3ac0a46fSAndroid Build Coastguard Worker
747*3ac0a46fSAndroid Build Coastguard Worker if (wc > stride)
748*3ac0a46fSAndroid Build Coastguard Worker {
749*3ac0a46fSAndroid Build Coastguard Worker wc -= stride;
750*3ac0a46fSAndroid Build Coastguard Worker wp += wc - 1;
751*3ac0a46fSAndroid Build Coastguard Worker do
752*3ac0a46fSAndroid Build Coastguard Worker {
753*3ac0a46fSAndroid Build Coastguard Worker REPEAT4(stride, wp[stride] -= wp[0]; wp--)
754*3ac0a46fSAndroid Build Coastguard Worker wc -= stride;
755*3ac0a46fSAndroid Build Coastguard Worker } while (wc > 0);
756*3ac0a46fSAndroid Build Coastguard Worker }
757*3ac0a46fSAndroid Build Coastguard Worker return 1;
758*3ac0a46fSAndroid Build Coastguard Worker }
759*3ac0a46fSAndroid Build Coastguard Worker
swabHorDiff32(TIFF * tif,uint8_t * cp0,tmsize_t cc)760*3ac0a46fSAndroid Build Coastguard Worker static int swabHorDiff32(TIFF *tif, uint8_t *cp0, tmsize_t cc)
761*3ac0a46fSAndroid Build Coastguard Worker {
762*3ac0a46fSAndroid Build Coastguard Worker uint32_t *wp = (uint32_t *)cp0;
763*3ac0a46fSAndroid Build Coastguard Worker tmsize_t wc = cc / 4;
764*3ac0a46fSAndroid Build Coastguard Worker
765*3ac0a46fSAndroid Build Coastguard Worker if (!horDiff32(tif, cp0, cc))
766*3ac0a46fSAndroid Build Coastguard Worker return 0;
767*3ac0a46fSAndroid Build Coastguard Worker
768*3ac0a46fSAndroid Build Coastguard Worker TIFFSwabArrayOfLong(wp, wc);
769*3ac0a46fSAndroid Build Coastguard Worker return 1;
770*3ac0a46fSAndroid Build Coastguard Worker }
771*3ac0a46fSAndroid Build Coastguard Worker
772*3ac0a46fSAndroid Build Coastguard Worker TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW
horDiff64(TIFF * tif,uint8_t * cp0,tmsize_t cc)773*3ac0a46fSAndroid Build Coastguard Worker static int horDiff64(TIFF *tif, uint8_t *cp0, tmsize_t cc)
774*3ac0a46fSAndroid Build Coastguard Worker {
775*3ac0a46fSAndroid Build Coastguard Worker TIFFPredictorState *sp = PredictorState(tif);
776*3ac0a46fSAndroid Build Coastguard Worker tmsize_t stride = sp->stride;
777*3ac0a46fSAndroid Build Coastguard Worker uint64_t *wp = (uint64_t *)cp0;
778*3ac0a46fSAndroid Build Coastguard Worker tmsize_t wc = cc / 8;
779*3ac0a46fSAndroid Build Coastguard Worker
780*3ac0a46fSAndroid Build Coastguard Worker if ((cc % (8 * stride)) != 0)
781*3ac0a46fSAndroid Build Coastguard Worker {
782*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, "horDiff64", "%s", "(cc%(8*stride))!=0");
783*3ac0a46fSAndroid Build Coastguard Worker return 0;
784*3ac0a46fSAndroid Build Coastguard Worker }
785*3ac0a46fSAndroid Build Coastguard Worker
786*3ac0a46fSAndroid Build Coastguard Worker if (wc > stride)
787*3ac0a46fSAndroid Build Coastguard Worker {
788*3ac0a46fSAndroid Build Coastguard Worker wc -= stride;
789*3ac0a46fSAndroid Build Coastguard Worker wp += wc - 1;
790*3ac0a46fSAndroid Build Coastguard Worker do
791*3ac0a46fSAndroid Build Coastguard Worker {
792*3ac0a46fSAndroid Build Coastguard Worker REPEAT4(stride, wp[stride] -= wp[0]; wp--)
793*3ac0a46fSAndroid Build Coastguard Worker wc -= stride;
794*3ac0a46fSAndroid Build Coastguard Worker } while (wc > 0);
795*3ac0a46fSAndroid Build Coastguard Worker }
796*3ac0a46fSAndroid Build Coastguard Worker return 1;
797*3ac0a46fSAndroid Build Coastguard Worker }
798*3ac0a46fSAndroid Build Coastguard Worker
swabHorDiff64(TIFF * tif,uint8_t * cp0,tmsize_t cc)799*3ac0a46fSAndroid Build Coastguard Worker static int swabHorDiff64(TIFF *tif, uint8_t *cp0, tmsize_t cc)
800*3ac0a46fSAndroid Build Coastguard Worker {
801*3ac0a46fSAndroid Build Coastguard Worker uint64_t *wp = (uint64_t *)cp0;
802*3ac0a46fSAndroid Build Coastguard Worker tmsize_t wc = cc / 8;
803*3ac0a46fSAndroid Build Coastguard Worker
804*3ac0a46fSAndroid Build Coastguard Worker if (!horDiff64(tif, cp0, cc))
805*3ac0a46fSAndroid Build Coastguard Worker return 0;
806*3ac0a46fSAndroid Build Coastguard Worker
807*3ac0a46fSAndroid Build Coastguard Worker TIFFSwabArrayOfLong8(wp, wc);
808*3ac0a46fSAndroid Build Coastguard Worker return 1;
809*3ac0a46fSAndroid Build Coastguard Worker }
810*3ac0a46fSAndroid Build Coastguard Worker
811*3ac0a46fSAndroid Build Coastguard Worker /*
812*3ac0a46fSAndroid Build Coastguard Worker * Floating point predictor differencing routine.
813*3ac0a46fSAndroid Build Coastguard Worker */
814*3ac0a46fSAndroid Build Coastguard Worker TIFF_NOSANITIZE_UNSIGNED_INT_OVERFLOW
fpDiff(TIFF * tif,uint8_t * cp0,tmsize_t cc)815*3ac0a46fSAndroid Build Coastguard Worker static int fpDiff(TIFF *tif, uint8_t *cp0, tmsize_t cc)
816*3ac0a46fSAndroid Build Coastguard Worker {
817*3ac0a46fSAndroid Build Coastguard Worker tmsize_t stride = PredictorState(tif)->stride;
818*3ac0a46fSAndroid Build Coastguard Worker uint32_t bps = tif->tif_dir.td_bitspersample / 8;
819*3ac0a46fSAndroid Build Coastguard Worker tmsize_t wc = cc / bps;
820*3ac0a46fSAndroid Build Coastguard Worker tmsize_t count;
821*3ac0a46fSAndroid Build Coastguard Worker uint8_t *cp = (uint8_t *)cp0;
822*3ac0a46fSAndroid Build Coastguard Worker uint8_t *tmp;
823*3ac0a46fSAndroid Build Coastguard Worker
824*3ac0a46fSAndroid Build Coastguard Worker if ((cc % (bps * stride)) != 0)
825*3ac0a46fSAndroid Build Coastguard Worker {
826*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, "fpDiff", "%s", "(cc%(bps*stride))!=0");
827*3ac0a46fSAndroid Build Coastguard Worker return 0;
828*3ac0a46fSAndroid Build Coastguard Worker }
829*3ac0a46fSAndroid Build Coastguard Worker
830*3ac0a46fSAndroid Build Coastguard Worker tmp = (uint8_t *)_TIFFmallocExt(tif, cc);
831*3ac0a46fSAndroid Build Coastguard Worker if (!tmp)
832*3ac0a46fSAndroid Build Coastguard Worker return 0;
833*3ac0a46fSAndroid Build Coastguard Worker
834*3ac0a46fSAndroid Build Coastguard Worker _TIFFmemcpy(tmp, cp0, cc);
835*3ac0a46fSAndroid Build Coastguard Worker for (count = 0; count < wc; count++)
836*3ac0a46fSAndroid Build Coastguard Worker {
837*3ac0a46fSAndroid Build Coastguard Worker uint32_t byte;
838*3ac0a46fSAndroid Build Coastguard Worker for (byte = 0; byte < bps; byte++)
839*3ac0a46fSAndroid Build Coastguard Worker {
840*3ac0a46fSAndroid Build Coastguard Worker #if WORDS_BIGENDIAN
841*3ac0a46fSAndroid Build Coastguard Worker cp[byte * wc + count] = tmp[bps * count + byte];
842*3ac0a46fSAndroid Build Coastguard Worker #else
843*3ac0a46fSAndroid Build Coastguard Worker cp[(bps - byte - 1) * wc + count] = tmp[bps * count + byte];
844*3ac0a46fSAndroid Build Coastguard Worker #endif
845*3ac0a46fSAndroid Build Coastguard Worker }
846*3ac0a46fSAndroid Build Coastguard Worker }
847*3ac0a46fSAndroid Build Coastguard Worker _TIFFfreeExt(tif, tmp);
848*3ac0a46fSAndroid Build Coastguard Worker
849*3ac0a46fSAndroid Build Coastguard Worker cp = (uint8_t *)cp0;
850*3ac0a46fSAndroid Build Coastguard Worker cp += cc - stride - 1;
851*3ac0a46fSAndroid Build Coastguard Worker for (count = cc; count > stride; count -= stride)
852*3ac0a46fSAndroid Build Coastguard Worker REPEAT4(stride,
853*3ac0a46fSAndroid Build Coastguard Worker cp[stride] = (unsigned char)((cp[stride] - cp[0]) & 0xff);
854*3ac0a46fSAndroid Build Coastguard Worker cp--)
855*3ac0a46fSAndroid Build Coastguard Worker return 1;
856*3ac0a46fSAndroid Build Coastguard Worker }
857*3ac0a46fSAndroid Build Coastguard Worker
PredictorEncodeRow(TIFF * tif,uint8_t * bp,tmsize_t cc,uint16_t s)858*3ac0a46fSAndroid Build Coastguard Worker static int PredictorEncodeRow(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
859*3ac0a46fSAndroid Build Coastguard Worker {
860*3ac0a46fSAndroid Build Coastguard Worker TIFFPredictorState *sp = PredictorState(tif);
861*3ac0a46fSAndroid Build Coastguard Worker
862*3ac0a46fSAndroid Build Coastguard Worker assert(sp != NULL);
863*3ac0a46fSAndroid Build Coastguard Worker assert(sp->encodepfunc != NULL);
864*3ac0a46fSAndroid Build Coastguard Worker assert(sp->encoderow != NULL);
865*3ac0a46fSAndroid Build Coastguard Worker
866*3ac0a46fSAndroid Build Coastguard Worker /* XXX horizontal differencing alters user's data XXX */
867*3ac0a46fSAndroid Build Coastguard Worker if (!(*sp->encodepfunc)(tif, bp, cc))
868*3ac0a46fSAndroid Build Coastguard Worker return 0;
869*3ac0a46fSAndroid Build Coastguard Worker return (*sp->encoderow)(tif, bp, cc, s);
870*3ac0a46fSAndroid Build Coastguard Worker }
871*3ac0a46fSAndroid Build Coastguard Worker
PredictorEncodeTile(TIFF * tif,uint8_t * bp0,tmsize_t cc0,uint16_t s)872*3ac0a46fSAndroid Build Coastguard Worker static int PredictorEncodeTile(TIFF *tif, uint8_t *bp0, tmsize_t cc0,
873*3ac0a46fSAndroid Build Coastguard Worker uint16_t s)
874*3ac0a46fSAndroid Build Coastguard Worker {
875*3ac0a46fSAndroid Build Coastguard Worker static const char module[] = "PredictorEncodeTile";
876*3ac0a46fSAndroid Build Coastguard Worker TIFFPredictorState *sp = PredictorState(tif);
877*3ac0a46fSAndroid Build Coastguard Worker uint8_t *working_copy;
878*3ac0a46fSAndroid Build Coastguard Worker tmsize_t cc = cc0, rowsize;
879*3ac0a46fSAndroid Build Coastguard Worker unsigned char *bp;
880*3ac0a46fSAndroid Build Coastguard Worker int result_code;
881*3ac0a46fSAndroid Build Coastguard Worker
882*3ac0a46fSAndroid Build Coastguard Worker assert(sp != NULL);
883*3ac0a46fSAndroid Build Coastguard Worker assert(sp->encodepfunc != NULL);
884*3ac0a46fSAndroid Build Coastguard Worker assert(sp->encodetile != NULL);
885*3ac0a46fSAndroid Build Coastguard Worker
886*3ac0a46fSAndroid Build Coastguard Worker /*
887*3ac0a46fSAndroid Build Coastguard Worker * Do predictor manipulation in a working buffer to avoid altering
888*3ac0a46fSAndroid Build Coastguard Worker * the callers buffer. http://trac.osgeo.org/gdal/ticket/1965
889*3ac0a46fSAndroid Build Coastguard Worker */
890*3ac0a46fSAndroid Build Coastguard Worker working_copy = (uint8_t *)_TIFFmallocExt(tif, cc0);
891*3ac0a46fSAndroid Build Coastguard Worker if (working_copy == NULL)
892*3ac0a46fSAndroid Build Coastguard Worker {
893*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, module,
894*3ac0a46fSAndroid Build Coastguard Worker "Out of memory allocating %" PRId64 " byte temp buffer.",
895*3ac0a46fSAndroid Build Coastguard Worker (int64_t)cc0);
896*3ac0a46fSAndroid Build Coastguard Worker return 0;
897*3ac0a46fSAndroid Build Coastguard Worker }
898*3ac0a46fSAndroid Build Coastguard Worker memcpy(working_copy, bp0, cc0);
899*3ac0a46fSAndroid Build Coastguard Worker bp = working_copy;
900*3ac0a46fSAndroid Build Coastguard Worker
901*3ac0a46fSAndroid Build Coastguard Worker rowsize = sp->rowsize;
902*3ac0a46fSAndroid Build Coastguard Worker assert(rowsize > 0);
903*3ac0a46fSAndroid Build Coastguard Worker if ((cc0 % rowsize) != 0)
904*3ac0a46fSAndroid Build Coastguard Worker {
905*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, "PredictorEncodeTile", "%s", "(cc0%rowsize)!=0");
906*3ac0a46fSAndroid Build Coastguard Worker _TIFFfreeExt(tif, working_copy);
907*3ac0a46fSAndroid Build Coastguard Worker return 0;
908*3ac0a46fSAndroid Build Coastguard Worker }
909*3ac0a46fSAndroid Build Coastguard Worker while (cc > 0)
910*3ac0a46fSAndroid Build Coastguard Worker {
911*3ac0a46fSAndroid Build Coastguard Worker (*sp->encodepfunc)(tif, bp, rowsize);
912*3ac0a46fSAndroid Build Coastguard Worker cc -= rowsize;
913*3ac0a46fSAndroid Build Coastguard Worker bp += rowsize;
914*3ac0a46fSAndroid Build Coastguard Worker }
915*3ac0a46fSAndroid Build Coastguard Worker result_code = (*sp->encodetile)(tif, working_copy, cc0, s);
916*3ac0a46fSAndroid Build Coastguard Worker
917*3ac0a46fSAndroid Build Coastguard Worker _TIFFfreeExt(tif, working_copy);
918*3ac0a46fSAndroid Build Coastguard Worker
919*3ac0a46fSAndroid Build Coastguard Worker return result_code;
920*3ac0a46fSAndroid Build Coastguard Worker }
921*3ac0a46fSAndroid Build Coastguard Worker
922*3ac0a46fSAndroid Build Coastguard Worker #define FIELD_PREDICTOR (FIELD_CODEC + 0) /* XXX */
923*3ac0a46fSAndroid Build Coastguard Worker
924*3ac0a46fSAndroid Build Coastguard Worker static const TIFFField predictFields[] = {
925*3ac0a46fSAndroid Build Coastguard Worker {TIFFTAG_PREDICTOR, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16,
926*3ac0a46fSAndroid Build Coastguard Worker TIFF_SETGET_UINT16, FIELD_PREDICTOR, FALSE, FALSE, "Predictor", NULL},
927*3ac0a46fSAndroid Build Coastguard Worker };
928*3ac0a46fSAndroid Build Coastguard Worker
PredictorVSetField(TIFF * tif,uint32_t tag,va_list ap)929*3ac0a46fSAndroid Build Coastguard Worker static int PredictorVSetField(TIFF *tif, uint32_t tag, va_list ap)
930*3ac0a46fSAndroid Build Coastguard Worker {
931*3ac0a46fSAndroid Build Coastguard Worker TIFFPredictorState *sp = PredictorState(tif);
932*3ac0a46fSAndroid Build Coastguard Worker
933*3ac0a46fSAndroid Build Coastguard Worker assert(sp != NULL);
934*3ac0a46fSAndroid Build Coastguard Worker assert(sp->vsetparent != NULL);
935*3ac0a46fSAndroid Build Coastguard Worker
936*3ac0a46fSAndroid Build Coastguard Worker switch (tag)
937*3ac0a46fSAndroid Build Coastguard Worker {
938*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_PREDICTOR:
939*3ac0a46fSAndroid Build Coastguard Worker sp->predictor = (uint16_t)va_arg(ap, uint16_vap);
940*3ac0a46fSAndroid Build Coastguard Worker TIFFSetFieldBit(tif, FIELD_PREDICTOR);
941*3ac0a46fSAndroid Build Coastguard Worker break;
942*3ac0a46fSAndroid Build Coastguard Worker default:
943*3ac0a46fSAndroid Build Coastguard Worker return (*sp->vsetparent)(tif, tag, ap);
944*3ac0a46fSAndroid Build Coastguard Worker }
945*3ac0a46fSAndroid Build Coastguard Worker tif->tif_flags |= TIFF_DIRTYDIRECT;
946*3ac0a46fSAndroid Build Coastguard Worker return 1;
947*3ac0a46fSAndroid Build Coastguard Worker }
948*3ac0a46fSAndroid Build Coastguard Worker
PredictorVGetField(TIFF * tif,uint32_t tag,va_list ap)949*3ac0a46fSAndroid Build Coastguard Worker static int PredictorVGetField(TIFF *tif, uint32_t tag, va_list ap)
950*3ac0a46fSAndroid Build Coastguard Worker {
951*3ac0a46fSAndroid Build Coastguard Worker TIFFPredictorState *sp = PredictorState(tif);
952*3ac0a46fSAndroid Build Coastguard Worker
953*3ac0a46fSAndroid Build Coastguard Worker assert(sp != NULL);
954*3ac0a46fSAndroid Build Coastguard Worker assert(sp->vgetparent != NULL);
955*3ac0a46fSAndroid Build Coastguard Worker
956*3ac0a46fSAndroid Build Coastguard Worker switch (tag)
957*3ac0a46fSAndroid Build Coastguard Worker {
958*3ac0a46fSAndroid Build Coastguard Worker case TIFFTAG_PREDICTOR:
959*3ac0a46fSAndroid Build Coastguard Worker *va_arg(ap, uint16_t *) = (uint16_t)sp->predictor;
960*3ac0a46fSAndroid Build Coastguard Worker break;
961*3ac0a46fSAndroid Build Coastguard Worker default:
962*3ac0a46fSAndroid Build Coastguard Worker return (*sp->vgetparent)(tif, tag, ap);
963*3ac0a46fSAndroid Build Coastguard Worker }
964*3ac0a46fSAndroid Build Coastguard Worker return 1;
965*3ac0a46fSAndroid Build Coastguard Worker }
966*3ac0a46fSAndroid Build Coastguard Worker
PredictorPrintDir(TIFF * tif,FILE * fd,long flags)967*3ac0a46fSAndroid Build Coastguard Worker static void PredictorPrintDir(TIFF *tif, FILE *fd, long flags)
968*3ac0a46fSAndroid Build Coastguard Worker {
969*3ac0a46fSAndroid Build Coastguard Worker TIFFPredictorState *sp = PredictorState(tif);
970*3ac0a46fSAndroid Build Coastguard Worker
971*3ac0a46fSAndroid Build Coastguard Worker (void)flags;
972*3ac0a46fSAndroid Build Coastguard Worker if (TIFFFieldSet(tif, FIELD_PREDICTOR))
973*3ac0a46fSAndroid Build Coastguard Worker {
974*3ac0a46fSAndroid Build Coastguard Worker fprintf(fd, " Predictor: ");
975*3ac0a46fSAndroid Build Coastguard Worker switch (sp->predictor)
976*3ac0a46fSAndroid Build Coastguard Worker {
977*3ac0a46fSAndroid Build Coastguard Worker case 1:
978*3ac0a46fSAndroid Build Coastguard Worker fprintf(fd, "none ");
979*3ac0a46fSAndroid Build Coastguard Worker break;
980*3ac0a46fSAndroid Build Coastguard Worker case 2:
981*3ac0a46fSAndroid Build Coastguard Worker fprintf(fd, "horizontal differencing ");
982*3ac0a46fSAndroid Build Coastguard Worker break;
983*3ac0a46fSAndroid Build Coastguard Worker case 3:
984*3ac0a46fSAndroid Build Coastguard Worker fprintf(fd, "floating point predictor ");
985*3ac0a46fSAndroid Build Coastguard Worker break;
986*3ac0a46fSAndroid Build Coastguard Worker }
987*3ac0a46fSAndroid Build Coastguard Worker fprintf(fd, "%d (0x%x)\n", sp->predictor, sp->predictor);
988*3ac0a46fSAndroid Build Coastguard Worker }
989*3ac0a46fSAndroid Build Coastguard Worker if (sp->printdir)
990*3ac0a46fSAndroid Build Coastguard Worker (*sp->printdir)(tif, fd, flags);
991*3ac0a46fSAndroid Build Coastguard Worker }
992*3ac0a46fSAndroid Build Coastguard Worker
TIFFPredictorInit(TIFF * tif)993*3ac0a46fSAndroid Build Coastguard Worker int TIFFPredictorInit(TIFF *tif)
994*3ac0a46fSAndroid Build Coastguard Worker {
995*3ac0a46fSAndroid Build Coastguard Worker TIFFPredictorState *sp = PredictorState(tif);
996*3ac0a46fSAndroid Build Coastguard Worker
997*3ac0a46fSAndroid Build Coastguard Worker assert(sp != 0);
998*3ac0a46fSAndroid Build Coastguard Worker
999*3ac0a46fSAndroid Build Coastguard Worker /*
1000*3ac0a46fSAndroid Build Coastguard Worker * Merge codec-specific tag information.
1001*3ac0a46fSAndroid Build Coastguard Worker */
1002*3ac0a46fSAndroid Build Coastguard Worker if (!_TIFFMergeFields(tif, predictFields, TIFFArrayCount(predictFields)))
1003*3ac0a46fSAndroid Build Coastguard Worker {
1004*3ac0a46fSAndroid Build Coastguard Worker TIFFErrorExtR(tif, "TIFFPredictorInit",
1005*3ac0a46fSAndroid Build Coastguard Worker "Merging Predictor codec-specific tags failed");
1006*3ac0a46fSAndroid Build Coastguard Worker return 0;
1007*3ac0a46fSAndroid Build Coastguard Worker }
1008*3ac0a46fSAndroid Build Coastguard Worker
1009*3ac0a46fSAndroid Build Coastguard Worker /*
1010*3ac0a46fSAndroid Build Coastguard Worker * Override parent get/set field methods.
1011*3ac0a46fSAndroid Build Coastguard Worker */
1012*3ac0a46fSAndroid Build Coastguard Worker sp->vgetparent = tif->tif_tagmethods.vgetfield;
1013*3ac0a46fSAndroid Build Coastguard Worker tif->tif_tagmethods.vgetfield =
1014*3ac0a46fSAndroid Build Coastguard Worker PredictorVGetField; /* hook for predictor tag */
1015*3ac0a46fSAndroid Build Coastguard Worker sp->vsetparent = tif->tif_tagmethods.vsetfield;
1016*3ac0a46fSAndroid Build Coastguard Worker tif->tif_tagmethods.vsetfield =
1017*3ac0a46fSAndroid Build Coastguard Worker PredictorVSetField; /* hook for predictor tag */
1018*3ac0a46fSAndroid Build Coastguard Worker sp->printdir = tif->tif_tagmethods.printdir;
1019*3ac0a46fSAndroid Build Coastguard Worker tif->tif_tagmethods.printdir =
1020*3ac0a46fSAndroid Build Coastguard Worker PredictorPrintDir; /* hook for predictor tag */
1021*3ac0a46fSAndroid Build Coastguard Worker
1022*3ac0a46fSAndroid Build Coastguard Worker sp->setupdecode = tif->tif_setupdecode;
1023*3ac0a46fSAndroid Build Coastguard Worker tif->tif_setupdecode = PredictorSetupDecode;
1024*3ac0a46fSAndroid Build Coastguard Worker sp->setupencode = tif->tif_setupencode;
1025*3ac0a46fSAndroid Build Coastguard Worker tif->tif_setupencode = PredictorSetupEncode;
1026*3ac0a46fSAndroid Build Coastguard Worker
1027*3ac0a46fSAndroid Build Coastguard Worker sp->predictor = 1; /* default value */
1028*3ac0a46fSAndroid Build Coastguard Worker sp->encodepfunc = NULL; /* no predictor routine */
1029*3ac0a46fSAndroid Build Coastguard Worker sp->decodepfunc = NULL; /* no predictor routine */
1030*3ac0a46fSAndroid Build Coastguard Worker return 1;
1031*3ac0a46fSAndroid Build Coastguard Worker }
1032*3ac0a46fSAndroid Build Coastguard Worker
TIFFPredictorCleanup(TIFF * tif)1033*3ac0a46fSAndroid Build Coastguard Worker int TIFFPredictorCleanup(TIFF *tif)
1034*3ac0a46fSAndroid Build Coastguard Worker {
1035*3ac0a46fSAndroid Build Coastguard Worker TIFFPredictorState *sp = PredictorState(tif);
1036*3ac0a46fSAndroid Build Coastguard Worker
1037*3ac0a46fSAndroid Build Coastguard Worker assert(sp != 0);
1038*3ac0a46fSAndroid Build Coastguard Worker
1039*3ac0a46fSAndroid Build Coastguard Worker tif->tif_tagmethods.vgetfield = sp->vgetparent;
1040*3ac0a46fSAndroid Build Coastguard Worker tif->tif_tagmethods.vsetfield = sp->vsetparent;
1041*3ac0a46fSAndroid Build Coastguard Worker tif->tif_tagmethods.printdir = sp->printdir;
1042*3ac0a46fSAndroid Build Coastguard Worker tif->tif_setupdecode = sp->setupdecode;
1043*3ac0a46fSAndroid Build Coastguard Worker tif->tif_setupencode = sp->setupencode;
1044*3ac0a46fSAndroid Build Coastguard Worker
1045*3ac0a46fSAndroid Build Coastguard Worker return 1;
1046*3ac0a46fSAndroid Build Coastguard Worker }
1047