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