source: trunk/third/tiff/libtiff/tif_predict.c @ 18174

Revision 18174, 11.7 KB checked in by ghudson, 22 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18173, which included commits to RCS files with non-trunk default branches.
Line 
1/* $Header: /afs/dev.mit.edu/source/repository/third/tiff/libtiff/tif_predict.c,v 1.1.1.1 2002-12-26 02:37:17 ghudson 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#include <assert.h>
36
37#define PredictorState(tif)     ((TIFFPredictorState*) (tif)->tif_data)
38
39static  void horAcc8(TIFF*, tidata_t, tsize_t);
40static  void horAcc16(TIFF*, tidata_t, tsize_t);
41static  void swabHorAcc16(TIFF*, tidata_t, tsize_t);
42static  void horDiff8(TIFF*, tidata_t, tsize_t);
43static  void horDiff16(TIFF*, tidata_t, tsize_t);
44static  int PredictorDecodeRow(TIFF*, tidata_t, tsize_t, tsample_t);
45static  int PredictorDecodeTile(TIFF*, tidata_t, tsize_t, tsample_t);
46static  int PredictorEncodeRow(TIFF*, tidata_t, tsize_t, tsample_t);
47static  int PredictorEncodeTile(TIFF*, tidata_t, tsize_t, tsample_t);
48
49static int
50PredictorSetup(TIFF* tif)
51{
52        TIFFPredictorState* sp = PredictorState(tif);
53        TIFFDirectory* td = &tif->tif_dir;
54
55        if (sp->predictor == 1)         /* no differencing */
56                return (1);
57        if (sp->predictor != 2) {
58                TIFFError(tif->tif_name, "\"Predictor\" value %d not supported",
59                    sp->predictor);
60                return (0);
61        }
62        if (td->td_bitspersample != 8 && td->td_bitspersample != 16) {
63                TIFFError(tif->tif_name,
64    "Horizontal differencing \"Predictor\" not supported with %d-bit samples",
65                    td->td_bitspersample);
66                return (0);
67        }
68        sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ?
69            td->td_samplesperpixel : 1);
70        /*
71         * Calculate the scanline/tile-width size in bytes.
72         */
73        if (isTiled(tif))
74                sp->rowsize = TIFFTileRowSize(tif);
75        else
76                sp->rowsize = TIFFScanlineSize(tif);
77        return (1);
78}
79
80static int
81PredictorSetupDecode(TIFF* tif)
82{
83        TIFFPredictorState* sp = PredictorState(tif);
84        TIFFDirectory* td = &tif->tif_dir;
85
86        if (!(*sp->setupdecode)(tif) || !PredictorSetup(tif))
87                return (0);
88        if (sp->predictor == 2) {
89                switch (td->td_bitspersample) {
90                case 8:  sp->pfunc = horAcc8; break;
91                case 16: sp->pfunc = horAcc16; break;
92                }
93                /*
94                 * Override default decoding method with
95                 * one that does the predictor stuff.
96                 */
97                sp->coderow = tif->tif_decoderow;
98                tif->tif_decoderow = PredictorDecodeRow;
99                sp->codestrip = tif->tif_decodestrip;
100                tif->tif_decodestrip = PredictorDecodeTile;
101                sp->codetile = tif->tif_decodetile;
102                tif->tif_decodetile = PredictorDecodeTile;
103                /*
104                 * If the data is horizontally differenced
105                 * 16-bit data that requires byte-swapping,
106                 * then it must be byte swapped before the
107                 * accumulation step.  We do this with a
108                 * special-purpose routine and override the
109                 * normal post decoding logic that the library
110                 * setup when the directory was read.
111                 */
112                if (tif->tif_flags&TIFF_SWAB) {
113                        if (sp->pfunc == horAcc16) {
114                                sp->pfunc = swabHorAcc16;
115                                tif->tif_postdecode = _TIFFNoPostDecode;
116                        } /* else handle 32-bit case... */
117                }
118        }
119        return (1);
120}
121
122static int
123PredictorSetupEncode(TIFF* tif)
124{
125        TIFFPredictorState* sp = PredictorState(tif);
126        TIFFDirectory* td = &tif->tif_dir;
127
128        if (!(*sp->setupencode)(tif) || !PredictorSetup(tif))
129                return (0);
130        if (sp->predictor == 2) {
131                switch (td->td_bitspersample) {
132                case 8:  sp->pfunc = horDiff8; break;
133                case 16: sp->pfunc = horDiff16; break;
134                }
135                /*
136                 * Override default encoding method with
137                 * one that does the predictor stuff.
138                 */
139                sp->coderow = tif->tif_encoderow;
140                tif->tif_encoderow = PredictorEncodeRow;
141                sp->codestrip = tif->tif_encodestrip;
142                tif->tif_encodestrip = PredictorEncodeTile;
143                sp->codetile = tif->tif_encodetile;
144                tif->tif_encodetile = PredictorEncodeTile;
145        }
146        return (1);
147}
148
149#define REPEAT4(n, op)          \
150    switch (n) {                \
151    default: { int i; for (i = n-4; i > 0; i--) { op; } } \
152    case 4:  op;                \
153    case 3:  op;                \
154    case 2:  op;                \
155    case 1:  op;                \
156    case 0:  ;                  \
157    }
158
159static void
160horAcc8(TIFF* tif, tidata_t cp0, tsize_t cc)
161{
162        TIFFPredictorState* sp = PredictorState(tif);
163        tsize_t stride = sp->stride;
164
165        char* cp = (char*) cp0;
166        if (cc > stride) {
167                cc -= stride;
168                /*
169                 * Pipeline the most common cases.
170                 */
171                if (stride == 3)  {
172                        u_int cr = cp[0];
173                        u_int cg = cp[1];
174                        u_int cb = cp[2];
175                        do {
176                                cc -= 3, cp += 3;
177                                cp[0] = (cr += cp[0]);
178                                cp[1] = (cg += cp[1]);
179                                cp[2] = (cb += cp[2]);
180                        } while ((int32) cc > 0);
181                } else if (stride == 4)  {
182                        u_int cr = cp[0];
183                        u_int cg = cp[1];
184                        u_int cb = cp[2];
185                        u_int ca = cp[3];
186                        do {
187                                cc -= 4, cp += 4;
188                                cp[0] = (cr += cp[0]);
189                                cp[1] = (cg += cp[1]);
190                                cp[2] = (cb += cp[2]);
191                                cp[3] = (ca += cp[3]);
192                        } while ((int32) cc > 0);
193                } else  {
194                        do {
195                                REPEAT4(stride, cp[stride] += *cp; cp++)
196                                cc -= stride;
197                        } while ((int32) cc > 0);
198                }
199        }
200}
201
202static void
203swabHorAcc16(TIFF* tif, tidata_t cp0, tsize_t cc)
204{
205        TIFFPredictorState* sp = PredictorState(tif);
206        tsize_t stride = sp->stride;
207        uint16* wp = (uint16*) cp0;
208        tsize_t wc = cc / 2;
209
210        if (wc > stride) {
211                TIFFSwabArrayOfShort(wp, wc);
212                wc -= stride;
213                do {
214                        REPEAT4(stride, wp[stride] += wp[0]; wp++)
215                        wc -= stride;
216                } while ((int32) wc > 0);
217        }
218}
219
220static void
221horAcc16(TIFF* tif, tidata_t cp0, tsize_t cc)
222{
223        tsize_t stride = PredictorState(tif)->stride;
224        uint16* wp = (uint16*) cp0;
225        tsize_t wc = cc / 2;
226
227        if (wc > stride) {
228                wc -= stride;
229                do {
230                        REPEAT4(stride, wp[stride] += wp[0]; wp++)
231                        wc -= stride;
232                } while ((int32) wc > 0);
233        }
234}
235
236/*
237 * Decode a scanline and apply the predictor routine.
238 */
239static int
240PredictorDecodeRow(TIFF* tif, tidata_t op0, tsize_t occ0, tsample_t s)
241{
242        TIFFPredictorState *sp = PredictorState(tif);
243
244        assert(sp != NULL);
245        assert(sp->coderow != NULL);
246        assert(sp->pfunc != NULL);
247        if ((*sp->coderow)(tif, op0, occ0, s)) {
248                (*sp->pfunc)(tif, op0, occ0);
249                return (1);
250        } else
251                return (0);
252}
253
254/*
255 * Decode a tile/strip and apply the predictor routine.
256 * Note that horizontal differencing must be done on a
257 * row-by-row basis.  The width of a "row" has already
258 * been calculated at pre-decode time according to the
259 * strip/tile dimensions.
260 */
261static int
262PredictorDecodeTile(TIFF* tif, tidata_t op0, tsize_t occ0, tsample_t s)
263{
264        TIFFPredictorState *sp = PredictorState(tif);
265
266        assert(sp != NULL);
267        assert(sp->codetile != NULL);
268        if ((*sp->codetile)(tif, op0, occ0, s)) {
269                tsize_t rowsize = sp->rowsize;
270                assert(rowsize > 0);
271                assert(sp->pfunc != NULL);
272                while ((long)occ0 > 0) {
273                        (*sp->pfunc)(tif, op0, (tsize_t) rowsize);
274                        occ0 -= rowsize;
275                        op0 += rowsize;
276                }
277                return (1);
278        } else
279                return (0);
280}
281
282static void
283horDiff8(TIFF* tif, tidata_t cp0, tsize_t cc)
284{
285        TIFFPredictorState* sp = PredictorState(tif);
286        tsize_t stride = sp->stride;
287        char* cp = (char*) cp0;
288
289        if (cc > stride) {
290                cc -= stride;
291                /*
292                 * Pipeline the most common cases.
293                 */
294                if (stride == 3) {
295                        int r1, g1, b1;
296                        int r2 = cp[0];
297                        int g2 = cp[1];
298                        int b2 = cp[2];
299                        do {
300                                r1 = cp[3]; cp[3] = r1-r2; r2 = r1;
301                                g1 = cp[4]; cp[4] = g1-g2; g2 = g1;
302                                b1 = cp[5]; cp[5] = b1-b2; b2 = b1;
303                                cp += 3;
304                        } while ((int32)(cc -= 3) > 0);
305                } else if (stride == 4) {
306                        int r1, g1, b1, a1;
307                        int r2 = cp[0];
308                        int g2 = cp[1];
309                        int b2 = cp[2];
310                        int a2 = cp[3];
311                        do {
312                                r1 = cp[4]; cp[4] = r1-r2; r2 = r1;
313                                g1 = cp[5]; cp[5] = g1-g2; g2 = g1;
314                                b1 = cp[6]; cp[6] = b1-b2; b2 = b1;
315                                a1 = cp[7]; cp[7] = a1-a2; a2 = a1;
316                                cp += 4;
317                        } while ((int32)(cc -= 4) > 0);
318                } else {
319                        cp += cc - 1;
320                        do {
321                                REPEAT4(stride, cp[stride] -= cp[0]; cp--)
322                        } while ((int32)(cc -= stride) > 0);
323                }
324        }
325}
326
327static void
328horDiff16(TIFF* tif, tidata_t cp0, tsize_t cc)
329{
330        TIFFPredictorState* sp = PredictorState(tif);
331        tsize_t stride = sp->stride;
332        int16 *wp = (int16*) cp0;
333        tsize_t wc = cc/2;
334
335        if (wc > stride) {
336                wc -= stride;
337                wp += wc - 1;
338                do {
339                        REPEAT4(stride, wp[stride] -= wp[0]; wp--)
340                        wc -= stride;
341                } while ((int32) wc > 0);
342        }
343}
344
345static int
346PredictorEncodeRow(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
347{
348        TIFFPredictorState *sp = PredictorState(tif);
349
350        assert(sp != NULL);
351        assert(sp->pfunc != NULL);
352        assert(sp->coderow != NULL);
353/* XXX horizontal differencing alters user's data XXX */
354        (*sp->pfunc)(tif, bp, cc);
355        return ((*sp->coderow)(tif, bp, cc, s));
356}
357
358static int
359PredictorEncodeTile(TIFF* tif, tidata_t bp0, tsize_t cc0, tsample_t s)
360{
361        TIFFPredictorState *sp = PredictorState(tif);
362        tsize_t cc = cc0, rowsize;
363        u_char* bp = bp0;
364
365        assert(sp != NULL);
366        assert(sp->pfunc != NULL);
367        assert(sp->codetile != NULL);
368        rowsize = sp->rowsize;
369        assert(rowsize > 0);
370        while ((long)cc > 0) {
371                (*sp->pfunc)(tif, bp, (tsize_t) rowsize);
372                cc -= rowsize;
373                bp += rowsize;
374        }
375        return ((*sp->codetile)(tif, bp0, cc0, s));
376}
377
378#define FIELD_PREDICTOR (FIELD_CODEC+0)         /* XXX */
379
380static const TIFFFieldInfo predictFieldInfo[] = {
381    { TIFFTAG_PREDICTOR,         1, 1, TIFF_SHORT,      FIELD_PREDICTOR,
382      FALSE,    FALSE,  "Predictor" },
383};
384#define N(a)    (sizeof (a) / sizeof (a[0]))
385
386static int
387PredictorVSetField(TIFF* tif, ttag_t tag, va_list ap)
388{
389        TIFFPredictorState *sp = PredictorState(tif);
390
391        switch (tag) {
392        case TIFFTAG_PREDICTOR:
393                sp->predictor = (uint16) va_arg(ap, int);
394                TIFFSetFieldBit(tif, FIELD_PREDICTOR);
395                break;
396        default:
397                return (*sp->vsetparent)(tif, tag, ap);
398        }
399        tif->tif_flags |= TIFF_DIRTYDIRECT;
400        return (1);
401}
402
403static int
404PredictorVGetField(TIFF* tif, ttag_t tag, va_list ap)
405{
406        TIFFPredictorState *sp = PredictorState(tif);
407
408        switch (tag) {
409        case TIFFTAG_PREDICTOR:
410                *va_arg(ap, uint16*) = sp->predictor;
411                break;
412        default:
413                return (*sp->vgetparent)(tif, tag, ap);
414        }
415        return (1);
416}
417
418static void
419PredictorPrintDir(TIFF* tif, FILE* fd, long flags)
420{
421        TIFFPredictorState* sp = PredictorState(tif);
422
423        (void) flags;
424        if (TIFFFieldSet(tif,FIELD_PREDICTOR)) {
425                fprintf(fd, "  Predictor: ");
426                switch (sp->predictor) {
427                case 1: fprintf(fd, "none "); break;
428                case 2: fprintf(fd, "horizontal differencing "); break;
429                }
430                fprintf(fd, "%u (0x%x)\n", sp->predictor, sp->predictor);
431        }
432        if (sp->printdir)
433                (*sp->printdir)(tif, fd, flags);
434}
435
436int
437TIFFPredictorInit(TIFF* tif)
438{
439        TIFFPredictorState* sp = PredictorState(tif);
440
441        /*
442         * Merge codec-specific tag information and
443         * override parent get/set field methods.
444         */
445        _TIFFMergeFieldInfo(tif, predictFieldInfo, N(predictFieldInfo));
446        sp->vgetparent = tif->tif_vgetfield;
447        tif->tif_vgetfield = PredictorVGetField;/* hook for predictor tag */
448        sp->vsetparent = tif->tif_vsetfield;
449        tif->tif_vsetfield = PredictorVSetField;/* hook for predictor tag */
450        sp->printdir = tif->tif_printdir;
451        tif->tif_printdir = PredictorPrintDir;  /* hook for predictor tag */
452
453        sp->setupdecode = tif->tif_setupdecode;
454        tif->tif_setupdecode = PredictorSetupDecode;
455        sp->setupencode = tif->tif_setupencode;
456        tif->tif_setupencode = PredictorSetupEncode;
457
458        sp->predictor = 1;                      /* default value */
459        sp->pfunc = NULL;                       /* no predictor routine */
460        return (1);
461}
Note: See TracBrowser for help on using the repository browser.