xref: /aosp_15_r20/external/pdfium/third_party/libtiff/tif_predict.c (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
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