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 113 : {
55 : static const char module[] = "PredictorSetup";
56 :
57 113 : TIFFPredictorState* sp = PredictorState(tif);
58 113 : TIFFDirectory* td = &tif->tif_dir;
59 :
60 113 : switch (sp->predictor) /* no differencing */
61 : {
62 : case PREDICTOR_NONE:
63 96 : return 1;
64 : case PREDICTOR_HORIZONTAL:
65 17 : if (td->td_bitspersample != 8
66 : && td->td_bitspersample != 16
67 : && td->td_bitspersample != 32) {
68 0 : TIFFErrorExt(tif->tif_clientdata, module,
69 : "Horizontal differencing \"Predictor\" not supported with %d-bit samples",
70 : td->td_bitspersample);
71 0 : return 0;
72 : }
73 17 : break;
74 : case PREDICTOR_FLOATINGPOINT:
75 0 : if (td->td_sampleformat != SAMPLEFORMAT_IEEEFP) {
76 0 : TIFFErrorExt(tif->tif_clientdata, module,
77 : "Floating point \"Predictor\" not supported with %d data format",
78 : td->td_sampleformat);
79 0 : return 0;
80 : }
81 0 : break;
82 : default:
83 0 : TIFFErrorExt(tif->tif_clientdata, module,
84 : "\"Predictor\" value %d not supported",
85 : sp->predictor);
86 0 : return 0;
87 : }
88 17 : sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ?
89 : td->td_samplesperpixel : 1);
90 : /*
91 : * Calculate the scanline/tile-width size in bytes.
92 : */
93 17 : if (isTiled(tif))
94 15 : sp->rowsize = TIFFTileRowSize(tif);
95 : else
96 2 : sp->rowsize = TIFFScanlineSize(tif);
97 17 : if (sp->rowsize == 0)
98 0 : return 0;
99 :
100 17 : return 1;
101 : }
102 :
103 : static int
104 : PredictorSetupDecode(TIFF* tif)
105 76 : {
106 76 : TIFFPredictorState* sp = PredictorState(tif);
107 76 : TIFFDirectory* td = &tif->tif_dir;
108 :
109 76 : if (!(*sp->setupdecode)(tif) || !PredictorSetup(tif))
110 0 : return 0;
111 :
112 76 : if (sp->predictor == 2) {
113 6 : switch (td->td_bitspersample) {
114 2 : case 8: sp->decodepfunc = horAcc8; break;
115 4 : case 16: sp->decodepfunc = horAcc16; break;
116 0 : case 32: sp->decodepfunc = horAcc32; break;
117 : }
118 : /*
119 : * Override default decoding method with one that does the
120 : * predictor stuff.
121 : */
122 6 : if( tif->tif_decoderow != PredictorDecodeRow )
123 : {
124 6 : sp->decoderow = tif->tif_decoderow;
125 6 : tif->tif_decoderow = PredictorDecodeRow;
126 6 : sp->decodestrip = tif->tif_decodestrip;
127 6 : tif->tif_decodestrip = PredictorDecodeTile;
128 6 : sp->decodetile = tif->tif_decodetile;
129 6 : 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 6 : if (tif->tif_flags & TIFF_SWAB) {
140 1 : if (sp->decodepfunc == horAcc16) {
141 1 : sp->decodepfunc = swabHorAcc16;
142 1 : tif->tif_postdecode = _TIFFNoPostDecode;
143 0 : } else if (sp->decodepfunc == horAcc32) {
144 0 : sp->decodepfunc = swabHorAcc32;
145 0 : tif->tif_postdecode = _TIFFNoPostDecode;
146 : }
147 : }
148 : }
149 :
150 70 : else if (sp->predictor == 3) {
151 0 : sp->decodepfunc = fpAcc;
152 : /*
153 : * Override default decoding method with one that does the
154 : * predictor stuff.
155 : */
156 0 : if( tif->tif_decoderow != PredictorDecodeRow )
157 : {
158 0 : sp->decoderow = tif->tif_decoderow;
159 0 : tif->tif_decoderow = PredictorDecodeRow;
160 0 : sp->decodestrip = tif->tif_decodestrip;
161 0 : tif->tif_decodestrip = PredictorDecodeTile;
162 0 : sp->decodetile = tif->tif_decodetile;
163 0 : 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 0 : if (tif->tif_flags & TIFF_SWAB) {
171 0 : 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 76 : return 1;
180 : }
181 :
182 : static int
183 : PredictorSetupEncode(TIFF* tif)
184 37 : {
185 37 : TIFFPredictorState* sp = PredictorState(tif);
186 37 : TIFFDirectory* td = &tif->tif_dir;
187 :
188 37 : if (!(*sp->setupencode)(tif) || !PredictorSetup(tif))
189 0 : return 0;
190 :
191 37 : if (sp->predictor == 2) {
192 11 : switch (td->td_bitspersample) {
193 3 : case 8: sp->encodepfunc = horDiff8; break;
194 8 : case 16: sp->encodepfunc = horDiff16; break;
195 0 : case 32: sp->encodepfunc = horDiff32; break;
196 : }
197 : /*
198 : * Override default encoding method with one that does the
199 : * predictor stuff.
200 : */
201 11 : if( tif->tif_encoderow != PredictorEncodeRow )
202 : {
203 10 : sp->encoderow = tif->tif_encoderow;
204 10 : tif->tif_encoderow = PredictorEncodeRow;
205 10 : sp->encodestrip = tif->tif_encodestrip;
206 10 : tif->tif_encodestrip = PredictorEncodeTile;
207 10 : sp->encodetile = tif->tif_encodetile;
208 10 : tif->tif_encodetile = PredictorEncodeTile;
209 : }
210 : }
211 :
212 26 : else if (sp->predictor == 3) {
213 0 : sp->encodepfunc = fpDiff;
214 : /*
215 : * Override default encoding method with one that does the
216 : * predictor stuff.
217 : */
218 0 : if( tif->tif_encoderow != PredictorEncodeRow )
219 : {
220 0 : sp->encoderow = tif->tif_encoderow;
221 0 : tif->tif_encoderow = PredictorEncodeRow;
222 0 : sp->encodestrip = tif->tif_encodestrip;
223 0 : tif->tif_encodestrip = PredictorEncodeTile;
224 0 : sp->encodetile = tif->tif_encodetile;
225 0 : tif->tif_encodetile = PredictorEncodeTile;
226 : }
227 : }
228 :
229 37 : 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 432 : {
245 432 : tmsize_t stride = PredictorState(tif)->stride;
246 :
247 432 : char* cp = (char*) cp0;
248 432 : assert((cc%stride)==0);
249 432 : if (cc > stride) {
250 : /*
251 : * Pipeline the most common cases.
252 : */
253 432 : if (stride == 3) {
254 0 : unsigned int cr = cp[0];
255 0 : unsigned int cg = cp[1];
256 0 : unsigned int cb = cp[2];
257 0 : cc -= 3;
258 0 : cp += 3;
259 0 : while (cc>0) {
260 0 : cp[0] = (char) (cr += cp[0]);
261 0 : cp[1] = (char) (cg += cp[1]);
262 0 : cp[2] = (char) (cb += cp[2]);
263 0 : cc -= 3;
264 0 : cp += 3;
265 : }
266 432 : } else if (stride == 4) {
267 0 : unsigned int cr = cp[0];
268 0 : unsigned int cg = cp[1];
269 0 : unsigned int cb = cp[2];
270 0 : unsigned int ca = cp[3];
271 0 : cc -= 4;
272 0 : cp += 4;
273 0 : while (cc>0) {
274 0 : cp[0] = (char) (cr += cp[0]);
275 0 : cp[1] = (char) (cg += cp[1]);
276 0 : cp[2] = (char) (cb += cp[2]);
277 0 : cp[3] = (char) (ca += cp[3]);
278 0 : cc -= 4;
279 0 : cp += 4;
280 : }
281 : } else {
282 432 : cc -= stride;
283 : do {
284 102992 : REPEAT4(stride, cp[stride] =
285 : (char) (cp[stride] + *cp); cp++)
286 102992 : cc -= stride;
287 102992 : } while (cc>0);
288 : }
289 : }
290 432 : }
291 :
292 : static void
293 : swabHorAcc16(TIFF* tif, uint8* cp0, tmsize_t cc)
294 122 : {
295 122 : tmsize_t stride = PredictorState(tif)->stride;
296 122 : uint16* wp = (uint16*) cp0;
297 122 : tmsize_t wc = cc / 2;
298 :
299 122 : assert((cc%(2*stride))==0);
300 :
301 122 : if (wc > stride) {
302 122 : TIFFSwabArrayOfShort(wp, wc);
303 122 : wc -= stride;
304 : do {
305 15494 : REPEAT4(stride, wp[stride] += wp[0]; wp++)
306 15494 : wc -= stride;
307 15494 : } while (wc > 0);
308 : }
309 122 : }
310 :
311 : static void
312 : horAcc16(TIFF* tif, uint8* cp0, tmsize_t cc)
313 366 : {
314 366 : tmsize_t stride = PredictorState(tif)->stride;
315 366 : uint16* wp = (uint16*) cp0;
316 366 : tmsize_t wc = cc / 2;
317 :
318 366 : assert((cc%(2*stride))==0);
319 :
320 366 : if (wc > stride) {
321 366 : wc -= stride;
322 : do {
323 46482 : REPEAT4(stride, wp[stride] += wp[0]; wp++)
324 46482 : wc -= stride;
325 46482 : } while (wc > 0);
326 : }
327 366 : }
328 :
329 : static void
330 : swabHorAcc32(TIFF* tif, uint8* cp0, tmsize_t cc)
331 0 : {
332 0 : tmsize_t stride = PredictorState(tif)->stride;
333 0 : uint32* wp = (uint32*) cp0;
334 0 : tmsize_t wc = cc / 4;
335 :
336 0 : assert((cc%(4*stride))==0);
337 :
338 0 : if (wc > stride) {
339 0 : TIFFSwabArrayOfLong(wp, wc);
340 0 : wc -= stride;
341 : do {
342 0 : REPEAT4(stride, wp[stride] += wp[0]; wp++)
343 0 : wc -= stride;
344 0 : } while (wc > 0);
345 : }
346 0 : }
347 :
348 : static void
349 : horAcc32(TIFF* tif, uint8* cp0, tmsize_t cc)
350 0 : {
351 0 : tmsize_t stride = PredictorState(tif)->stride;
352 0 : uint32* wp = (uint32*) cp0;
353 0 : tmsize_t wc = cc / 4;
354 :
355 0 : assert((cc%(4*stride))==0);
356 :
357 0 : if (wc > stride) {
358 0 : wc -= stride;
359 : do {
360 0 : REPEAT4(stride, wp[stride] += wp[0]; wp++)
361 0 : wc -= stride;
362 0 : } while (wc > 0);
363 : }
364 0 : }
365 :
366 : /*
367 : * Floating point predictor accumulation routine.
368 : */
369 : static void
370 : fpAcc(TIFF* tif, uint8* cp0, tmsize_t cc)
371 0 : {
372 0 : tmsize_t stride = PredictorState(tif)->stride;
373 0 : uint32 bps = tif->tif_dir.td_bitspersample / 8;
374 0 : tmsize_t wc = cc / bps;
375 0 : tmsize_t count = cc;
376 0 : uint8 *cp = (uint8 *) cp0;
377 0 : uint8 *tmp = (uint8 *)_TIFFmalloc(cc);
378 :
379 0 : assert((cc%(bps*stride))==0);
380 :
381 0 : if (!tmp)
382 0 : return;
383 :
384 0 : while (count > stride) {
385 0 : REPEAT4(stride, cp[stride] += cp[0]; cp++)
386 0 : count -= stride;
387 : }
388 :
389 0 : _TIFFmemcpy(tmp, cp0, cc);
390 0 : cp = (uint8 *) cp0;
391 0 : for (count = 0; count < wc; count++) {
392 : uint32 byte;
393 0 : for (byte = 0; byte < bps; byte++) {
394 : #if WORDS_BIGENDIAN
395 : cp[bps * count + byte] = tmp[byte * wc + count];
396 : #else
397 0 : cp[bps * count + byte] =
398 : tmp[(bps - byte - 1) * wc + count];
399 : #endif
400 : }
401 : }
402 0 : _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 0 : {
411 0 : TIFFPredictorState *sp = PredictorState(tif);
412 :
413 0 : assert(sp != NULL);
414 0 : assert(sp->decoderow != NULL);
415 0 : assert(sp->decodepfunc != NULL);
416 :
417 0 : if ((*sp->decoderow)(tif, op0, occ0, s)) {
418 0 : (*sp->decodepfunc)(tif, op0, occ0);
419 0 : return 1;
420 : } else
421 0 : 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 7 : {
434 7 : TIFFPredictorState *sp = PredictorState(tif);
435 :
436 7 : assert(sp != NULL);
437 7 : assert(sp->decodetile != NULL);
438 :
439 7 : if ((*sp->decodetile)(tif, op0, occ0, s)) {
440 7 : tmsize_t rowsize = sp->rowsize;
441 7 : assert(rowsize > 0);
442 7 : assert((occ0%rowsize)==0);
443 7 : assert(sp->decodepfunc != NULL);
444 934 : while (occ0 > 0) {
445 920 : (*sp->decodepfunc)(tif, op0, rowsize);
446 920 : occ0 -= rowsize;
447 920 : op0 += rowsize;
448 : }
449 7 : return 1;
450 : } else
451 0 : return 0;
452 : }
453 :
454 : static void
455 : horDiff8(TIFF* tif, uint8* cp0, tmsize_t cc)
456 2080 : {
457 2080 : TIFFPredictorState* sp = PredictorState(tif);
458 2080 : tmsize_t stride = sp->stride;
459 2080 : char* cp = (char*) cp0;
460 :
461 2080 : assert((cc%stride)==0);
462 :
463 2080 : if (cc > stride) {
464 2080 : cc -= stride;
465 : /*
466 : * Pipeline the most common cases.
467 : */
468 2080 : if (stride == 3) {
469 : int r1, g1, b1;
470 0 : int r2 = cp[0];
471 0 : int g2 = cp[1];
472 0 : int b2 = cp[2];
473 : do {
474 0 : r1 = cp[3]; cp[3] = r1-r2; r2 = r1;
475 0 : g1 = cp[4]; cp[4] = g1-g2; g2 = g1;
476 0 : b1 = cp[5]; cp[5] = b1-b2; b2 = b1;
477 0 : cp += 3;
478 0 : } while ((cc -= 3) > 0);
479 2080 : } else if (stride == 4) {
480 : int r1, g1, b1, a1;
481 0 : int r2 = cp[0];
482 0 : int g2 = cp[1];
483 0 : int b2 = cp[2];
484 0 : int a2 = cp[3];
485 : do {
486 0 : r1 = cp[4]; cp[4] = r1-r2; r2 = r1;
487 0 : g1 = cp[5]; cp[5] = g1-g2; g2 = g1;
488 0 : b1 = cp[6]; cp[6] = b1-b2; b2 = b1;
489 0 : a1 = cp[7]; cp[7] = a1-a2; a2 = a1;
490 0 : cp += 4;
491 0 : } while ((cc -= 4) > 0);
492 : } else {
493 2080 : cp += cc - 1;
494 : do {
495 179168 : REPEAT4(stride, cp[stride] -= cp[0]; cp--)
496 179168 : } while ((cc -= stride) > 0);
497 : }
498 : }
499 2080 : }
500 :
501 : static void
502 : horDiff16(TIFF* tif, uint8* cp0, tmsize_t cc)
503 1010 : {
504 1010 : TIFFPredictorState* sp = PredictorState(tif);
505 1010 : tmsize_t stride = sp->stride;
506 1010 : int16 *wp = (int16*) cp0;
507 1010 : tmsize_t wc = cc/2;
508 :
509 1010 : assert((cc%(2*stride))==0);
510 :
511 1010 : if (wc > stride) {
512 1010 : wc -= stride;
513 1010 : wp += wc - 1;
514 : do {
515 126576 : REPEAT4(stride, wp[stride] -= wp[0]; wp--)
516 126576 : wc -= stride;
517 126576 : } while (wc > 0);
518 : }
519 1010 : }
520 :
521 : static void
522 : horDiff32(TIFF* tif, uint8* cp0, tmsize_t cc)
523 0 : {
524 0 : TIFFPredictorState* sp = PredictorState(tif);
525 0 : tmsize_t stride = sp->stride;
526 0 : int32 *wp = (int32*) cp0;
527 0 : tmsize_t wc = cc/4;
528 :
529 0 : assert((cc%(4*stride))==0);
530 :
531 0 : if (wc > stride) {
532 0 : wc -= stride;
533 0 : wp += wc - 1;
534 : do {
535 0 : REPEAT4(stride, wp[stride] -= wp[0]; wp--)
536 0 : wc -= stride;
537 0 : } while (wc > 0);
538 : }
539 0 : }
540 :
541 : /*
542 : * Floating point predictor differencing routine.
543 : */
544 : static void
545 : fpDiff(TIFF* tif, uint8* cp0, tmsize_t cc)
546 0 : {
547 0 : tmsize_t stride = PredictorState(tif)->stride;
548 0 : uint32 bps = tif->tif_dir.td_bitspersample / 8;
549 0 : tmsize_t wc = cc / bps;
550 : tmsize_t count;
551 0 : uint8 *cp = (uint8 *) cp0;
552 0 : uint8 *tmp = (uint8 *)_TIFFmalloc(cc);
553 :
554 0 : assert((cc%(bps*stride))==0);
555 :
556 0 : if (!tmp)
557 0 : return;
558 :
559 0 : _TIFFmemcpy(tmp, cp0, cc);
560 0 : for (count = 0; count < wc; count++) {
561 : uint32 byte;
562 0 : for (byte = 0; byte < bps; byte++) {
563 : #if WORDS_BIGENDIAN
564 : cp[byte * wc + count] = tmp[bps * count + byte];
565 : #else
566 0 : cp[(bps - byte - 1) * wc + count] =
567 : tmp[bps * count + byte];
568 : #endif
569 : }
570 : }
571 0 : _TIFFfree(tmp);
572 :
573 0 : cp = (uint8 *) cp0;
574 0 : cp += cc - stride - 1;
575 0 : for (count = cc; count > stride; count -= stride)
576 0 : REPEAT4(stride, cp[stride] -= cp[0]; cp--)
577 : }
578 :
579 : static int
580 : PredictorEncodeRow(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
581 0 : {
582 0 : TIFFPredictorState *sp = PredictorState(tif);
583 :
584 0 : assert(sp != NULL);
585 0 : assert(sp->encodepfunc != NULL);
586 0 : assert(sp->encoderow != NULL);
587 :
588 : /* XXX horizontal differencing alters user's data XXX */
589 0 : (*sp->encodepfunc)(tif, bp, cc);
590 0 : return (*sp->encoderow)(tif, bp, cc, s);
591 : }
592 :
593 : static int
594 : PredictorEncodeTile(TIFF* tif, uint8* bp0, tmsize_t cc0, uint16 s)
595 65 : {
596 : static const char module[] = "PredictorEncodeTile";
597 65 : TIFFPredictorState *sp = PredictorState(tif);
598 : uint8 *working_copy;
599 65 : tmsize_t cc = cc0, rowsize;
600 : unsigned char* bp;
601 : int result_code;
602 :
603 65 : assert(sp != NULL);
604 65 : assert(sp->encodepfunc != NULL);
605 65 : 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 65 : working_copy = (uint8*) _TIFFmalloc(cc0);
612 65 : if( working_copy == NULL )
613 : {
614 0 : TIFFErrorExt(tif->tif_clientdata, module,
615 : "Out of memory allocating " TIFF_SSIZE_FORMAT " byte temp buffer.",
616 : cc0 );
617 0 : return 0;
618 : }
619 65 : memcpy( working_copy, bp0, cc0 );
620 65 : bp = working_copy;
621 :
622 65 : rowsize = sp->rowsize;
623 65 : assert(rowsize > 0);
624 65 : assert((cc0%rowsize)==0);
625 3220 : while (cc > 0) {
626 3090 : (*sp->encodepfunc)(tif, bp, rowsize);
627 3090 : cc -= rowsize;
628 3090 : bp += rowsize;
629 : }
630 65 : result_code = (*sp->encodetile)(tif, working_copy, cc0, s);
631 :
632 65 : _TIFFfree( working_copy );
633 :
634 65 : 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 2977 : {
646 2977 : TIFFPredictorState *sp = PredictorState(tif);
647 :
648 2977 : assert(sp != NULL);
649 2977 : assert(sp->vsetparent != NULL);
650 :
651 2977 : switch (tag) {
652 : case TIFFTAG_PREDICTOR:
653 252 : sp->predictor = (uint16) va_arg(ap, uint16_vap);
654 252 : TIFFSetFieldBit(tif, FIELD_PREDICTOR);
655 : break;
656 : default:
657 2725 : return (*sp->vsetparent)(tif, tag, ap);
658 : }
659 252 : tif->tif_flags |= TIFF_DIRTYDIRECT;
660 252 : return 1;
661 : }
662 :
663 : static int
664 : PredictorVGetField(TIFF* tif, uint32 tag, va_list ap)
665 3927 : {
666 3927 : TIFFPredictorState *sp = PredictorState(tif);
667 :
668 3927 : assert(sp != NULL);
669 3927 : assert(sp->vgetparent != NULL);
670 :
671 3927 : switch (tag) {
672 : case TIFFTAG_PREDICTOR:
673 105 : *va_arg(ap, uint16*) = sp->predictor;
674 : break;
675 : default:
676 3822 : return (*sp->vgetparent)(tif, tag, ap);
677 : }
678 105 : return 1;
679 : }
680 :
681 : static void
682 : PredictorPrintDir(TIFF* tif, FILE* fd, long flags)
683 0 : {
684 0 : TIFFPredictorState* sp = PredictorState(tif);
685 :
686 : (void) flags;
687 0 : if (TIFFFieldSet(tif,FIELD_PREDICTOR)) {
688 0 : fprintf(fd, " Predictor: ");
689 0 : switch (sp->predictor) {
690 0 : case 1: fprintf(fd, "none "); break;
691 0 : case 2: fprintf(fd, "horizontal differencing "); break;
692 0 : case 3: fprintf(fd, "floating point predictor "); break;
693 : }
694 0 : fprintf(fd, "%u (0x%x)\n", sp->predictor, sp->predictor);
695 : }
696 0 : if (sp->printdir)
697 0 : (*sp->printdir)(tif, fd, flags);
698 0 : }
699 :
700 : int
701 : TIFFPredictorInit(TIFF* tif)
702 298 : {
703 298 : TIFFPredictorState* sp = PredictorState(tif);
704 :
705 298 : assert(sp != 0);
706 :
707 : /*
708 : * Merge codec-specific tag information.
709 : */
710 298 : if (!_TIFFMergeFields(tif, predictFields,
711 : TIFFArrayCount(predictFields))) {
712 0 : TIFFErrorExt(tif->tif_clientdata, "TIFFPredictorInit",
713 : "Merging Predictor codec-specific tags failed");
714 0 : return 0;
715 : }
716 :
717 : /*
718 : * Override parent get/set field methods.
719 : */
720 298 : sp->vgetparent = tif->tif_tagmethods.vgetfield;
721 298 : tif->tif_tagmethods.vgetfield =
722 : PredictorVGetField;/* hook for predictor tag */
723 298 : sp->vsetparent = tif->tif_tagmethods.vsetfield;
724 298 : tif->tif_tagmethods.vsetfield =
725 : PredictorVSetField;/* hook for predictor tag */
726 298 : sp->printdir = tif->tif_tagmethods.printdir;
727 298 : tif->tif_tagmethods.printdir =
728 : PredictorPrintDir; /* hook for predictor tag */
729 :
730 298 : sp->setupdecode = tif->tif_setupdecode;
731 298 : tif->tif_setupdecode = PredictorSetupDecode;
732 298 : sp->setupencode = tif->tif_setupencode;
733 298 : tif->tif_setupencode = PredictorSetupEncode;
734 :
735 298 : sp->predictor = 1; /* default value */
736 298 : sp->encodepfunc = NULL; /* no predictor routine */
737 298 : sp->decodepfunc = NULL; /* no predictor routine */
738 298 : return 1;
739 : }
740 :
741 : int
742 : TIFFPredictorCleanup(TIFF* tif)
743 288 : {
744 288 : TIFFPredictorState* sp = PredictorState(tif);
745 :
746 288 : assert(sp != 0);
747 :
748 288 : tif->tif_tagmethods.vgetfield = sp->vgetparent;
749 288 : tif->tif_tagmethods.vsetfield = sp->vsetparent;
750 288 : tif->tif_tagmethods.printdir = sp->printdir;
751 288 : tif->tif_setupdecode = sp->setupdecode;
752 288 : tif->tif_setupencode = sp->setupencode;
753 :
754 288 : 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 : */
|