1 /* $Id: tif_predict.c,v 1.11 2006/03/03 14:10:09 dron 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*, tidata_t, tsize_t);
38 static	void horAcc16(TIFF*, tidata_t, tsize_t);
39 static	void swabHorAcc16(TIFF*, tidata_t, tsize_t);
40 static	void horDiff8(TIFF*, tidata_t, tsize_t);
41 static	void horDiff16(TIFF*, tidata_t, tsize_t);
42 static	void fpAcc(TIFF*, tidata_t, tsize_t);
43 static	void fpDiff(TIFF*, tidata_t, tsize_t);
44 static	int PredictorDecodeRow(TIFF*, tidata_t, tsize_t, tsample_t);
45 static	int PredictorDecodeTile(TIFF*, tidata_t, tsize_t, tsample_t);
46 static	int PredictorEncodeRow(TIFF*, tidata_t, tsize_t, tsample_t);
47 static	int PredictorEncodeTile(TIFF*, tidata_t, tsize_t, tsample_t);
48 
49 static int
PredictorSetup(TIFF * tif)50 PredictorSetup(TIFF* tif)
51 {
52 	static const char module[] = "PredictorSetup";
53 
54 	TIFFPredictorState* sp = PredictorState(tif);
55 	TIFFDirectory* td = &tif->tif_dir;
56 
57 	switch (sp->predictor)		/* no differencing */
58 	{
59 		case PREDICTOR_NONE:
60 			return 1;
61 		case PREDICTOR_HORIZONTAL:
62 			if (td->td_bitspersample != 8
63 			    && td->td_bitspersample != 16) {
64 				TIFFErrorExt(tif->tif_clientdata, module,
65     "Horizontal differencing \"Predictor\" not supported with %d-bit samples",
66 					  td->td_bitspersample);
67 				return 0;
68 			}
69 			break;
70 		case PREDICTOR_FLOATINGPOINT:
71 			if (td->td_sampleformat != SAMPLEFORMAT_IEEEFP) {
72 				TIFFErrorExt(tif->tif_clientdata, module,
73 	"Floating point \"Predictor\" not supported with %d data format",
74 					  td->td_sampleformat);
75 				return 0;
76 			}
77 			break;
78 		default:
79 			TIFFErrorExt(tif->tif_clientdata, module,
80 				  "\"Predictor\" value %d not supported",
81 				  sp->predictor);
82 			return 0;
83 	}
84 	sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ?
85 	    td->td_samplesperpixel : 1);
86 	/*
87 	 * Calculate the scanline/tile-width size in bytes.
88 	 */
89 	if (isTiled(tif))
90 		sp->rowsize = TIFFTileRowSize(tif);
91 	else
92 		sp->rowsize = TIFFScanlineSize(tif);
93 
94 	return 1;
95 }
96 
97 static int
PredictorSetupDecode(TIFF * tif)98 PredictorSetupDecode(TIFF* tif)
99 {
100 	TIFFPredictorState* sp = PredictorState(tif);
101 	TIFFDirectory* td = &tif->tif_dir;
102 
103 	if (!(*sp->setupdecode)(tif) || !PredictorSetup(tif))
104 		return 0;
105 
106 	if (sp->predictor == 2) {
107 		switch (td->td_bitspersample) {
108 			case 8:  sp->pfunc = horAcc8; break;
109 			case 16: sp->pfunc = horAcc16; break;
110 		}
111 		/*
112 		 * Override default decoding method with one that does the
113 		 * predictor stuff.
114 		 */
115 		sp->coderow = tif->tif_decoderow;
116 		tif->tif_decoderow = PredictorDecodeRow;
117 		sp->codestrip = tif->tif_decodestrip;
118 		tif->tif_decodestrip = PredictorDecodeTile;
119 		sp->codetile = tif->tif_decodetile;
120 		tif->tif_decodetile = PredictorDecodeTile;
121 		/*
122 		 * If the data is horizontally differenced 16-bit data that
123 		 * requires byte-swapping, then it must be byte swapped before
124 		 * the accumulation step.  We do this with a special-purpose
125 		 * routine and override the normal post decoding logic that
126 		 * the library setup when the directory was read.
127 		 */
128 		if (tif->tif_flags & TIFF_SWAB) {
129 			if (sp->pfunc == horAcc16) {
130 				sp->pfunc = swabHorAcc16;
131 				tif->tif_postdecode = _TIFFNoPostDecode;
132 			} /* else handle 32-bit case... */
133 		}
134 	}
135 
136 	else if (sp->predictor == 3) {
137 		sp->pfunc = fpAcc;
138 		/*
139 		 * Override default decoding method with one that does the
140 		 * predictor stuff.
141 		 */
142 		sp->coderow = tif->tif_decoderow;
143 		tif->tif_decoderow = PredictorDecodeRow;
144 		sp->codestrip = tif->tif_decodestrip;
145 		tif->tif_decodestrip = PredictorDecodeTile;
146 		sp->codetile = tif->tif_decodetile;
147 		tif->tif_decodetile = PredictorDecodeTile;
148 		/*
149 		 * The data should not be swapped outside of the floating
150 		 * point predictor, the accumulation routine should return
151 		 * byres in the native order.
152 		 */
153 		if (tif->tif_flags & TIFF_SWAB) {
154 			tif->tif_postdecode = _TIFFNoPostDecode;
155 		}
156 		/*
157 		 * Allocate buffer to keep the decoded bytes before
158 		 * rearranging in the ight order
159 		 */
160 	}
161 
162 	return 1;
163 }
164 
165 static int
PredictorSetupEncode(TIFF * tif)166 PredictorSetupEncode(TIFF* tif)
167 {
168 	TIFFPredictorState* sp = PredictorState(tif);
169 	TIFFDirectory* td = &tif->tif_dir;
170 
171 	if (!(*sp->setupencode)(tif) || !PredictorSetup(tif))
172 		return 0;
173 
174 	if (sp->predictor == 2) {
175 		switch (td->td_bitspersample) {
176 			case 8:  sp->pfunc = horDiff8; break;
177 			case 16: sp->pfunc = horDiff16; break;
178 		}
179 		/*
180 		 * Override default encoding method with one that does the
181 		 * predictor stuff.
182 		 */
183 		sp->coderow = tif->tif_encoderow;
184 		tif->tif_encoderow = PredictorEncodeRow;
185 		sp->codestrip = tif->tif_encodestrip;
186 		tif->tif_encodestrip = PredictorEncodeTile;
187 		sp->codetile = tif->tif_encodetile;
188 		tif->tif_encodetile = PredictorEncodeTile;
189 	}
190 
191 	else if (sp->predictor == 3) {
192 		sp->pfunc = fpDiff;
193 		/*
194 		 * Override default encoding method with one that does the
195 		 * predictor stuff.
196 		 */
197 		sp->coderow = tif->tif_encoderow;
198 		tif->tif_encoderow = PredictorEncodeRow;
199 		sp->codestrip = tif->tif_encodestrip;
200 		tif->tif_encodestrip = PredictorEncodeTile;
201 		sp->codetile = tif->tif_encodetile;
202 		tif->tif_encodetile = PredictorEncodeTile;
203 	}
204 
205 	return 1;
206 }
207 
208 #define REPEAT4(n, op)		\
209     switch (n) {		\
210     default: { int i; for (i = n-4; i > 0; i--) { op; } } \
211     case 4:  op;		\
212     case 3:  op;		\
213     case 2:  op;		\
214     case 1:  op;		\
215     case 0:  ;			\
216     }
217 
218 static void
horAcc8(TIFF * tif,tidata_t cp0,tsize_t cc)219 horAcc8(TIFF* tif, tidata_t cp0, tsize_t cc)
220 {
221 	tsize_t stride = PredictorState(tif)->stride;
222 
223 	char* cp = (char*) cp0;
224 	if (cc > stride) {
225 		cc -= stride;
226 		/*
227 		 * Pipeline the most common cases.
228 		 */
229 		if (stride == 3)  {
230 			unsigned int cr = cp[0];
231 			unsigned int cg = cp[1];
232 			unsigned int cb = cp[2];
233 			do {
234 				cc -= 3, cp += 3;
235 				cp[0] = (char) (cr += cp[0]);
236 				cp[1] = (char) (cg += cp[1]);
237 				cp[2] = (char) (cb += cp[2]);
238 			} while ((int32) cc > 0);
239 		} else if (stride == 4)  {
240 			unsigned int cr = cp[0];
241 			unsigned int cg = cp[1];
242 			unsigned int cb = cp[2];
243 			unsigned int ca = cp[3];
244 			do {
245 				cc -= 4, cp += 4;
246 				cp[0] = (char) (cr += cp[0]);
247 				cp[1] = (char) (cg += cp[1]);
248 				cp[2] = (char) (cb += cp[2]);
249 				cp[3] = (char) (ca += cp[3]);
250 			} while ((int32) cc > 0);
251 		} else  {
252 			do {
253 				REPEAT4(stride, cp[stride] =
254 					(char) (cp[stride] + *cp); cp++)
255 				cc -= stride;
256 			} while ((int32) cc > 0);
257 		}
258 	}
259 }
260 
261 static void
swabHorAcc16(TIFF * tif,tidata_t cp0,tsize_t cc)262 swabHorAcc16(TIFF* tif, tidata_t cp0, tsize_t cc)
263 {
264 	tsize_t stride = PredictorState(tif)->stride;
265 	uint16* wp = (uint16*) cp0;
266 	tsize_t wc = cc / 2;
267 
268 	if (wc > stride) {
269 		TIFFSwabArrayOfShort(wp, wc);
270 		wc -= stride;
271 		do {
272 			REPEAT4(stride, wp[stride] += wp[0]; wp++)
273 			wc -= stride;
274 		} while ((int32) wc > 0);
275 	}
276 }
277 
278 static void
horAcc16(TIFF * tif,tidata_t cp0,tsize_t cc)279 horAcc16(TIFF* tif, tidata_t cp0, tsize_t cc)
280 {
281 	tsize_t stride = PredictorState(tif)->stride;
282 	uint16* wp = (uint16*) cp0;
283 	tsize_t wc = cc / 2;
284 
285 	if (wc > stride) {
286 		wc -= stride;
287 		do {
288 			REPEAT4(stride, wp[stride] += wp[0]; wp++)
289 			wc -= stride;
290 		} while ((int32) wc > 0);
291 	}
292 }
293 
294 /*
295  * Floating point predictor accumulation routine.
296  */
297 static void
fpAcc(TIFF * tif,tidata_t cp0,tsize_t cc)298 fpAcc(TIFF* tif, tidata_t cp0, tsize_t cc)
299 {
300 	tsize_t stride = PredictorState(tif)->stride;
301 	uint32 bps = tif->tif_dir.td_bitspersample / 8;
302 	tsize_t wc = cc / bps;
303 	tsize_t count = cc;
304 	uint8 *cp = (uint8 *) cp0;
305 	uint8 *tmp = (uint8 *)_TIFFmalloc(cc);
306 
307 	if (!tmp)
308 		return;
309 
310 	while (count > stride) {
311 		REPEAT4(stride, cp[stride] += cp[0]; cp++)
312 		count -= stride;
313 	}
314 
315 	_TIFFmemcpy(tmp, cp0, cc);
316 	cp = (uint8 *) cp0;
317 	for (count = 0; count < wc; count++) {
318 		uint32 byte;
319 		for (byte = 0; byte < bps; byte++) {
320 #if WORDS_BIGENDIAN
321 			cp[bps * count + byte] = tmp[byte * wc + count];
322 #else
323 			cp[bps * count + byte] =
324 				tmp[(bps - byte - 1) * wc + count];
325 #endif
326 		}
327 	}
328 	_TIFFfree(tmp);
329 }
330 
331 /*
332  * Decode a scanline and apply the predictor routine.
333  */
334 static int
PredictorDecodeRow(TIFF * tif,tidata_t op0,tsize_t occ0,tsample_t s)335 PredictorDecodeRow(TIFF* tif, tidata_t op0, tsize_t occ0, tsample_t s)
336 {
337 	TIFFPredictorState *sp = PredictorState(tif);
338 
339 	assert(sp != NULL);
340 	assert(sp->coderow != NULL);
341 	assert(sp->pfunc != NULL);
342 
343 	if ((*sp->coderow)(tif, op0, occ0, s)) {
344 		(*sp->pfunc)(tif, op0, occ0);
345 		return 1;
346 	} else
347 		return 0;
348 }
349 
350 /*
351  * Decode a tile/strip and apply the predictor routine.
352  * Note that horizontal differencing must be done on a
353  * row-by-row basis.  The width of a "row" has already
354  * been calculated at pre-decode time according to the
355  * strip/tile dimensions.
356  */
357 static int
PredictorDecodeTile(TIFF * tif,tidata_t op0,tsize_t occ0,tsample_t s)358 PredictorDecodeTile(TIFF* tif, tidata_t op0, tsize_t occ0, tsample_t s)
359 {
360 	TIFFPredictorState *sp = PredictorState(tif);
361 
362 	assert(sp != NULL);
363 	assert(sp->codetile != NULL);
364 
365 	if ((*sp->codetile)(tif, op0, occ0, s)) {
366 		tsize_t rowsize = sp->rowsize;
367 		assert(rowsize > 0);
368 		assert(sp->pfunc != NULL);
369 		while ((long)occ0 > 0) {
370 			(*sp->pfunc)(tif, op0, (tsize_t) rowsize);
371 			occ0 -= rowsize;
372 			op0 += rowsize;
373 		}
374 		return 1;
375 	} else
376 		return 0;
377 }
378 
379 static void
horDiff8(TIFF * tif,tidata_t cp0,tsize_t cc)380 horDiff8(TIFF* tif, tidata_t cp0, tsize_t cc)
381 {
382 	TIFFPredictorState* sp = PredictorState(tif);
383 	tsize_t stride = sp->stride;
384 	char* cp = (char*) cp0;
385 
386 	if (cc > stride) {
387 		cc -= stride;
388 		/*
389 		 * Pipeline the most common cases.
390 		 */
391 		if (stride == 3) {
392 			int r1, g1, b1;
393 			int r2 = cp[0];
394 			int g2 = cp[1];
395 			int b2 = cp[2];
396 			do {
397 				r1 = cp[3]; cp[3] = r1-r2; r2 = r1;
398 				g1 = cp[4]; cp[4] = g1-g2; g2 = g1;
399 				b1 = cp[5]; cp[5] = b1-b2; b2 = b1;
400 				cp += 3;
401 			} while ((int32)(cc -= 3) > 0);
402 		} else if (stride == 4) {
403 			int r1, g1, b1, a1;
404 			int r2 = cp[0];
405 			int g2 = cp[1];
406 			int b2 = cp[2];
407 			int a2 = cp[3];
408 			do {
409 				r1 = cp[4]; cp[4] = r1-r2; r2 = r1;
410 				g1 = cp[5]; cp[5] = g1-g2; g2 = g1;
411 				b1 = cp[6]; cp[6] = b1-b2; b2 = b1;
412 				a1 = cp[7]; cp[7] = a1-a2; a2 = a1;
413 				cp += 4;
414 			} while ((int32)(cc -= 4) > 0);
415 		} else {
416 			cp += cc - 1;
417 			do {
418 				REPEAT4(stride, cp[stride] -= cp[0]; cp--)
419 			} while ((int32)(cc -= stride) > 0);
420 		}
421 	}
422 }
423 
424 static void
horDiff16(TIFF * tif,tidata_t cp0,tsize_t cc)425 horDiff16(TIFF* tif, tidata_t cp0, tsize_t cc)
426 {
427 	TIFFPredictorState* sp = PredictorState(tif);
428 	tsize_t stride = sp->stride;
429 	int16 *wp = (int16*) cp0;
430 	tsize_t wc = cc/2;
431 
432 	if (wc > stride) {
433 		wc -= stride;
434 		wp += wc - 1;
435 		do {
436 			REPEAT4(stride, wp[stride] -= wp[0]; wp--)
437 			wc -= stride;
438 		} while ((int32) wc > 0);
439 	}
440 }
441 
442 /*
443  * Floating point predictor differencing routine.
444  */
445 static void
fpDiff(TIFF * tif,tidata_t cp0,tsize_t cc)446 fpDiff(TIFF* tif, tidata_t cp0, tsize_t cc)
447 {
448 	tsize_t stride = PredictorState(tif)->stride;
449 	uint32 bps = tif->tif_dir.td_bitspersample / 8;
450 	tsize_t wc = cc / bps;
451 	tsize_t count;
452 	uint8 *cp = (uint8 *) cp0;
453 	uint8 *tmp = (uint8 *)_TIFFmalloc(cc);
454 
455 	if (!tmp)
456 		return;
457 
458 	_TIFFmemcpy(tmp, cp0, cc);
459 	for (count = 0; count < wc; count++) {
460 		uint32 byte;
461 		for (byte = 0; byte < bps; byte++) {
462 #if WORDS_BIGENDIAN
463 			cp[byte * wc + count] =	tmp[bps * count + byte];
464 #else
465 			cp[(bps - byte - 1) * wc + count] =
466 				tmp[bps * count + byte];
467 #endif
468 		}
469 	}
470 	_TIFFfree(tmp);
471 
472 	cp = (uint8 *) cp0;
473 	cp += cc - stride - 1;
474 	for (count = cc; count > stride; count -= stride)
475 		REPEAT4(stride, cp[stride] -= cp[0]; cp--)
476 }
477 
478 static int
PredictorEncodeRow(TIFF * tif,tidata_t bp,tsize_t cc,tsample_t s)479 PredictorEncodeRow(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
480 {
481 	TIFFPredictorState *sp = PredictorState(tif);
482 
483 	assert(sp != NULL);
484 	assert(sp->pfunc != NULL);
485 	assert(sp->coderow != NULL);
486 
487 	/* XXX horizontal differencing alters user's data XXX */
488 	(*sp->pfunc)(tif, bp, cc);
489 	return (*sp->coderow)(tif, bp, cc, s);
490 }
491 
492 static int
PredictorEncodeTile(TIFF * tif,tidata_t bp0,tsize_t cc0,tsample_t s)493 PredictorEncodeTile(TIFF* tif, tidata_t bp0, tsize_t cc0, tsample_t s)
494 {
495 	TIFFPredictorState *sp = PredictorState(tif);
496 	tsize_t cc = cc0, rowsize;
497 	unsigned char* bp = bp0;
498 
499 	assert(sp != NULL);
500 	assert(sp->pfunc != NULL);
501 	assert(sp->codetile != NULL);
502 
503 	rowsize = sp->rowsize;
504 	assert(rowsize > 0);
505 	while ((long)cc > 0) {
506 		(*sp->pfunc)(tif, bp, (tsize_t) rowsize);
507 		cc -= rowsize;
508 		bp += rowsize;
509 	}
510 	return (*sp->codetile)(tif, bp0, cc0, s);
511 }
512 
513 #define	FIELD_PREDICTOR	(FIELD_CODEC+0)		/* XXX */
514 
515 static const TIFFFieldInfo predictFieldInfo[] = {
516     { TIFFTAG_PREDICTOR,	 1, 1, TIFF_SHORT,	FIELD_PREDICTOR,
517       FALSE,	FALSE,	"Predictor" },
518 };
519 #define	N(a)	(sizeof (a) / sizeof (a[0]))
520 
521 static int
PredictorVSetField(TIFF * tif,ttag_t tag,va_list ap)522 PredictorVSetField(TIFF* tif, ttag_t tag, va_list ap)
523 {
524 	TIFFPredictorState *sp = PredictorState(tif);
525 
526 	assert(sp != NULL);
527 	assert(sp->vsetparent != NULL);
528 
529 	switch (tag) {
530 	case TIFFTAG_PREDICTOR:
531 		sp->predictor = (uint16) va_arg(ap, int);
532 		TIFFSetFieldBit(tif, FIELD_PREDICTOR);
533 		break;
534 	default:
535 		return (*sp->vsetparent)(tif, tag, ap);
536 	}
537 	tif->tif_flags |= TIFF_DIRTYDIRECT;
538 	return 1;
539 }
540 
541 static int
PredictorVGetField(TIFF * tif,ttag_t tag,va_list ap)542 PredictorVGetField(TIFF* tif, ttag_t tag, va_list ap)
543 {
544 	TIFFPredictorState *sp = PredictorState(tif);
545 
546 	assert(sp != NULL);
547 	assert(sp->vgetparent != NULL);
548 
549 	switch (tag) {
550 	case TIFFTAG_PREDICTOR:
551 		*va_arg(ap, uint16*) = sp->predictor;
552 		break;
553 	default:
554 		return (*sp->vgetparent)(tif, tag, ap);
555 	}
556 	return 1;
557 }
558 
559 static void
PredictorPrintDir(TIFF * tif,FILE * fd,long flags)560 PredictorPrintDir(TIFF* tif, FILE* fd, long flags)
561 {
562 	TIFFPredictorState* sp = PredictorState(tif);
563 
564 	(void) flags;
565 	if (TIFFFieldSet(tif,FIELD_PREDICTOR)) {
566 		fprintf(fd, "  Predictor: ");
567 		switch (sp->predictor) {
568 		case 1: fprintf(fd, "none "); break;
569 		case 2: fprintf(fd, "horizontal differencing "); break;
570 		case 3: fprintf(fd, "floating point predictor "); break;
571 		}
572 		fprintf(fd, "%u (0x%x)\n", sp->predictor, sp->predictor);
573 	}
574 	if (sp->printdir)
575 		(*sp->printdir)(tif, fd, flags);
576 }
577 
578 int
TIFFPredictorInit(TIFF * tif)579 TIFFPredictorInit(TIFF* tif)
580 {
581 	TIFFPredictorState* sp = PredictorState(tif);
582 
583 	assert(sp != 0);
584 
585 	/*
586 	 * Merge codec-specific tag information and
587 	 * override parent get/set field methods.
588 	 */
589 	_TIFFMergeFieldInfo(tif, predictFieldInfo, N(predictFieldInfo));
590 	sp->vgetparent = tif->tif_tagmethods.vgetfield;
591 	tif->tif_tagmethods.vgetfield =
592             PredictorVGetField;/* hook for predictor tag */
593 	sp->vsetparent = tif->tif_tagmethods.vsetfield;
594 	tif->tif_tagmethods.vsetfield =
595             PredictorVSetField;/* hook for predictor tag */
596 	sp->printdir = tif->tif_tagmethods.printdir;
597 	tif->tif_tagmethods.printdir =
598             PredictorPrintDir;	/* hook for predictor tag */
599 
600 	sp->setupdecode = tif->tif_setupdecode;
601 	tif->tif_setupdecode = PredictorSetupDecode;
602 	sp->setupencode = tif->tif_setupencode;
603 	tif->tif_setupencode = PredictorSetupEncode;
604 
605 	sp->predictor = 1;			/* default value */
606 	sp->pfunc = NULL;			/* no predictor routine */
607 	return 1;
608 }
609 
610 int
TIFFPredictorCleanup(TIFF * tif)611 TIFFPredictorCleanup(TIFF* tif)
612 {
613 	TIFFPredictorState* sp = PredictorState(tif);
614 
615 	assert(sp != 0);
616 
617 	tif->tif_tagmethods.vgetfield = sp->vgetparent;
618 	tif->tif_tagmethods.vsetfield = sp->vsetparent;
619 	tif->tif_tagmethods.printdir = sp->printdir;
620 	tif->tif_setupdecode = sp->setupdecode;
621 	tif->tif_setupencode = sp->setupencode;
622 
623 	return 1;
624 }
625 
626 /* vim: set ts=8 sts=8 sw=8 noet: */
627