• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* $Id: tif_predict.c,v 1.32 2010-03-10 18:56:49 bfriesen Exp $ */
2 
3 /*
4  * Copyright (c) 1988-1997 Sam Leffler
5  * Copyright (c) 1991-1997 Silicon Graphics, Inc.
6  *
7  * Permission to use, copy, modify, distribute, and sell this software and
8  * its documentation for any purpose is hereby granted without fee, provided
9  * that (i) the above copyright notices and this permission notice appear in
10  * all copies of the software and related documentation, and (ii) the names of
11  * Sam Leffler and Silicon Graphics may not be used in any advertising or
12  * publicity relating to the software without the specific, prior written
13  * permission of Sam Leffler and Silicon Graphics.
14  *
15  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
17  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
18  *
19  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
20  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
21  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
22  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
23  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
24  * OF THIS SOFTWARE.
25  */
26 
27 /*
28  * TIFF Library.
29  *
30  * Predictor Tag Support (used by multiple codecs).
31  */
32 #include "tiffiop.h"
33 #include "tif_predict.h"
34 
35 #define	PredictorState(tif)	((TIFFPredictorState*) (tif)->tif_data)
36 
37 static void horAcc8(TIFF* tif, uint8* cp0, tmsize_t cc);
38 static void horAcc16(TIFF* tif, uint8* cp0, tmsize_t cc);
39 static void horAcc32(TIFF* tif, uint8* cp0, tmsize_t cc);
40 static void swabHorAcc16(TIFF* tif, uint8* cp0, tmsize_t cc);
41 static void swabHorAcc32(TIFF* tif, uint8* cp0, tmsize_t cc);
42 static void horDiff8(TIFF* tif, uint8* cp0, tmsize_t cc);
43 static void horDiff16(TIFF* tif, uint8* cp0, tmsize_t cc);
44 static void horDiff32(TIFF* tif, uint8* cp0, tmsize_t cc);
45 static void fpAcc(TIFF* tif, uint8* cp0, tmsize_t cc);
46 static void fpDiff(TIFF* tif, uint8* cp0, tmsize_t cc);
47 static int PredictorDecodeRow(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s);
48 static int PredictorDecodeTile(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s);
49 static int PredictorEncodeRow(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s);
50 static int PredictorEncodeTile(TIFF* tif, uint8* bp0, tmsize_t cc0, uint16 s);
51 
52 static int
PredictorSetup(TIFF * tif)53 PredictorSetup(TIFF* tif)
54 {
55     static const char module[] = "PredictorSetup";
56 
57     TIFFPredictorState* sp = PredictorState(tif);
58     TIFFDirectory* td = &tif->tif_dir;
59 
60     switch (sp->predictor)		/* no differencing */
61     {
62         case PREDICTOR_NONE:
63             return 1;
64         case PREDICTOR_HORIZONTAL:
65             if (td->td_bitspersample != 8
66                 && td->td_bitspersample != 16
67                 && td->td_bitspersample != 32) {
68                 TIFFErrorExt(tif->tif_clientdata, module,
69                     "Horizontal differencing \"Predictor\" not supported with %d-bit samples",
70                     td->td_bitspersample);
71                 return 0;
72             }
73             break;
74         case PREDICTOR_FLOATINGPOINT:
75             if (td->td_sampleformat != SAMPLEFORMAT_IEEEFP) {
76                 TIFFErrorExt(tif->tif_clientdata, module,
77                     "Floating point \"Predictor\" not supported with %d data format",
78                     td->td_sampleformat);
79                 return 0;
80             }
81             break;
82         default:
83             TIFFErrorExt(tif->tif_clientdata, module,
84                 "\"Predictor\" value %d not supported",
85                 sp->predictor);
86             return 0;
87     }
88     sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ?
89         td->td_samplesperpixel : 1);
90     /*
91      * Calculate the scanline/tile-width size in bytes.
92      */
93     if (isTiled(tif))
94         sp->rowsize = TIFFTileRowSize(tif);
95     else
96         sp->rowsize = TIFFScanlineSize(tif);
97     if (sp->rowsize == 0)
98         return 0;
99 
100     return 1;
101 }
102 
103 static int
PredictorSetupDecode(TIFF * tif)104 PredictorSetupDecode(TIFF* tif)
105 {
106     TIFFPredictorState* sp = PredictorState(tif);
107     TIFFDirectory* td = &tif->tif_dir;
108 
109     if (!(*sp->setupdecode)(tif) || !PredictorSetup(tif))
110         return 0;
111 
112     if (sp->predictor == 2) {
113         switch (td->td_bitspersample) {
114             case 8:  sp->decodepfunc = horAcc8; break;
115             case 16: sp->decodepfunc = horAcc16; break;
116             case 32: sp->decodepfunc = horAcc32; break;
117         }
118         /*
119          * Override default decoding method with one that does the
120          * predictor stuff.
121          */
122                 if( tif->tif_decoderow != PredictorDecodeRow )
123                 {
124                     sp->decoderow = tif->tif_decoderow;
125                     tif->tif_decoderow = PredictorDecodeRow;
126                     sp->decodestrip = tif->tif_decodestrip;
127                     tif->tif_decodestrip = PredictorDecodeTile;
128                     sp->decodetile = tif->tif_decodetile;
129                     tif->tif_decodetile = PredictorDecodeTile;
130                 }
131 
132         /*
133          * If the data is horizontally differenced 16-bit data that
134          * requires byte-swapping, then it must be byte swapped before
135          * the accumulation step.  We do this with a special-purpose
136          * routine and override the normal post decoding logic that
137          * the library setup when the directory was read.
138          */
139         if (tif->tif_flags & TIFF_SWAB) {
140             if (sp->decodepfunc == horAcc16) {
141                 sp->decodepfunc = swabHorAcc16;
142                 tif->tif_postdecode = _TIFFNoPostDecode;
143             } else if (sp->decodepfunc == horAcc32) {
144                 sp->decodepfunc = swabHorAcc32;
145                 tif->tif_postdecode = _TIFFNoPostDecode;
146             }
147         }
148     }
149 
150     else if (sp->predictor == 3) {
151         sp->decodepfunc = fpAcc;
152         /*
153          * Override default decoding method with one that does the
154          * predictor stuff.
155          */
156                 if( tif->tif_decoderow != PredictorDecodeRow )
157                 {
158                     sp->decoderow = tif->tif_decoderow;
159                     tif->tif_decoderow = PredictorDecodeRow;
160                     sp->decodestrip = tif->tif_decodestrip;
161                     tif->tif_decodestrip = PredictorDecodeTile;
162                     sp->decodetile = tif->tif_decodetile;
163                     tif->tif_decodetile = PredictorDecodeTile;
164                 }
165         /*
166          * The data should not be swapped outside of the floating
167          * point predictor, the accumulation routine should return
168          * byres in the native order.
169          */
170         if (tif->tif_flags & TIFF_SWAB) {
171             tif->tif_postdecode = _TIFFNoPostDecode;
172         }
173         /*
174          * Allocate buffer to keep the decoded bytes before
175          * rearranging in the ight order
176          */
177     }
178 
179     return 1;
180 }
181 
182 static int
PredictorSetupEncode(TIFF * tif)183 PredictorSetupEncode(TIFF* tif)
184 {
185     TIFFPredictorState* sp = PredictorState(tif);
186     TIFFDirectory* td = &tif->tif_dir;
187 
188     if (!(*sp->setupencode)(tif) || !PredictorSetup(tif))
189         return 0;
190 
191     if (sp->predictor == 2) {
192         switch (td->td_bitspersample) {
193             case 8:  sp->encodepfunc = horDiff8; break;
194             case 16: sp->encodepfunc = horDiff16; break;
195             case 32: sp->encodepfunc = horDiff32; break;
196         }
197         /*
198          * Override default encoding method with one that does the
199          * predictor stuff.
200          */
201                 if( tif->tif_encoderow != PredictorEncodeRow )
202                 {
203                     sp->encoderow = tif->tif_encoderow;
204                     tif->tif_encoderow = PredictorEncodeRow;
205                     sp->encodestrip = tif->tif_encodestrip;
206                     tif->tif_encodestrip = PredictorEncodeTile;
207                     sp->encodetile = tif->tif_encodetile;
208                     tif->tif_encodetile = PredictorEncodeTile;
209                 }
210     }
211 
212     else if (sp->predictor == 3) {
213         sp->encodepfunc = fpDiff;
214         /*
215          * Override default encoding method with one that does the
216          * predictor stuff.
217          */
218                 if( tif->tif_encoderow != PredictorEncodeRow )
219                 {
220                     sp->encoderow = tif->tif_encoderow;
221                     tif->tif_encoderow = PredictorEncodeRow;
222                     sp->encodestrip = tif->tif_encodestrip;
223                     tif->tif_encodestrip = PredictorEncodeTile;
224                     sp->encodetile = tif->tif_encodetile;
225                     tif->tif_encodetile = PredictorEncodeTile;
226                 }
227     }
228 
229     return 1;
230 }
231 
232 #define REPEAT4(n, op)		\
233     switch (n) {		\
234     default: { tmsize_t i; for (i = n-4; i > 0; i--) { op; } } \
235     case 4:  op;		\
236     case 3:  op;		\
237     case 2:  op;		\
238     case 1:  op;		\
239     case 0:  ;			\
240     }
241 
242 static void
horAcc8(TIFF * tif,uint8 * cp0,tmsize_t cc)243 horAcc8(TIFF* tif, uint8* cp0, tmsize_t cc)
244 {
245     tmsize_t stride = PredictorState(tif)->stride;
246 
247     char* cp = (char*) cp0;
248     assert((cc%stride)==0);
249     if (cc > stride) {
250         /*
251          * Pipeline the most common cases.
252          */
253         if (stride == 3)  {
254             unsigned int cr = cp[0];
255             unsigned int cg = cp[1];
256             unsigned int cb = cp[2];
257             cc -= 3;
258             cp += 3;
259             while (cc>0) {
260                 cp[0] = (char) (cr += cp[0]);
261                 cp[1] = (char) (cg += cp[1]);
262                 cp[2] = (char) (cb += cp[2]);
263                 cc -= 3;
264                 cp += 3;
265             }
266         } else if (stride == 4)  {
267             unsigned int cr = cp[0];
268             unsigned int cg = cp[1];
269             unsigned int cb = cp[2];
270             unsigned int ca = cp[3];
271             cc -= 4;
272             cp += 4;
273             while (cc>0) {
274                 cp[0] = (char) (cr += cp[0]);
275                 cp[1] = (char) (cg += cp[1]);
276                 cp[2] = (char) (cb += cp[2]);
277                 cp[3] = (char) (ca += cp[3]);
278                 cc -= 4;
279                 cp += 4;
280             }
281         } else  {
282             cc -= stride;
283             do {
284                 REPEAT4(stride, cp[stride] =
285                     (char) (cp[stride] + *cp); cp++)
286                 cc -= stride;
287             } while (cc>0);
288         }
289     }
290 }
291 
292 static void
swabHorAcc16(TIFF * tif,uint8 * cp0,tmsize_t cc)293 swabHorAcc16(TIFF* tif, uint8* cp0, tmsize_t cc)
294 {
295     tmsize_t stride = PredictorState(tif)->stride;
296     uint16* wp = (uint16*) cp0;
297     tmsize_t wc = cc / 2;
298 
299     assert((cc%(2*stride))==0);
300 
301     if (wc > stride) {
302         TIFFSwabArrayOfShort(wp, wc);
303         wc -= stride;
304         do {
305             REPEAT4(stride, wp[stride] += wp[0]; wp++)
306             wc -= stride;
307         } while (wc > 0);
308     }
309 }
310 
311 static void
horAcc16(TIFF * tif,uint8 * cp0,tmsize_t cc)312 horAcc16(TIFF* tif, uint8* cp0, tmsize_t cc)
313 {
314     tmsize_t stride = PredictorState(tif)->stride;
315     uint16* wp = (uint16*) cp0;
316     tmsize_t wc = cc / 2;
317 
318     assert((cc%(2*stride))==0);
319 
320     if (wc > stride) {
321         wc -= stride;
322         do {
323             REPEAT4(stride, wp[stride] += wp[0]; wp++)
324             wc -= stride;
325         } while (wc > 0);
326     }
327 }
328 
329 static void
swabHorAcc32(TIFF * tif,uint8 * cp0,tmsize_t cc)330 swabHorAcc32(TIFF* tif, uint8* cp0, tmsize_t cc)
331 {
332     tmsize_t stride = PredictorState(tif)->stride;
333     uint32* wp = (uint32*) cp0;
334     tmsize_t wc = cc / 4;
335 
336     assert((cc%(4*stride))==0);
337 
338     if (wc > stride) {
339         TIFFSwabArrayOfLong(wp, wc);
340         wc -= stride;
341         do {
342             REPEAT4(stride, wp[stride] += wp[0]; wp++)
343             wc -= stride;
344         } while (wc > 0);
345     }
346 }
347 
348 static void
horAcc32(TIFF * tif,uint8 * cp0,tmsize_t cc)349 horAcc32(TIFF* tif, uint8* cp0, tmsize_t cc)
350 {
351     tmsize_t stride = PredictorState(tif)->stride;
352     uint32* wp = (uint32*) cp0;
353     tmsize_t wc = cc / 4;
354 
355     assert((cc%(4*stride))==0);
356 
357     if (wc > stride) {
358         wc -= stride;
359         do {
360             REPEAT4(stride, wp[stride] += wp[0]; wp++)
361             wc -= stride;
362         } while (wc > 0);
363     }
364 }
365 
366 /*
367  * Floating point predictor accumulation routine.
368  */
369 static void
fpAcc(TIFF * tif,uint8 * cp0,tmsize_t cc)370 fpAcc(TIFF* tif, uint8* cp0, tmsize_t cc)
371 {
372     tmsize_t stride = PredictorState(tif)->stride;
373     uint32 bps = tif->tif_dir.td_bitspersample / 8;
374     tmsize_t wc = cc / bps;
375     tmsize_t count = cc;
376     uint8 *cp = (uint8 *) cp0;
377     uint8 *tmp = (uint8 *)_TIFFmalloc(cc);
378 
379     assert((cc%(bps*stride))==0);
380 
381     if (!tmp)
382         return;
383 
384     while (count > stride) {
385         REPEAT4(stride, cp[stride] += cp[0]; cp++)
386         count -= stride;
387     }
388 
389     _TIFFmemcpy(tmp, cp0, cc);
390     cp = (uint8 *) cp0;
391     for (count = 0; count < wc; count++) {
392         uint32 byte;
393         for (byte = 0; byte < bps; byte++) {
394             #if WORDS_BIGENDIAN
395             cp[bps * count + byte] = tmp[byte * wc + count];
396             #else
397             cp[bps * count + byte] =
398                 tmp[(bps - byte - 1) * wc + count];
399             #endif
400         }
401     }
402     _TIFFfree(tmp);
403 }
404 
405 /*
406  * Decode a scanline and apply the predictor routine.
407  */
408 static int
PredictorDecodeRow(TIFF * tif,uint8 * op0,tmsize_t occ0,uint16 s)409 PredictorDecodeRow(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s)
410 {
411     TIFFPredictorState *sp = PredictorState(tif);
412 
413     assert(sp != NULL);
414     assert(sp->decoderow != NULL);
415     assert(sp->decodepfunc != NULL);
416 
417     if ((*sp->decoderow)(tif, op0, occ0, s)) {
418         (*sp->decodepfunc)(tif, op0, occ0);
419         return 1;
420     } else
421         return 0;
422 }
423 
424 /*
425  * Decode a tile/strip and apply the predictor routine.
426  * Note that horizontal differencing must be done on a
427  * row-by-row basis.  The width of a "row" has already
428  * been calculated at pre-decode time according to the
429  * strip/tile dimensions.
430  */
431 static int
PredictorDecodeTile(TIFF * tif,uint8 * op0,tmsize_t occ0,uint16 s)432 PredictorDecodeTile(TIFF* tif, uint8* op0, tmsize_t occ0, uint16 s)
433 {
434     TIFFPredictorState *sp = PredictorState(tif);
435 
436     assert(sp != NULL);
437     assert(sp->decodetile != NULL);
438 
439     if ((*sp->decodetile)(tif, op0, occ0, s)) {
440         tmsize_t rowsize = sp->rowsize;
441         assert(rowsize > 0);
442         assert((occ0%rowsize)==0);
443         assert(sp->decodepfunc != NULL);
444         while (occ0 > 0) {
445             (*sp->decodepfunc)(tif, op0, rowsize);
446             occ0 -= rowsize;
447             op0 += rowsize;
448         }
449         return 1;
450     } else
451         return 0;
452 }
453 
454 static void
horDiff8(TIFF * tif,uint8 * cp0,tmsize_t cc)455 horDiff8(TIFF* tif, uint8* cp0, tmsize_t cc)
456 {
457     TIFFPredictorState* sp = PredictorState(tif);
458     tmsize_t stride = sp->stride;
459     char* cp = (char*) cp0;
460 
461     assert((cc%stride)==0);
462 
463     if (cc > stride) {
464         cc -= stride;
465         /*
466          * Pipeline the most common cases.
467          */
468         if (stride == 3) {
469             int r1, g1, b1;
470             int r2 = cp[0];
471             int g2 = cp[1];
472             int b2 = cp[2];
473             do {
474                 r1 = cp[3]; cp[3] = r1-r2; r2 = r1;
475                 g1 = cp[4]; cp[4] = g1-g2; g2 = g1;
476                 b1 = cp[5]; cp[5] = b1-b2; b2 = b1;
477                 cp += 3;
478             } while ((cc -= 3) > 0);
479         } else if (stride == 4) {
480             int r1, g1, b1, a1;
481             int r2 = cp[0];
482             int g2 = cp[1];
483             int b2 = cp[2];
484             int a2 = cp[3];
485             do {
486                 r1 = cp[4]; cp[4] = r1-r2; r2 = r1;
487                 g1 = cp[5]; cp[5] = g1-g2; g2 = g1;
488                 b1 = cp[6]; cp[6] = b1-b2; b2 = b1;
489                 a1 = cp[7]; cp[7] = a1-a2; a2 = a1;
490                 cp += 4;
491             } while ((cc -= 4) > 0);
492         } else {
493             cp += cc - 1;
494             do {
495                 REPEAT4(stride, cp[stride] -= cp[0]; cp--)
496             } while ((cc -= stride) > 0);
497         }
498     }
499 }
500 
501 static void
horDiff16(TIFF * tif,uint8 * cp0,tmsize_t cc)502 horDiff16(TIFF* tif, uint8* cp0, tmsize_t cc)
503 {
504     TIFFPredictorState* sp = PredictorState(tif);
505     tmsize_t stride = sp->stride;
506     int16 *wp = (int16*) cp0;
507     tmsize_t wc = cc/2;
508 
509     assert((cc%(2*stride))==0);
510 
511     if (wc > stride) {
512         wc -= stride;
513         wp += wc - 1;
514         do {
515             REPEAT4(stride, wp[stride] -= wp[0]; wp--)
516             wc -= stride;
517         } while (wc > 0);
518     }
519 }
520 
521 static void
horDiff32(TIFF * tif,uint8 * cp0,tmsize_t cc)522 horDiff32(TIFF* tif, uint8* cp0, tmsize_t cc)
523 {
524     TIFFPredictorState* sp = PredictorState(tif);
525     tmsize_t stride = sp->stride;
526     int32 *wp = (int32*) cp0;
527     tmsize_t wc = cc/4;
528 
529     assert((cc%(4*stride))==0);
530 
531     if (wc > stride) {
532         wc -= stride;
533         wp += wc - 1;
534         do {
535             REPEAT4(stride, wp[stride] -= wp[0]; wp--)
536             wc -= stride;
537         } while (wc > 0);
538     }
539 }
540 
541 /*
542  * Floating point predictor differencing routine.
543  */
544 static void
fpDiff(TIFF * tif,uint8 * cp0,tmsize_t cc)545 fpDiff(TIFF* tif, uint8* cp0, tmsize_t cc)
546 {
547     tmsize_t stride = PredictorState(tif)->stride;
548     uint32 bps = tif->tif_dir.td_bitspersample / 8;
549     tmsize_t wc = cc / bps;
550     tmsize_t count;
551     uint8 *cp = (uint8 *) cp0;
552     uint8 *tmp = (uint8 *)_TIFFmalloc(cc);
553 
554     assert((cc%(bps*stride))==0);
555 
556     if (!tmp)
557         return;
558 
559     _TIFFmemcpy(tmp, cp0, cc);
560     for (count = 0; count < wc; count++) {
561         uint32 byte;
562         for (byte = 0; byte < bps; byte++) {
563             #if WORDS_BIGENDIAN
564             cp[byte * wc + count] = tmp[bps * count + byte];
565             #else
566             cp[(bps - byte - 1) * wc + count] =
567                 tmp[bps * count + byte];
568             #endif
569         }
570     }
571     _TIFFfree(tmp);
572 
573     cp = (uint8 *) cp0;
574     cp += cc - stride - 1;
575     for (count = cc; count > stride; count -= stride)
576         REPEAT4(stride, cp[stride] -= cp[0]; cp--)
577 }
578 
579 static int
PredictorEncodeRow(TIFF * tif,uint8 * bp,tmsize_t cc,uint16 s)580 PredictorEncodeRow(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
581 {
582     TIFFPredictorState *sp = PredictorState(tif);
583 
584     assert(sp != NULL);
585     assert(sp->encodepfunc != NULL);
586     assert(sp->encoderow != NULL);
587 
588     /* XXX horizontal differencing alters user's data XXX */
589     (*sp->encodepfunc)(tif, bp, cc);
590     return (*sp->encoderow)(tif, bp, cc, s);
591 }
592 
593 static int
PredictorEncodeTile(TIFF * tif,uint8 * bp0,tmsize_t cc0,uint16 s)594 PredictorEncodeTile(TIFF* tif, uint8* bp0, tmsize_t cc0, uint16 s)
595 {
596     static const char module[] = "PredictorEncodeTile";
597     TIFFPredictorState *sp = PredictorState(tif);
598         uint8 *working_copy;
599     tmsize_t cc = cc0, rowsize;
600     unsigned char* bp;
601         int result_code;
602 
603     assert(sp != NULL);
604     assert(sp->encodepfunc != NULL);
605     assert(sp->encodetile != NULL);
606 
607         /*
608          * Do predictor manipulation in a working buffer to avoid altering
609          * the callers buffer. http://trac.osgeo.org/gdal/ticket/1965
610          */
611         working_copy = (uint8*) _TIFFmalloc(cc0);
612         if( working_copy == NULL )
613         {
614             TIFFErrorExt(tif->tif_clientdata, module,
615                          "Out of memory allocating " TIFF_SSIZE_FORMAT " byte temp buffer.",
616                          cc0 );
617             return 0;
618         }
619         memcpy( working_copy, bp0, cc0 );
620         bp = working_copy;
621 
622     rowsize = sp->rowsize;
623     assert(rowsize > 0);
624     assert((cc0%rowsize)==0);
625     while (cc > 0) {
626         (*sp->encodepfunc)(tif, bp, rowsize);
627         cc -= rowsize;
628         bp += rowsize;
629     }
630     result_code = (*sp->encodetile)(tif, working_copy, cc0, s);
631 
632         _TIFFfree( working_copy );
633 
634         return result_code;
635 }
636 
637 #define	FIELD_PREDICTOR	(FIELD_CODEC+0)		/* XXX */
638 
639 static const TIFFField predictFields[] = {
640     { TIFFTAG_PREDICTOR, 1, 1, TIFF_SHORT, 0, TIFF_SETGET_UINT16, TIFF_SETGET_UINT16, FIELD_PREDICTOR, FALSE, FALSE, "Predictor", NULL },
641 };
642 
643 static int
PredictorVSetField(TIFF * tif,uint32 tag,va_list ap)644 PredictorVSetField(TIFF* tif, uint32 tag, va_list ap)
645 {
646     TIFFPredictorState *sp = PredictorState(tif);
647 
648     assert(sp != NULL);
649     assert(sp->vsetparent != NULL);
650 
651     switch (tag) {
652     case TIFFTAG_PREDICTOR:
653         sp->predictor = (uint16) va_arg(ap, uint16_vap);
654         TIFFSetFieldBit(tif, FIELD_PREDICTOR);
655         break;
656     default:
657         return (*sp->vsetparent)(tif, tag, ap);
658     }
659     tif->tif_flags |= TIFF_DIRTYDIRECT;
660     return 1;
661 }
662 
663 static int
PredictorVGetField(TIFF * tif,uint32 tag,va_list ap)664 PredictorVGetField(TIFF* tif, uint32 tag, va_list ap)
665 {
666     TIFFPredictorState *sp = PredictorState(tif);
667 
668     assert(sp != NULL);
669     assert(sp->vgetparent != NULL);
670 
671     switch (tag) {
672     case TIFFTAG_PREDICTOR:
673         *va_arg(ap, uint16*) = sp->predictor;
674         break;
675     default:
676         return (*sp->vgetparent)(tif, tag, ap);
677     }
678     return 1;
679 }
680 
681 static void
PredictorPrintDir(TIFF * tif,FILE * fd,long flags)682 PredictorPrintDir(TIFF* tif, FILE* fd, long flags)
683 {
684     TIFFPredictorState* sp = PredictorState(tif);
685 
686     (void) flags;
687     if (TIFFFieldSet(tif,FIELD_PREDICTOR)) {
688         fprintf(fd, "  Predictor: ");
689         switch (sp->predictor) {
690             case 1: fprintf(fd, "none "); break;
691             case 2: fprintf(fd, "horizontal differencing "); break;
692             case 3: fprintf(fd, "floating point predictor "); break;
693         }
694         fprintf(fd, "%u (0x%x)\n", sp->predictor, sp->predictor);
695     }
696     if (sp->printdir)
697         (*sp->printdir)(tif, fd, flags);
698 }
699 
700 int
TIFFPredictorInit(TIFF * tif)701 TIFFPredictorInit(TIFF* tif)
702 {
703     TIFFPredictorState* sp = PredictorState(tif);
704 
705     assert(sp != 0);
706 
707     /*
708      * Merge codec-specific tag information.
709      */
710     if (!_TIFFMergeFields(tif, predictFields,
711                   TIFFArrayCount(predictFields))) {
712         TIFFErrorExt(tif->tif_clientdata, "TIFFPredictorInit",
713             "Merging Predictor codec-specific tags failed");
714         return 0;
715     }
716 
717     /*
718      * Override parent get/set field methods.
719      */
720     sp->vgetparent = tif->tif_tagmethods.vgetfield;
721     tif->tif_tagmethods.vgetfield =
722             PredictorVGetField;/* hook for predictor tag */
723     sp->vsetparent = tif->tif_tagmethods.vsetfield;
724     tif->tif_tagmethods.vsetfield =
725         PredictorVSetField;/* hook for predictor tag */
726     sp->printdir = tif->tif_tagmethods.printdir;
727     tif->tif_tagmethods.printdir =
728             PredictorPrintDir;	/* hook for predictor tag */
729 
730     sp->setupdecode = tif->tif_setupdecode;
731     tif->tif_setupdecode = PredictorSetupDecode;
732     sp->setupencode = tif->tif_setupencode;
733     tif->tif_setupencode = PredictorSetupEncode;
734 
735     sp->predictor = 1;			/* default value */
736     sp->encodepfunc = NULL;			/* no predictor routine */
737     sp->decodepfunc = NULL;			/* no predictor routine */
738     return 1;
739 }
740 
741 int
TIFFPredictorCleanup(TIFF * tif)742 TIFFPredictorCleanup(TIFF* tif)
743 {
744     TIFFPredictorState* sp = PredictorState(tif);
745 
746     assert(sp != 0);
747 
748     tif->tif_tagmethods.vgetfield = sp->vgetparent;
749     tif->tif_tagmethods.vsetfield = sp->vsetparent;
750     tif->tif_tagmethods.printdir = sp->printdir;
751     tif->tif_setupdecode = sp->setupdecode;
752     tif->tif_setupencode = sp->setupencode;
753 
754     return 1;
755 }
756 
757 /* vim: set ts=8 sts=8 sw=8 noet: */
758 /*
759  * Local Variables:
760  * mode: c
761  * c-basic-offset: 8
762  * fill-column: 78
763  * End:
764  */
765