Home | History | Annotate | Download | only in libtiff
      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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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