1/* $Id: tif_predict.c 276 2010-06-30 12:18:30Z nijtmans $ */ 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 37static void horAcc8(TIFF*, tidata_t, tsize_t); 38static void horAcc16(TIFF*, tidata_t, tsize_t); 39static void horAcc32(TIFF*, tidata_t, tsize_t); 40static void swabHorAcc16(TIFF*, tidata_t, tsize_t); 41static void swabHorAcc32(TIFF*, tidata_t, tsize_t); 42static void horDiff8(TIFF*, tidata_t, tsize_t); 43static void horDiff16(TIFF*, tidata_t, tsize_t); 44static void horDiff32(TIFF*, tidata_t, tsize_t); 45static void fpAcc(TIFF*, tidata_t, tsize_t); 46static void fpDiff(TIFF*, tidata_t, tsize_t); 47static int PredictorDecodeRow(TIFF*, tidata_t, tsize_t, tsample_t); 48static int PredictorDecodeTile(TIFF*, tidata_t, tsize_t, tsample_t); 49static int PredictorEncodeRow(TIFF*, tidata_t, tsize_t, tsample_t); 50static int PredictorEncodeTile(TIFF*, tidata_t, tsize_t, tsample_t); 51 52static int 53PredictorSetup(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 98 return 1; 99} 100 101static int 102PredictorSetupDecode(TIFF* tif) 103{ 104 TIFFPredictorState* sp = PredictorState(tif); 105 TIFFDirectory* td = &tif->tif_dir; 106 107 if (!(*sp->setupdecode)(tif) || !PredictorSetup(tif)) 108 return 0; 109 110 if (sp->predictor == 2) { 111 switch (td->td_bitspersample) { 112 case 8: sp->decodepfunc = horAcc8; break; 113 case 16: sp->decodepfunc = horAcc16; break; 114 case 32: sp->decodepfunc = horAcc32; break; 115 } 116 /* 117 * Override default decoding method with one that does the 118 * predictor stuff. 119 */ 120 if( tif->tif_decoderow != PredictorDecodeRow ) 121 { 122 sp->decoderow = tif->tif_decoderow; 123 tif->tif_decoderow = PredictorDecodeRow; 124 sp->decodestrip = tif->tif_decodestrip; 125 tif->tif_decodestrip = PredictorDecodeTile; 126 sp->decodetile = tif->tif_decodetile; 127 tif->tif_decodetile = PredictorDecodeTile; 128 } 129 /* 130 * If the data is horizontally differenced 16-bit data that 131 * requires byte-swapping, then it must be byte swapped before 132 * the accumulation step. We do this with a special-purpose 133 * routine and override the normal post decoding logic that 134 * the library setup when the directory was read. 135 */ 136 if (tif->tif_flags & TIFF_SWAB) { 137 if (sp->decodepfunc == horAcc16) { 138 sp->decodepfunc = swabHorAcc16; 139 tif->tif_postdecode = _TIFFNoPostDecode; 140 } else if (sp->decodepfunc == horAcc32) { 141 sp->decodepfunc = swabHorAcc32; 142 tif->tif_postdecode = _TIFFNoPostDecode; 143 } 144 } 145 } 146 147 else if (sp->predictor == 3) { 148 sp->decodepfunc = fpAcc; 149 /* 150 * Override default decoding method with one that does the 151 * predictor stuff. 152 */ 153 if( tif->tif_decoderow != PredictorDecodeRow ) 154 { 155 sp->decoderow = tif->tif_decoderow; 156 tif->tif_decoderow = PredictorDecodeRow; 157 sp->decodestrip = tif->tif_decodestrip; 158 tif->tif_decodestrip = PredictorDecodeTile; 159 sp->decodetile = tif->tif_decodetile; 160 tif->tif_decodetile = PredictorDecodeTile; 161 } 162 /* 163 * The data should not be swapped outside of the floating 164 * point predictor, the accumulation routine should return 165 * byres in the native order. 166 */ 167 if (tif->tif_flags & TIFF_SWAB) { 168 tif->tif_postdecode = _TIFFNoPostDecode; 169 } 170 /* 171 * Allocate buffer to keep the decoded bytes before 172 * rearranging in the ight order 173 */ 174 } 175 176 return 1; 177} 178 179static int 180PredictorSetupEncode(TIFF* tif) 181{ 182 TIFFPredictorState* sp = PredictorState(tif); 183 TIFFDirectory* td = &tif->tif_dir; 184 185 if (!(*sp->setupencode)(tif) || !PredictorSetup(tif)) 186 return 0; 187 188 if (sp->predictor == 2) { 189 switch (td->td_bitspersample) { 190 case 8: sp->encodepfunc = horDiff8; break; 191 case 16: sp->encodepfunc = horDiff16; break; 192 case 32: sp->encodepfunc = horDiff32; break; 193 } 194 /* 195 * Override default encoding method with one that does the 196 * predictor stuff. 197 */ 198 if( tif->tif_encoderow != PredictorEncodeRow ) 199 { 200 sp->encoderow = tif->tif_encoderow; 201 tif->tif_encoderow = PredictorEncodeRow; 202 sp->encodestrip = tif->tif_encodestrip; 203 tif->tif_encodestrip = PredictorEncodeTile; 204 sp->encodetile = tif->tif_encodetile; 205 tif->tif_encodetile = PredictorEncodeTile; 206 } 207 } 208 209 else if (sp->predictor == 3) { 210 sp->encodepfunc = fpDiff; 211 /* 212 * Override default encoding method with one that does the 213 * predictor stuff. 214 */ 215 if( tif->tif_encoderow != PredictorEncodeRow ) 216 { 217 sp->encoderow = tif->tif_encoderow; 218 tif->tif_encoderow = PredictorEncodeRow; 219 sp->encodestrip = tif->tif_encodestrip; 220 tif->tif_encodestrip = PredictorEncodeTile; 221 sp->encodetile = tif->tif_encodetile; 222 tif->tif_encodetile = PredictorEncodeTile; 223 } 224 } 225 226 return 1; 227} 228 229#define REPEAT4(n, op) \ 230 switch (n) { \ 231 default: { int i; for (i = n-4; i > 0; i--) { op; } } \ 232 case 4: op; \ 233 case 3: op; \ 234 case 2: op; \ 235 case 1: op; \ 236 case 0: ; \ 237 } 238 239static void 240horAcc8(TIFF* tif, tidata_t cp0, tsize_t cc) 241{ 242 tsize_t stride = PredictorState(tif)->stride; 243 244 char* cp = (char*) cp0; 245 if (cc > stride) { 246 cc -= stride; 247 /* 248 * Pipeline the most common cases. 249 */ 250 if (stride == 3) { 251 unsigned int cr = cp[0]; 252 unsigned int cg = cp[1]; 253 unsigned int cb = cp[2]; 254 do { 255 cc -= 3, cp += 3; 256 cp[0] = (char) (cr += cp[0]); 257 cp[1] = (char) (cg += cp[1]); 258 cp[2] = (char) (cb += cp[2]); 259 } while ((int32) cc > 0); 260 } else if (stride == 4) { 261 unsigned int cr = cp[0]; 262 unsigned int cg = cp[1]; 263 unsigned int cb = cp[2]; 264 unsigned int ca = cp[3]; 265 do { 266 cc -= 4, cp += 4; 267 cp[0] = (char) (cr += cp[0]); 268 cp[1] = (char) (cg += cp[1]); 269 cp[2] = (char) (cb += cp[2]); 270 cp[3] = (char) (ca += cp[3]); 271 } while ((int32) cc > 0); 272 } else { 273 do { 274 REPEAT4(stride, cp[stride] = 275 (char) (cp[stride] + *cp); cp++) 276 cc -= stride; 277 } while ((int32) cc > 0); 278 } 279 } 280} 281 282static void 283swabHorAcc16(TIFF* tif, tidata_t cp0, tsize_t cc) 284{ 285 tsize_t stride = PredictorState(tif)->stride; 286 uint16* wp = (uint16*) cp0; 287 tsize_t wc = cc / 2; 288 289 if (wc > stride) { 290 TIFFSwabArrayOfShort(wp, wc); 291 wc -= stride; 292 do { 293 REPEAT4(stride, wp[stride] += wp[0]; wp++) 294 wc -= stride; 295 } while ((int32) wc > 0); 296 } 297} 298 299static void 300horAcc16(TIFF* tif, tidata_t cp0, tsize_t cc) 301{ 302 tsize_t stride = PredictorState(tif)->stride; 303 uint16* wp = (uint16*) cp0; 304 tsize_t wc = cc / 2; 305 306 if (wc > stride) { 307 wc -= stride; 308 do { 309 REPEAT4(stride, wp[stride] += wp[0]; wp++) 310 wc -= stride; 311 } while ((int32) wc > 0); 312 } 313} 314 315static void 316swabHorAcc32(TIFF* tif, tidata_t cp0, tsize_t cc) 317{ 318 tsize_t stride = PredictorState(tif)->stride; 319 uint32* wp = (uint32*) cp0; 320 tsize_t wc = cc / 4; 321 322 if (wc > stride) { 323 TIFFSwabArrayOfLong(wp, wc); 324 wc -= stride; 325 do { 326 REPEAT4(stride, wp[stride] += wp[0]; wp++) 327 wc -= stride; 328 } while ((int32) wc > 0); 329 } 330} 331 332static void 333horAcc32(TIFF* tif, tidata_t cp0, tsize_t cc) 334{ 335 tsize_t stride = PredictorState(tif)->stride; 336 uint32* wp = (uint32*) cp0; 337 tsize_t wc = cc / 4; 338 339 if (wc > stride) { 340 wc -= stride; 341 do { 342 REPEAT4(stride, wp[stride] += wp[0]; wp++) 343 wc -= stride; 344 } while ((int32) wc > 0); 345 } 346} 347 348/* 349 * Floating point predictor accumulation routine. 350 */ 351static void 352fpAcc(TIFF* tif, tidata_t cp0, tsize_t cc) 353{ 354 tsize_t stride = PredictorState(tif)->stride; 355 uint32 bps = tif->tif_dir.td_bitspersample / 8; 356 tsize_t wc = cc / bps; 357 tsize_t count = cc; 358 uint8 *cp = (uint8 *) cp0; 359 uint8 *tmp = (uint8 *)_TIFFmalloc(cc); 360 361 if (!tmp) 362 return; 363 364 while (count > stride) { 365 REPEAT4(stride, cp[stride] += cp[0]; cp++) 366 count -= stride; 367 } 368 369 _TIFFmemcpy(tmp, cp0, cc); 370 cp = (uint8 *) cp0; 371 for (count = 0; count < wc; count++) { 372 uint32 byte; 373 for (byte = 0; byte < bps; byte++) { 374#if WORDS_BIGENDIAN 375 cp[bps * count + byte] = tmp[byte * wc + count]; 376#else 377 cp[bps * count + byte] = 378 tmp[(bps - byte - 1) * wc + count]; 379#endif 380 } 381 } 382 _TIFFfree(tmp); 383} 384 385/* 386 * Decode a scanline and apply the predictor routine. 387 */ 388static int 389PredictorDecodeRow(TIFF* tif, tidata_t op0, tsize_t occ0, tsample_t s) 390{ 391 TIFFPredictorState *sp = PredictorState(tif); 392 393 assert(sp != NULL); 394 assert(sp->decoderow != NULL); 395 assert(sp->decodepfunc != NULL); 396 397 if ((*sp->decoderow)(tif, op0, occ0, s)) { 398 (*sp->decodepfunc)(tif, op0, occ0); 399 return 1; 400 } else 401 return 0; 402} 403 404/* 405 * Decode a tile/strip and apply the predictor routine. 406 * Note that horizontal differencing must be done on a 407 * row-by-row basis. The width of a "row" has already 408 * been calculated at pre-decode time according to the 409 * strip/tile dimensions. 410 */ 411static int 412PredictorDecodeTile(TIFF* tif, tidata_t op0, tsize_t occ0, tsample_t s) 413{ 414 TIFFPredictorState *sp = PredictorState(tif); 415 416 assert(sp != NULL); 417 assert(sp->decodetile != NULL); 418 419 if ((*sp->decodetile)(tif, op0, occ0, s)) { 420 tsize_t rowsize = sp->rowsize; 421 assert(rowsize > 0); 422 assert(sp->decodepfunc != NULL); 423 while ((long)occ0 > 0) { 424 (*sp->decodepfunc)(tif, op0, (tsize_t) rowsize); 425 occ0 -= rowsize; 426 op0 += rowsize; 427 } 428 return 1; 429 } else 430 return 0; 431} 432 433static void 434horDiff8(TIFF* tif, tidata_t cp0, tsize_t cc) 435{ 436 TIFFPredictorState* sp = PredictorState(tif); 437 tsize_t stride = sp->stride; 438 char* cp = (char*) cp0; 439 440 if (cc > stride) { 441 cc -= stride; 442 /* 443 * Pipeline the most common cases. 444 */ 445 if (stride == 3) { 446 int r1, g1, b1; 447 int r2 = cp[0]; 448 int g2 = cp[1]; 449 int b2 = cp[2]; 450 do { 451 r1 = cp[3]; cp[3] = r1-r2; r2 = r1; 452 g1 = cp[4]; cp[4] = g1-g2; g2 = g1; 453 b1 = cp[5]; cp[5] = b1-b2; b2 = b1; 454 cp += 3; 455 } while ((int32)(cc -= 3) > 0); 456 } else if (stride == 4) { 457 int r1, g1, b1, a1; 458 int r2 = cp[0]; 459 int g2 = cp[1]; 460 int b2 = cp[2]; 461 int a2 = cp[3]; 462 do { 463 r1 = cp[4]; cp[4] = r1-r2; r2 = r1; 464 g1 = cp[5]; cp[5] = g1-g2; g2 = g1; 465 b1 = cp[6]; cp[6] = b1-b2; b2 = b1; 466 a1 = cp[7]; cp[7] = a1-a2; a2 = a1; 467 cp += 4; 468 } while ((int32)(cc -= 4) > 0); 469 } else { 470 cp += cc - 1; 471 do { 472 REPEAT4(stride, cp[stride] -= cp[0]; cp--) 473 } while ((int32)(cc -= stride) > 0); 474 } 475 } 476} 477 478static void 479horDiff16(TIFF* tif, tidata_t cp0, tsize_t cc) 480{ 481 TIFFPredictorState* sp = PredictorState(tif); 482 tsize_t stride = sp->stride; 483 int16 *wp = (int16*) cp0; 484 tsize_t wc = cc/2; 485 486 if (wc > stride) { 487 wc -= stride; 488 wp += wc - 1; 489 do { 490 REPEAT4(stride, wp[stride] -= wp[0]; wp--) 491 wc -= stride; 492 } while ((int32) wc > 0); 493 } 494} 495 496static void 497horDiff32(TIFF* tif, tidata_t cp0, tsize_t cc) 498{ 499 TIFFPredictorState* sp = PredictorState(tif); 500 tsize_t stride = sp->stride; 501 int32 *wp = (int32*) cp0; 502 tsize_t wc = cc/4; 503 504 if (wc > stride) { 505 wc -= stride; 506 wp += wc - 1; 507 do { 508 REPEAT4(stride, wp[stride] -= wp[0]; wp--) 509 wc -= stride; 510 } while ((int32) wc > 0); 511 } 512} 513 514/* 515 * Floating point predictor differencing routine. 516 */ 517static void 518fpDiff(TIFF* tif, tidata_t cp0, tsize_t cc) 519{ 520 tsize_t stride = PredictorState(tif)->stride; 521 uint32 bps = tif->tif_dir.td_bitspersample / 8; 522 tsize_t wc = cc / bps; 523 tsize_t count; 524 uint8 *cp = (uint8 *) cp0; 525 uint8 *tmp = (uint8 *)_TIFFmalloc(cc); 526 527 if (!tmp) 528 return; 529 530 _TIFFmemcpy(tmp, cp0, cc); 531 for (count = 0; count < wc; count++) { 532 uint32 byte; 533 for (byte = 0; byte < bps; byte++) { 534#if WORDS_BIGENDIAN 535 cp[byte * wc + count] = tmp[bps * count + byte]; 536#else 537 cp[(bps - byte - 1) * wc + count] = 538 tmp[bps * count + byte]; 539#endif 540 } 541 } 542 _TIFFfree(tmp); 543 544 cp = (uint8 *) cp0; 545 cp += cc - stride - 1; 546 for (count = cc; count > stride; count -= stride) 547 REPEAT4(stride, cp[stride] -= cp[0]; cp--) 548} 549 550static int 551PredictorEncodeRow(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) 552{ 553 TIFFPredictorState *sp = PredictorState(tif); 554 555 assert(sp != NULL); 556 assert(sp->encodepfunc != NULL); 557 assert(sp->encoderow != NULL); 558 559 /* XXX horizontal differencing alters user's data XXX */ 560 (*sp->encodepfunc)(tif, bp, cc); 561 return (*sp->encoderow)(tif, bp, cc, s); 562} 563 564static int 565PredictorEncodeTile(TIFF* tif, tidata_t bp0, tsize_t cc0, tsample_t s) 566{ 567 static const char module[] = "PredictorEncodeTile"; 568 TIFFPredictorState *sp = PredictorState(tif); 569 uint8 *working_copy; 570 tsize_t cc = cc0, rowsize; 571 unsigned char* bp; 572 int result_code; 573 574 assert(sp != NULL); 575 assert(sp->encodepfunc != NULL); 576 assert(sp->encodetile != NULL); 577 578 /* 579 * Do predictor manipulation in a working buffer to avoid altering 580 * the callers buffer. http://trac.osgeo.org/gdal/ticket/1965 581 */ 582 working_copy = (uint8*) _TIFFmalloc(cc0); 583 if( working_copy == NULL ) 584 { 585 TIFFErrorExt(tif->tif_clientdata, module, 586 "Out of memory allocating %d byte temp buffer.", 587 cc0 ); 588 return 0; 589 } 590 memcpy( working_copy, bp0, cc0 ); 591 bp = working_copy; 592 593 rowsize = sp->rowsize; 594 assert(rowsize > 0); 595 assert((cc0%rowsize)==0); 596 while (cc > 0) { 597 (*sp->encodepfunc)(tif, bp, rowsize); 598 cc -= rowsize; 599 bp += rowsize; 600 } 601 result_code = (*sp->encodetile)(tif, working_copy, cc0, s); 602 603 _TIFFfree( working_copy ); 604 605 return result_code; 606} 607 608#define FIELD_PREDICTOR (FIELD_CODEC+0) /* XXX */ 609 610static const TIFFFieldInfo predictFieldInfo[] = { 611 { TIFFTAG_PREDICTOR, 1, 1, TIFF_SHORT, FIELD_PREDICTOR, 612 FALSE, FALSE, "Predictor" }, 613}; 614 615static int 616PredictorVSetField(TIFF* tif, ttag_t tag, va_list ap) 617{ 618 TIFFPredictorState *sp = PredictorState(tif); 619 620 assert(sp != NULL); 621 assert(sp->vsetparent != NULL); 622 623 switch (tag) { 624 case TIFFTAG_PREDICTOR: 625 sp->predictor = (uint16) va_arg(ap, int); 626 TIFFSetFieldBit(tif, FIELD_PREDICTOR); 627 break; 628 default: 629 return (*sp->vsetparent)(tif, tag, ap); 630 } 631 tif->tif_flags |= TIFF_DIRTYDIRECT; 632 return 1; 633} 634 635static int 636PredictorVGetField(TIFF* tif, ttag_t tag, va_list ap) 637{ 638 TIFFPredictorState *sp = PredictorState(tif); 639 640 assert(sp != NULL); 641 assert(sp->vgetparent != NULL); 642 643 switch (tag) { 644 case TIFFTAG_PREDICTOR: 645 *va_arg(ap, uint16*) = sp->predictor; 646 break; 647 default: 648 return (*sp->vgetparent)(tif, tag, ap); 649 } 650 return 1; 651} 652 653static void 654PredictorPrintDir(TIFF* tif, FILE* fd, long flags) 655{ 656 TIFFPredictorState* sp = PredictorState(tif); 657 658 (void) flags; 659 if (TIFFFieldSet(tif,FIELD_PREDICTOR)) { 660 fprintf(fd, " Predictor: "); 661 switch (sp->predictor) { 662 case 1: fprintf(fd, "none "); break; 663 case 2: fprintf(fd, "horizontal differencing "); break; 664 case 3: fprintf(fd, "floating point predictor "); break; 665 } 666 fprintf(fd, "%u (0x%x)\n", sp->predictor, sp->predictor); 667 } 668 if (sp->printdir) 669 (*sp->printdir)(tif, fd, flags); 670} 671 672int 673TIFFPredictorInit(TIFF* tif) 674{ 675 TIFFPredictorState* sp = PredictorState(tif); 676 677 assert(sp != 0); 678 679 /* 680 * Merge codec-specific tag information. 681 */ 682 if (!_TIFFMergeFieldInfo(tif, predictFieldInfo, 683 TIFFArrayCount(predictFieldInfo))) { 684 TIFFErrorExt(tif->tif_clientdata, "TIFFPredictorInit", 685 "Merging Predictor codec-specific tags failed"); 686 return 0; 687 } 688 689 /* 690 * Override parent get/set field methods. 691 */ 692 sp->vgetparent = tif->tif_tagmethods.vgetfield; 693 tif->tif_tagmethods.vgetfield = 694 PredictorVGetField;/* hook for predictor tag */ 695 sp->vsetparent = tif->tif_tagmethods.vsetfield; 696 tif->tif_tagmethods.vsetfield = 697 PredictorVSetField;/* hook for predictor tag */ 698 sp->printdir = tif->tif_tagmethods.printdir; 699 tif->tif_tagmethods.printdir = 700 PredictorPrintDir; /* hook for predictor tag */ 701 702 sp->setupdecode = tif->tif_setupdecode; 703 tif->tif_setupdecode = PredictorSetupDecode; 704 sp->setupencode = tif->tif_setupencode; 705 tif->tif_setupencode = PredictorSetupEncode; 706 707 sp->predictor = 1; /* default value */ 708 sp->encodepfunc = NULL; /* no predictor routine */ 709 sp->decodepfunc = NULL; /* no predictor routine */ 710 return 1; 711} 712 713int 714TIFFPredictorCleanup(TIFF* tif) 715{ 716 TIFFPredictorState* sp = PredictorState(tif); 717 718 assert(sp != 0); 719 720 tif->tif_tagmethods.vgetfield = sp->vgetparent; 721 tif->tif_tagmethods.vsetfield = sp->vsetparent; 722 tif->tif_tagmethods.printdir = sp->printdir; 723 tif->tif_setupdecode = sp->setupdecode; 724 tif->tif_setupencode = sp->setupencode; 725 726 return 1; 727} 728 729/* vim: set ts=8 sts=8 sw=8 noet: */ 730/* 731 * Local Variables: 732 * mode: c 733 * c-basic-offset: 8 734 * fill-column: 78 735 * End: 736 */ 737