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