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

Revision 18174, 35.1 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/*
2 * Copyright (c) 1996-1997 Sam Leffler
3 * Copyright (c) 1996 Pixar
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and
6 * its documentation for any purpose is hereby granted without fee, provided
7 * that (i) the above copyright notices and this permission notice appear in
8 * all copies of the software and related documentation, and (ii) the names of
9 * Pixar, Sam Leffler and Silicon Graphics may not be used in any advertising or
10 * publicity relating to the software without the specific, prior written
11 * permission of Pixar, Sam Leffler and Silicon Graphics.
12 *
13 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
14 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
15 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 
16 *
17 * IN NO EVENT SHALL PIXAR, SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
18 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
21 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22 * OF THIS SOFTWARE.
23 */
24
25#include "tiffiop.h"
26#ifdef PIXARLOG_SUPPORT
27
28/*
29 * TIFF Library.
30 * PixarLog Compression Support
31 *
32 * Contributed by Dan McCoy.
33 *
34 * PixarLog film support uses the TIFF library to store companded
35 * 11 bit values into a tiff file, which are compressed using the
36 * zip compressor. 
37 *
38 * The codec can take as input and produce as output 32-bit IEEE float values
39 * as well as 16-bit or 8-bit unsigned integer values.
40 *
41 * On writing any of the above are converted into the internal
42 * 11-bit log format.   In the case of  8 and 16 bit values, the
43 * input is assumed to be unsigned linear color values that represent
44 * the range 0-1.  In the case of IEEE values, the 0-1 range is assumed to
45 * be the normal linear color range, in addition over 1 values are
46 * accepted up to a value of about 25.0 to encode "hot" hightlights and such.
47 * The encoding is lossless for 8-bit values, slightly lossy for the
48 * other bit depths.  The actual color precision should be better
49 * than the human eye can perceive with extra room to allow for
50 * error introduced by further image computation.  As with any quantized
51 * color format, it is possible to perform image calculations which
52 * expose the quantization error. This format should certainly be less
53 * susceptable to such errors than standard 8-bit encodings, but more
54 * susceptable than straight 16-bit or 32-bit encodings.
55 *
56 * On reading the internal format is converted to the desired output format.
57 * The program can request which format it desires by setting the internal
58 * pseudo tag TIFFTAG_PIXARLOGDATAFMT to one of these possible values:
59 *  PIXARLOGDATAFMT_FLOAT     = provide IEEE float values.
60 *  PIXARLOGDATAFMT_16BIT     = provide unsigned 16-bit integer values
61 *  PIXARLOGDATAFMT_8BIT      = provide unsigned 8-bit integer values
62 *
63 * alternately PIXARLOGDATAFMT_8BITABGR provides unsigned 8-bit integer
64 * values with the difference that if there are exactly three or four channels
65 * (rgb or rgba) it swaps the channel order (bgr or abgr).
66 *
67 * PIXARLOGDATAFMT_11BITLOG provides the internal encoding directly
68 * packed in 16-bit values.   However no tools are supplied for interpreting
69 * these values.
70 *
71 * "hot" (over 1.0) areas written in floating point get clamped to
72 * 1.0 in the integer data types.
73 *
74 * When the file is closed after writing, the bit depth and sample format
75 * are set always to appear as if 8-bit data has been written into it.
76 * That way a naive program unaware of the particulars of the encoding
77 * gets the format it is most likely able to handle.
78 *
79 * The codec does it's own horizontal differencing step on the coded
80 * values so the libraries predictor stuff should be turned off.
81 * The codec also handle byte swapping the encoded values as necessary
82 * since the library does not have the information necessary
83 * to know the bit depth of the raw unencoded buffer.
84 *
85 */
86
87#include "tif_predict.h"
88#include "zlib.h"
89#include "zutil.h"
90
91#include <stdio.h>
92#include <assert.h>
93#include <stdlib.h>
94#include <math.h>
95
96/* Tables for converting to/from 11 bit coded values */
97
98#define  TSIZE   2048           /* decode table size (11-bit tokens) */
99#define  TSIZEP1 2049           /* Plus one for slop */
100#define  ONE     1250           /* token value of 1.0 exactly */
101#define  RATIO   1.004          /* nominal ratio for log part */
102
103#define CODE_MASK 0x7ff         /* 11 bits. */
104
105static float  Fltsize;
106static float  LogK1, LogK2;
107
108#define REPEAT(n, op)   { int i; i=n; do { i--; op; } while (i>0); }
109
110static void
111horizontalAccumulateF(uint16 *wp, int n, int stride, float *op,
112        float *ToLinearF)
113{
114    register unsigned int  cr, cg, cb, ca, mask;
115    register float  t0, t1, t2, t3;
116
117    if (n >= stride) {
118        mask = CODE_MASK;
119        if (stride == 3) {
120            t0 = ToLinearF[cr = wp[0]];
121            t1 = ToLinearF[cg = wp[1]];
122            t2 = ToLinearF[cb = wp[2]];
123            op[0] = t0;
124            op[1] = t1;
125            op[2] = t2;
126            n -= 3;
127            while (n > 0) {
128                wp += 3;
129                op += 3;
130                n -= 3;
131                t0 = ToLinearF[(cr += wp[0]) & mask];
132                t1 = ToLinearF[(cg += wp[1]) & mask];
133                t2 = ToLinearF[(cb += wp[2]) & mask];
134                op[0] = t0;
135                op[1] = t1;
136                op[2] = t2;
137            }
138        } else if (stride == 4) {
139            t0 = ToLinearF[cr = wp[0]];
140            t1 = ToLinearF[cg = wp[1]];
141            t2 = ToLinearF[cb = wp[2]];
142            t3 = ToLinearF[ca = wp[3]];
143            op[0] = t0;
144            op[1] = t1;
145            op[2] = t2;
146            op[3] = t3;
147            n -= 4;
148            while (n > 0) {
149                wp += 4;
150                op += 4;
151                n -= 4;
152                t0 = ToLinearF[(cr += wp[0]) & mask];
153                t1 = ToLinearF[(cg += wp[1]) & mask];
154                t2 = ToLinearF[(cb += wp[2]) & mask];
155                t3 = ToLinearF[(ca += wp[3]) & mask];
156                op[0] = t0;
157                op[1] = t1;
158                op[2] = t2;
159                op[3] = t3;
160            }
161        } else {
162            REPEAT(stride, *op = ToLinearF[*wp&mask]; wp++; op++)
163            n -= stride;
164            while (n > 0) {
165                REPEAT(stride,
166                    wp[stride] += *wp; *op = ToLinearF[*wp&mask]; wp++; op++)
167                n -= stride;
168            }
169        }
170    }
171}
172
173static void
174horizontalAccumulate12(uint16 *wp, int n, int stride, int16 *op,
175        float *ToLinearF)
176{
177    register unsigned int  cr, cg, cb, ca, mask;
178    register float  t0, t1, t2, t3;
179
180#define SCALE12 2048.0
181#define CLAMP12(t) (((t) < 3071) ? (uint16) (t) : 3071)
182
183    if (n >= stride) {
184        mask = CODE_MASK;
185        if (stride == 3) {
186            t0 = ToLinearF[cr = wp[0]] * SCALE12;
187            t1 = ToLinearF[cg = wp[1]] * SCALE12;
188            t2 = ToLinearF[cb = wp[2]] * SCALE12;
189            op[0] = CLAMP12(t0);
190            op[1] = CLAMP12(t1);
191            op[2] = CLAMP12(t2);
192            n -= 3;
193            while (n > 0) {
194                wp += 3;
195                op += 3;
196                n -= 3;
197                t0 = ToLinearF[(cr += wp[0]) & mask] * SCALE12;
198                t1 = ToLinearF[(cg += wp[1]) & mask] * SCALE12;
199                t2 = ToLinearF[(cb += wp[2]) & mask] * SCALE12;
200                op[0] = CLAMP12(t0);
201                op[1] = CLAMP12(t1);
202                op[2] = CLAMP12(t2);
203            }
204        } else if (stride == 4) {
205            t0 = ToLinearF[cr = wp[0]] * SCALE12;
206            t1 = ToLinearF[cg = wp[1]] * SCALE12;
207            t2 = ToLinearF[cb = wp[2]] * SCALE12;
208            t3 = ToLinearF[ca = wp[3]] * SCALE12;
209            op[0] = CLAMP12(t0);
210            op[1] = CLAMP12(t1);
211            op[2] = CLAMP12(t2);
212            op[3] = CLAMP12(t3);
213            n -= 4;
214            while (n > 0) {
215                wp += 4;
216                op += 4;
217                n -= 4;
218                t0 = ToLinearF[(cr += wp[0]) & mask] * SCALE12;
219                t1 = ToLinearF[(cg += wp[1]) & mask] * SCALE12;
220                t2 = ToLinearF[(cb += wp[2]) & mask] * SCALE12;
221                t3 = ToLinearF[(ca += wp[3]) & mask] * SCALE12;
222                op[0] = CLAMP12(t0);
223                op[1] = CLAMP12(t1);
224                op[2] = CLAMP12(t2);
225                op[3] = CLAMP12(t3);
226            }
227        } else {
228            REPEAT(stride, t0 = ToLinearF[*wp&mask] * SCALE12;
229                           *op = CLAMP12(t0); wp++; op++)
230            n -= stride;
231            while (n > 0) {
232                REPEAT(stride,
233                    wp[stride] += *wp; t0 = ToLinearF[wp[stride]&mask]*SCALE12;
234                    *op = CLAMP12(t0);  wp++; op++)
235                n -= stride;
236            }
237        }
238    }
239}
240
241static void
242horizontalAccumulate16(uint16 *wp, int n, int stride, uint16 *op,
243        uint16 *ToLinear16)
244{
245    register unsigned int  cr, cg, cb, ca, mask;
246
247    if (n >= stride) {
248        mask = CODE_MASK;
249        if (stride == 3) {
250            op[0] = ToLinear16[cr = wp[0]];
251            op[1] = ToLinear16[cg = wp[1]];
252            op[2] = ToLinear16[cb = wp[2]];
253            n -= 3;
254            while (n > 0) {
255                wp += 3;
256                op += 3;
257                n -= 3;
258                op[0] = ToLinear16[(cr += wp[0]) & mask];
259                op[1] = ToLinear16[(cg += wp[1]) & mask];
260                op[2] = ToLinear16[(cb += wp[2]) & mask];
261            }
262        } else if (stride == 4) {
263            op[0] = ToLinear16[cr = wp[0]];
264            op[1] = ToLinear16[cg = wp[1]];
265            op[2] = ToLinear16[cb = wp[2]];
266            op[3] = ToLinear16[ca = wp[3]];
267            n -= 4;
268            while (n > 0) {
269                wp += 4;
270                op += 4;
271                n -= 4;
272                op[0] = ToLinear16[(cr += wp[0]) & mask];
273                op[1] = ToLinear16[(cg += wp[1]) & mask];
274                op[2] = ToLinear16[(cb += wp[2]) & mask];
275                op[3] = ToLinear16[(ca += wp[3]) & mask];
276            }
277        } else {
278            REPEAT(stride, *op = ToLinear16[*wp&mask]; wp++; op++)
279            n -= stride;
280            while (n > 0) {
281                REPEAT(stride,
282                    wp[stride] += *wp; *op = ToLinear16[*wp&mask]; wp++; op++)
283                n -= stride;
284            }
285        }
286    }
287}
288
289/*
290 * Returns the log encoded 11-bit values with the horizontal
291 * differencing undone.
292 */
293static void
294horizontalAccumulate11(uint16 *wp, int n, int stride, uint16 *op)
295{
296    register unsigned int  cr, cg, cb, ca, mask;
297
298    if (n >= stride) {
299        mask = CODE_MASK;
300        if (stride == 3) {
301            op[0] = cr = wp[0];  op[1] = cg = wp[1];  op[2] = cb = wp[2];
302            n -= 3;
303            while (n > 0) {
304                wp += 3;
305                op += 3;
306                n -= 3;
307                op[0] = (cr += wp[0]) & mask;
308                op[1] = (cg += wp[1]) & mask;
309                op[2] = (cb += wp[2]) & mask;
310            }
311        } else if (stride == 4) {
312            op[0] = cr = wp[0];  op[1] = cg = wp[1];
313            op[2] = cb = wp[2];  op[3] = ca = wp[3];
314            n -= 4;
315            while (n > 0) {
316                wp += 4;
317                op += 4;
318                n -= 4;
319                op[0] = (cr += wp[0]) & mask;
320                op[1] = (cg += wp[1]) & mask;
321                op[2] = (cb += wp[2]) & mask;
322                op[3] = (ca += wp[3]) & mask;
323            }
324        } else {
325            REPEAT(stride, *op = *wp&mask; wp++; op++)
326            n -= stride;
327            while (n > 0) {
328                REPEAT(stride,
329                    wp[stride] += *wp; *op = *wp&mask; wp++; op++)
330                n -= stride;
331            }
332        }
333    }
334}
335
336static void
337horizontalAccumulate8(uint16 *wp, int n, int stride, unsigned char *op,
338        unsigned char *ToLinear8)
339{
340    register unsigned int  cr, cg, cb, ca, mask;
341
342    if (n >= stride) {
343        mask = CODE_MASK;
344        if (stride == 3) {
345            op[0] = ToLinear8[cr = wp[0]];
346            op[1] = ToLinear8[cg = wp[1]];
347            op[2] = ToLinear8[cb = wp[2]];
348            n -= 3;
349            while (n > 0) {
350                n -= 3;
351                wp += 3;
352                op += 3;
353                op[0] = ToLinear8[(cr += wp[0]) & mask];
354                op[1] = ToLinear8[(cg += wp[1]) & mask];
355                op[2] = ToLinear8[(cb += wp[2]) & mask];
356            }
357        } else if (stride == 4) {
358            op[0] = ToLinear8[cr = wp[0]];
359            op[1] = ToLinear8[cg = wp[1]];
360            op[2] = ToLinear8[cb = wp[2]];
361            op[3] = ToLinear8[ca = wp[3]];
362            n -= 4;
363            while (n > 0) {
364                n -= 4;
365                wp += 4;
366                op += 4;
367                op[0] = ToLinear8[(cr += wp[0]) & mask];
368                op[1] = ToLinear8[(cg += wp[1]) & mask];
369                op[2] = ToLinear8[(cb += wp[2]) & mask];
370                op[3] = ToLinear8[(ca += wp[3]) & mask];
371            }
372        } else {
373            REPEAT(stride, *op = ToLinear8[*wp&mask]; wp++; op++)
374            n -= stride;
375            while (n > 0) {
376                REPEAT(stride,
377                    wp[stride] += *wp; *op = ToLinear8[*wp&mask]; wp++; op++)
378                n -= stride;
379            }
380        }
381    }
382}
383
384
385static void
386horizontalAccumulate8abgr(uint16 *wp, int n, int stride, unsigned char *op,
387        unsigned char *ToLinear8)
388{
389    register unsigned int  cr, cg, cb, ca, mask;
390    register unsigned char  t0, t1, t2, t3;
391
392    if (n >= stride) {
393        mask = CODE_MASK;
394        if (stride == 3) {
395            op[0] = 0;
396            t1 = ToLinear8[cb = wp[2]];
397            t2 = ToLinear8[cg = wp[1]];
398            t3 = ToLinear8[cr = wp[0]];
399            op[1] = t1;
400            op[2] = t2;
401            op[3] = t3;
402            n -= 3;
403            while (n > 0) {
404                n -= 3;
405                wp += 3;
406                op += 4;
407                op[0] = 0;
408                t1 = ToLinear8[(cb += wp[2]) & mask];
409                t2 = ToLinear8[(cg += wp[1]) & mask];
410                t3 = ToLinear8[(cr += wp[0]) & mask];
411                op[1] = t1;
412                op[2] = t2;
413                op[3] = t3;
414            }
415        } else if (stride == 4) {
416            t0 = ToLinear8[ca = wp[3]];
417            t1 = ToLinear8[cb = wp[2]];
418            t2 = ToLinear8[cg = wp[1]];
419            t3 = ToLinear8[cr = wp[0]];
420            op[0] = t0;
421            op[1] = t1;
422            op[2] = t2;
423            op[3] = t3;
424            n -= 4;
425            while (n > 0) {
426                n -= 4;
427                wp += 4;
428                op += 4;
429                t0 = ToLinear8[(ca += wp[3]) & mask];
430                t1 = ToLinear8[(cb += wp[2]) & mask];
431                t2 = ToLinear8[(cg += wp[1]) & mask];
432                t3 = ToLinear8[(cr += wp[0]) & mask];
433                op[0] = t0;
434                op[1] = t1;
435                op[2] = t2;
436                op[3] = t3;
437            }
438        } else {
439            REPEAT(stride, *op = ToLinear8[*wp&mask]; wp++; op++)
440            n -= stride;
441            while (n > 0) {
442                REPEAT(stride,
443                    wp[stride] += *wp; *op = ToLinear8[*wp&mask]; wp++; op++)
444                n -= stride;
445            }
446        }
447    }
448}
449
450/*
451 * State block for each open TIFF
452 * file using PixarLog compression/decompression.
453 */
454typedef struct {
455        TIFFPredictorState      predict;
456        z_stream                stream;
457        uint16                  *tbuf;
458        uint16                  stride;
459        int                     state;
460        int                     user_datafmt;
461        int                     quality;
462#define PLSTATE_INIT 1
463
464        TIFFVSetMethod          vgetparent;     /* super-class method */
465        TIFFVSetMethod          vsetparent;     /* super-class method */
466
467        float *ToLinearF;
468        uint16 *ToLinear16;
469        unsigned char *ToLinear8;
470        uint16  *FromLT2;
471        uint16  *From14; /* Really for 16-bit data, but we shift down 2 */
472        uint16  *From8;
473       
474} PixarLogState;
475
476static int
477PixarLogMakeTables(PixarLogState *sp)
478{
479
480/*
481 *    We make several tables here to convert between various external
482 *    representations (float, 16-bit, and 8-bit) and the internal
483 *    11-bit companded representation.  The 11-bit representation has two
484 *    distinct regions.  A linear bottom end up through .018316 in steps
485 *    of about .000073, and a region of constant ratio up to about 25.
486 *    These floating point numbers are stored in the main table ToLinearF.
487 *    All other tables are derived from this one.  The tables (and the
488 *    ratios) are continuous at the internal seam.
489 */
490
491    int  nlin, lt2size;
492    int  i, j;
493    double  b, c, linstep, max;
494    double  k, v, dv, r, lr2, r2;
495    float *ToLinearF;
496    uint16 *ToLinear16;
497    unsigned char *ToLinear8;
498    uint16  *FromLT2;
499    uint16  *From14; /* Really for 16-bit data, but we shift down 2 */
500    uint16  *From8;
501
502    c = log(RATIO);     
503    nlin = 1./c;        /* nlin must be an integer */
504    c = 1./nlin;
505    b = exp(-c*ONE);    /* multiplicative scale factor [b*exp(c*ONE) = 1] */
506    linstep = b*c*exp(1.);
507
508    LogK1 = 1./c;       /* if (v >= 2)  token = k1*log(v*k2) */
509    LogK2 = 1./b;
510    lt2size = (2./linstep)+1;
511    FromLT2 = (uint16 *)_TIFFmalloc(lt2size*sizeof(uint16));
512    From14 = (uint16 *)_TIFFmalloc(16384*sizeof(uint16));
513    From8 = (uint16 *)_TIFFmalloc(256*sizeof(uint16));
514    ToLinearF = (float *)_TIFFmalloc(TSIZEP1 * sizeof(float));
515    ToLinear16 = (uint16 *)_TIFFmalloc(TSIZEP1 * sizeof(uint16));
516    ToLinear8 = (unsigned char *)_TIFFmalloc(TSIZEP1 * sizeof(unsigned char));
517    if (FromLT2 == NULL || From14  == NULL || From8   == NULL ||
518         ToLinearF == NULL || ToLinear16 == NULL || ToLinear8 == NULL) {
519        if (FromLT2) _TIFFfree(FromLT2);
520        if (From14) _TIFFfree(From14);
521        if (From8) _TIFFfree(From8);
522        if (ToLinearF) _TIFFfree(ToLinearF);
523        if (ToLinear16) _TIFFfree(ToLinear16);
524        if (ToLinear8) _TIFFfree(ToLinear8);
525        sp->FromLT2 = NULL;
526        sp->From14 = NULL;
527        sp->From8 = NULL;
528        sp->ToLinearF = NULL;
529        sp->ToLinear16 = NULL;
530        sp->ToLinear8 = NULL;
531        return 0;
532    }
533
534    j = 0;
535
536    for (i = 0; i < nlin; i++)  {
537        v = i * linstep;
538        ToLinearF[j++] = v;
539    }
540
541    for (i = nlin; i < TSIZE; i++)
542        ToLinearF[j++] = b*exp(c*i);
543
544    ToLinearF[2048] = ToLinearF[2047];
545
546    for (i = 0; i < TSIZEP1; i++)  {
547        v = ToLinearF[i]*65535.0 + 0.5;
548        ToLinear16[i] = (v > 65535.0) ? 65535 : v;
549        v = ToLinearF[i]*255.0  + 0.5;
550        ToLinear8[i]  = (v > 255.0) ? 255 : v;
551    }
552
553    j = 0;
554    for (i = 0; i < lt2size; i++)  {
555        if ((i*linstep)*(i*linstep) > ToLinearF[j]*ToLinearF[j+1])
556            j++;
557        FromLT2[i] = j;
558    }
559
560    /*
561     * Since we lose info anyway on 16-bit data, we set up a 14-bit
562     * table and shift 16-bit values down two bits on input.
563     * saves a little table space.
564     */
565    j = 0;
566    for (i = 0; i < 16384; i++)  {
567        while ((i/16383.)*(i/16383.) > ToLinearF[j]*ToLinearF[j+1])
568            j++;
569        From14[i] = j;
570    }
571
572    j = 0;
573    for (i = 0; i < 256; i++)  {
574        while ((i/255.)*(i/255.) > ToLinearF[j]*ToLinearF[j+1])
575            j++;
576        From8[i] = j;
577    }
578
579    Fltsize = lt2size/2;
580
581    sp->ToLinearF = ToLinearF;
582    sp->ToLinear16 = ToLinear16;
583    sp->ToLinear8 = ToLinear8;
584    sp->FromLT2 = FromLT2;
585    sp->From14 = From14;
586    sp->From8 = From8;
587
588    return 1;
589}
590
591#define DecoderState(tif)       ((PixarLogState*) (tif)->tif_data)
592#define EncoderState(tif)       ((PixarLogState*) (tif)->tif_data)
593
594static  int PixarLogEncode(TIFF*, tidata_t, tsize_t, tsample_t);
595static  int PixarLogDecode(TIFF*, tidata_t, tsize_t, tsample_t);
596
597#define N(a)   (sizeof(a)/sizeof(a[0]))
598#define PIXARLOGDATAFMT_UNKNOWN -1
599
600static int
601PixarLogGuessDataFmt(TIFFDirectory *td)
602{
603        int guess = PIXARLOGDATAFMT_UNKNOWN;
604        int format = td->td_sampleformat;
605
606        /* If the user didn't tell us his datafmt,
607         * take our best guess from the bitspersample.
608         */
609        switch (td->td_bitspersample) {
610         case 32:
611                if (format == SAMPLEFORMAT_IEEEFP)
612                        guess = PIXARLOGDATAFMT_FLOAT;
613                break;
614         case 16:
615                if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT)
616                        guess = PIXARLOGDATAFMT_16BIT;
617                break;
618         case 12:
619                if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_INT)
620                        guess = PIXARLOGDATAFMT_12BITPICIO;
621                break;
622         case 11:
623                if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT)
624                        guess = PIXARLOGDATAFMT_11BITLOG;
625                break;
626         case 8:
627                if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT)
628                        guess = PIXARLOGDATAFMT_8BIT;
629                break;
630        }
631
632        return guess;
633}
634
635static int
636PixarLogSetupDecode(TIFF* tif)
637{
638        TIFFDirectory *td = &tif->tif_dir;
639        PixarLogState* sp = DecoderState(tif);
640        static const char module[] = "PixarLogSetupDecode";
641
642        assert(sp != NULL);
643
644        /* Make sure no byte swapping happens on the data
645         * after decompression. */
646        tif->tif_postdecode = _TIFFNoPostDecode;
647
648        /* for some reason, we can't do this in TIFFInitPixarLog */
649
650        sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ?
651            td->td_samplesperpixel : 1);
652        sp->tbuf = (uint16 *) _TIFFmalloc(sp->stride *
653                td->td_imagewidth * td->td_rowsperstrip * sizeof(uint16));
654        if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN)
655                sp->user_datafmt = PixarLogGuessDataFmt(td);
656        if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) {
657                TIFFError(module,
658                        "PixarLog compression can't handle bits depth/data format combination (depth: %d)",
659                        td->td_bitspersample);
660                return (0);
661        }
662
663        if (inflateInit(&sp->stream) != Z_OK) {
664                TIFFError(module, "%s: %s", tif->tif_name, sp->stream.msg);
665                return (0);
666        } else {
667                sp->state |= PLSTATE_INIT;
668                return (1);
669        }
670}
671
672/*
673 * Setup state for decoding a strip.
674 */
675static int
676PixarLogPreDecode(TIFF* tif, tsample_t s)
677{
678        TIFFDirectory *td = &tif->tif_dir;
679        PixarLogState* sp = DecoderState(tif);
680
681        (void) s;
682        assert(sp != NULL);
683        sp->stream.next_in = tif->tif_rawdata;
684        sp->stream.avail_in = tif->tif_rawcc;
685        return (inflateReset(&sp->stream) == Z_OK);
686}
687
688static int
689PixarLogDecode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
690{
691        TIFFDirectory *td = &tif->tif_dir;
692        PixarLogState* sp = DecoderState(tif);
693        static const char module[] = "PixarLogDecode";
694        int i, nsamples, llen;
695        uint16 *up;
696
697        switch (sp->user_datafmt) {
698        case PIXARLOGDATAFMT_FLOAT:
699                nsamples = occ / sizeof(float); /* XXX float == 32 bits */
700                break;
701        case PIXARLOGDATAFMT_16BIT:
702        case PIXARLOGDATAFMT_12BITPICIO:
703        case PIXARLOGDATAFMT_11BITLOG:
704                nsamples = occ / sizeof(uint16); /* XXX uint16 == 16 bits */
705                break;
706        case PIXARLOGDATAFMT_8BIT:
707        case PIXARLOGDATAFMT_8BITABGR:
708                nsamples = occ;
709                break;
710        default:
711                TIFFError(tif->tif_name,
712                        "%d bit input not supported in PixarLog",
713                        td->td_bitspersample);
714                return 0;
715        }
716
717        llen = sp->stride * td->td_imagewidth;
718
719        (void) s;
720        assert(sp != NULL);
721        sp->stream.next_out = (unsigned char *) sp->tbuf;
722        sp->stream.avail_out = nsamples * sizeof(uint16);
723        do {
724                int state = inflate(&sp->stream, Z_PARTIAL_FLUSH);
725                if (state == Z_STREAM_END) {
726                        break;                  /* XXX */
727                }
728                if (state == Z_DATA_ERROR) {
729                        TIFFError(module,
730                            "%s: Decoding error at scanline %d, %s",
731                            tif->tif_name, tif->tif_row, sp->stream.msg);
732                        if (inflateSync(&sp->stream) != Z_OK)
733                                return (0);
734                        continue;
735                }
736                if (state != Z_OK) {
737                        TIFFError(module, "%s: zlib error: %s",
738                            tif->tif_name, sp->stream.msg);
739                        return (0);
740                }
741        } while (sp->stream.avail_out > 0);
742
743        /* hopefully, we got all the bytes we needed */
744        if (sp->stream.avail_out != 0) {
745                TIFFError(module,
746                    "%s: Not enough data at scanline %d (short %d bytes)",
747                    tif->tif_name, tif->tif_row, sp->stream.avail_out);
748                return (0);
749        }
750
751        up = sp->tbuf;
752        /* Swap bytes in the data if from a different endian machine. */
753        if (tif->tif_flags & TIFF_SWAB)
754                TIFFSwabArrayOfShort(up, nsamples);
755
756        for (i = 0; i < nsamples; i += llen, up += llen) {
757                switch (sp->user_datafmt)  {
758                case PIXARLOGDATAFMT_FLOAT:
759                        horizontalAccumulateF(up, llen, sp->stride,
760                                        (float *)op, sp->ToLinearF);
761                        op += llen * sizeof(float);
762                        break;
763                case PIXARLOGDATAFMT_16BIT:
764                        horizontalAccumulate16(up, llen, sp->stride,
765                                        (uint16 *)op, sp->ToLinear16);
766                        op += llen * sizeof(uint16);
767                        break;
768                case PIXARLOGDATAFMT_12BITPICIO:
769                        horizontalAccumulate12(up, llen, sp->stride,
770                                        (int16 *)op, sp->ToLinearF);
771                        op += llen * sizeof(int16);
772                        break;
773                case PIXARLOGDATAFMT_11BITLOG:
774                        horizontalAccumulate11(up, llen, sp->stride,
775                                        (uint16 *)op);
776                        op += llen * sizeof(uint16);
777                        break;
778                case PIXARLOGDATAFMT_8BIT:
779                        horizontalAccumulate8(up, llen, sp->stride,
780                                        (unsigned char *)op, sp->ToLinear8);
781                        op += llen * sizeof(unsigned char);
782                        break;
783                case PIXARLOGDATAFMT_8BITABGR:
784                        horizontalAccumulate8abgr(up, llen, sp->stride,
785                                        (unsigned char *)op, sp->ToLinear8);
786                        op += llen * sizeof(unsigned char);
787                        break;
788                default:
789                        TIFFError(tif->tif_name,
790                                  "PixarLogDecode: unsupported bits/sample: %d",
791                                  td->td_bitspersample);
792                        return (0);
793                }
794        }
795
796        return (1);
797}
798
799static int
800PixarLogSetupEncode(TIFF* tif)
801{
802        TIFFDirectory *td = &tif->tif_dir;
803        PixarLogState* sp = EncoderState(tif);
804        static const char module[] = "PixarLogSetupEncode";
805
806        assert(sp != NULL);
807
808        /* for some reason, we can't do this in TIFFInitPixarLog */
809
810        sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ?
811            td->td_samplesperpixel : 1);
812        sp->tbuf = (uint16 *) _TIFFmalloc(sp->stride *
813                td->td_imagewidth * td->td_rowsperstrip * sizeof(uint16));
814        if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN)
815                sp->user_datafmt = PixarLogGuessDataFmt(td);
816        if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) {
817                TIFFError(module, "PixarLog compression can't handle %d bit linear encodings", td->td_bitspersample);
818                return (0);
819        }
820
821        if (deflateInit(&sp->stream, sp->quality) != Z_OK) {
822                TIFFError(module, "%s: %s", tif->tif_name, sp->stream.msg);
823                return (0);
824        } else {
825                sp->state |= PLSTATE_INIT;
826                return (1);
827        }
828}
829
830/*
831 * Reset encoding state at the start of a strip.
832 */
833static int
834PixarLogPreEncode(TIFF* tif, tsample_t s)
835{
836        TIFFDirectory *td = &tif->tif_dir;
837        PixarLogState *sp = EncoderState(tif);
838
839        (void) s;
840        assert(sp != NULL);
841        sp->stream.next_out = tif->tif_rawdata;
842        sp->stream.avail_out = tif->tif_rawdatasize;
843        return (deflateReset(&sp->stream) == Z_OK);
844}
845
846static void
847horizontalDifferenceF(float *ip, int n, int stride, uint16 *wp, uint16 *FromLT2)
848{
849
850    register int  r1, g1, b1, a1, r2, g2, b2, a2, mask;
851    register float  fltsize = Fltsize;
852
853#define  CLAMP(v) ( (v<(float)0.)   ? 0                         \
854                  : (v<(float)2.)   ? FromLT2[(int)(v*fltsize)] \
855                  : (v>(float)24.2) ? 2047                      \
856                  : LogK1*log(v*LogK2) + 0.5 )
857
858    mask = CODE_MASK;
859    if (n >= stride) {
860        if (stride == 3) {
861            r2 = wp[0] = CLAMP(ip[0]);  g2 = wp[1] = CLAMP(ip[1]);
862            b2 = wp[2] = CLAMP(ip[2]);
863            n -= 3;
864            while (n > 0) {
865                n -= 3;
866                wp += 3;
867                ip += 3;
868                r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1;
869                g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1;
870                b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1;
871            }
872        } else if (stride == 4) {
873            r2 = wp[0] = CLAMP(ip[0]);  g2 = wp[1] = CLAMP(ip[1]);
874            b2 = wp[2] = CLAMP(ip[2]);  a2 = wp[3] = CLAMP(ip[3]);
875            n -= 4;
876            while (n > 0) {
877                n -= 4;
878                wp += 4;
879                ip += 4;
880                r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1;
881                g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1;
882                b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1;
883                a1 = CLAMP(ip[3]); wp[3] = (a1-a2) & mask; a2 = a1;
884            }
885        } else {
886            ip += n - 1;        /* point to last one */
887            wp += n - 1;        /* point to last one */
888            n -= stride;
889            while (n > 0) {
890                REPEAT(stride, wp[0] = CLAMP(ip[0]);
891                                wp[stride] -= wp[0];
892                                wp[stride] &= mask;
893                                wp--; ip--)
894                n -= stride;
895            }
896            REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--)
897        }
898    }
899}
900
901static void
902horizontalDifference16(unsigned short *ip, int n, int stride,
903        unsigned short *wp, uint16 *From14)
904{
905    register int  r1, g1, b1, a1, r2, g2, b2, a2, mask;
906
907/* assumption is unsigned pixel values */
908#undef   CLAMP
909#define  CLAMP(v) From14[(v) >> 2]
910
911    mask = CODE_MASK;
912    if (n >= stride) {
913        if (stride == 3) {
914            r2 = wp[0] = CLAMP(ip[0]);  g2 = wp[1] = CLAMP(ip[1]);
915            b2 = wp[2] = CLAMP(ip[2]);
916            n -= 3;
917            while (n > 0) {
918                n -= 3;
919                wp += 3;
920                ip += 3;
921                r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1;
922                g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1;
923                b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1;
924            }
925        } else if (stride == 4) {
926            r2 = wp[0] = CLAMP(ip[0]);  g2 = wp[1] = CLAMP(ip[1]);
927            b2 = wp[2] = CLAMP(ip[2]);  a2 = wp[3] = CLAMP(ip[3]);
928            n -= 4;
929            while (n > 0) {
930                n -= 4;
931                wp += 4;
932                ip += 4;
933                r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1;
934                g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1;
935                b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1;
936                a1 = CLAMP(ip[3]); wp[3] = (a1-a2) & mask; a2 = a1;
937            }
938        } else {
939            ip += n - 1;        /* point to last one */
940            wp += n - 1;        /* point to last one */
941            n -= stride;
942            while (n > 0) {
943                REPEAT(stride, wp[0] = CLAMP(ip[0]);
944                                wp[stride] -= wp[0];
945                                wp[stride] &= mask;
946                                wp--; ip--)
947                n -= stride;
948            }
949            REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--)
950        }
951    }
952}
953
954
955static void
956horizontalDifference8(unsigned char *ip, int n, int stride,
957        unsigned short *wp, uint16 *From8)
958{
959    register int  r1, g1, b1, a1, r2, g2, b2, a2, mask;
960
961#undef   CLAMP
962#define  CLAMP(v) (From8[(v)])
963
964    mask = CODE_MASK;
965    if (n >= stride) {
966        if (stride == 3) {
967            r2 = wp[0] = CLAMP(ip[0]);  g2 = wp[1] = CLAMP(ip[1]);
968            b2 = wp[2] = CLAMP(ip[2]);
969            n -= 3;
970            while (n > 0) {
971                n -= 3;
972                r1 = CLAMP(ip[3]); wp[3] = (r1-r2) & mask; r2 = r1;
973                g1 = CLAMP(ip[4]); wp[4] = (g1-g2) & mask; g2 = g1;
974                b1 = CLAMP(ip[5]); wp[5] = (b1-b2) & mask; b2 = b1;
975                wp += 3;
976                ip += 3;
977            }
978        } else if (stride == 4) {
979            r2 = wp[0] = CLAMP(ip[0]);  g2 = wp[1] = CLAMP(ip[1]);
980            b2 = wp[2] = CLAMP(ip[2]);  a2 = wp[3] = CLAMP(ip[3]);
981            n -= 4;
982            while (n > 0) {
983                n -= 4;
984                r1 = CLAMP(ip[4]); wp[4] = (r1-r2) & mask; r2 = r1;
985                g1 = CLAMP(ip[5]); wp[5] = (g1-g2) & mask; g2 = g1;
986                b1 = CLAMP(ip[6]); wp[6] = (b1-b2) & mask; b2 = b1;
987                a1 = CLAMP(ip[7]); wp[7] = (a1-a2) & mask; a2 = a1;
988                wp += 4;
989                ip += 4;
990            }
991        } else {
992            wp += n + stride - 1;       /* point to last one */
993            ip += n + stride - 1;       /* point to last one */
994            n -= stride;
995            while (n > 0) {
996                REPEAT(stride, wp[0] = CLAMP(ip[0]);
997                                wp[stride] -= wp[0];
998                                wp[stride] &= mask;
999                                wp--; ip--)
1000                n -= stride;
1001            }
1002            REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--)
1003        }
1004    }
1005}
1006
1007/*
1008 * Encode a chunk of pixels.
1009 */
1010static int
1011PixarLogEncode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
1012{
1013        TIFFDirectory *td = &tif->tif_dir;
1014        PixarLogState *sp = EncoderState(tif);
1015        static const char module[] = "PixarLogEncode";
1016        int     i, n, llen;
1017        unsigned short * up;
1018
1019        (void) s;
1020
1021        switch (sp->user_datafmt) {
1022        case PIXARLOGDATAFMT_FLOAT:
1023                n = cc / sizeof(float);         /* XXX float == 32 bits */
1024                break;
1025        case PIXARLOGDATAFMT_16BIT:
1026        case PIXARLOGDATAFMT_12BITPICIO:
1027        case PIXARLOGDATAFMT_11BITLOG:
1028                n = cc / sizeof(uint16);        /* XXX uint16 == 16 bits */
1029                break;
1030        case PIXARLOGDATAFMT_8BIT:
1031        case PIXARLOGDATAFMT_8BITABGR:
1032                n = cc;
1033                break;
1034        default:
1035                TIFFError(tif->tif_name,
1036                        "%d bit input not supported in PixarLog",
1037                        td->td_bitspersample);
1038                return 0;
1039        }
1040
1041        llen = sp->stride * td->td_imagewidth;
1042
1043        for (i = 0, up = sp->tbuf; i < n; i += llen, up += llen) {
1044                switch (sp->user_datafmt)  {
1045                case PIXARLOGDATAFMT_FLOAT:
1046                        horizontalDifferenceF((float *)bp, llen,
1047                                sp->stride, up, sp->FromLT2);
1048                        bp += llen * sizeof(float);
1049                        break;
1050                case PIXARLOGDATAFMT_16BIT:
1051                        horizontalDifference16((uint16 *)bp, llen,
1052                                sp->stride, up, sp->From14);
1053                        bp += llen * sizeof(uint16);
1054                        break;
1055                case PIXARLOGDATAFMT_8BIT:
1056                        horizontalDifference8((unsigned char *)bp, llen,
1057                                sp->stride, up, sp->From8);
1058                        bp += llen * sizeof(unsigned char);
1059                        break;
1060                default:
1061                        TIFFError(tif->tif_name,
1062                                "%d bit input not supported in PixarLog",
1063                                td->td_bitspersample);
1064                        return 0;
1065                }
1066        }
1067 
1068        sp->stream.next_in = (unsigned char *) sp->tbuf;
1069        sp->stream.avail_in = n * sizeof(uint16);
1070
1071        do {
1072                if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) {
1073                        TIFFError(module, "%s: Encoder error: %s",
1074                            tif->tif_name, sp->stream.msg);
1075                        return (0);
1076                }
1077                if (sp->stream.avail_out == 0) {
1078                        tif->tif_rawcc = tif->tif_rawdatasize;
1079                        TIFFFlushData1(tif);
1080                        sp->stream.next_out = tif->tif_rawdata;
1081                        sp->stream.avail_out = tif->tif_rawdatasize;
1082                }
1083        } while (sp->stream.avail_in > 0);
1084        return (1);
1085}
1086
1087/*
1088 * Finish off an encoded strip by flushing the last
1089 * string and tacking on an End Of Information code.
1090 */
1091
1092static int
1093PixarLogPostEncode(TIFF* tif)
1094{
1095        PixarLogState *sp = EncoderState(tif);
1096        static const char module[] = "PixarLogPostEncode";
1097        int state;
1098
1099        sp->stream.avail_in = 0;
1100
1101        do {
1102                state = deflate(&sp->stream, Z_FINISH);
1103                switch (state) {
1104                case Z_STREAM_END:
1105                case Z_OK:
1106                    if (sp->stream.avail_out != tif->tif_rawdatasize) {
1107                            tif->tif_rawcc =
1108                                tif->tif_rawdatasize - sp->stream.avail_out;
1109                            TIFFFlushData1(tif);
1110                            sp->stream.next_out = tif->tif_rawdata;
1111                            sp->stream.avail_out = tif->tif_rawdatasize;
1112                    }
1113                    break;
1114                default:
1115                    TIFFError(module, "%s: zlib error: %s",
1116                        tif->tif_name, sp->stream.msg);
1117                    return (0);
1118                }
1119        } while (state != Z_STREAM_END);
1120        return (1);
1121}
1122
1123static void
1124PixarLogClose(TIFF* tif)
1125{
1126        TIFFDirectory *td = &tif->tif_dir;
1127
1128        /* In a really sneaky maneuver, on close, we covertly modify both
1129         * bitspersample and sampleformat in the directory to indicate
1130         * 8-bit linear.  This way, the decode "just works" even for
1131         * readers that don't know about PixarLog, or how to set
1132         * the PIXARLOGDATFMT pseudo-tag.
1133         */
1134        td->td_bitspersample = 8;
1135        td->td_sampleformat = SAMPLEFORMAT_UINT;
1136}
1137
1138static void
1139PixarLogCleanup(TIFF* tif)
1140{
1141        PixarLogState* sp = (PixarLogState*) tif->tif_data;
1142
1143        if (sp) {
1144                if (sp->FromLT2) _TIFFfree(sp->FromLT2);
1145                if (sp->From14) _TIFFfree(sp->From14);
1146                if (sp->From8) _TIFFfree(sp->From8);
1147                if (sp->ToLinearF) _TIFFfree(sp->ToLinearF);
1148                if (sp->ToLinear16) _TIFFfree(sp->ToLinear16);
1149                if (sp->ToLinear8) _TIFFfree(sp->ToLinear8);
1150                if (sp->state&PLSTATE_INIT) {
1151                        if (tif->tif_mode == O_RDONLY)
1152                                inflateEnd(&sp->stream);
1153                        else
1154                                deflateEnd(&sp->stream);
1155                }
1156                if (sp->tbuf)
1157                        _TIFFfree(sp->tbuf);
1158                _TIFFfree(sp);
1159                tif->tif_data = NULL;
1160        }
1161}
1162
1163static int
1164PixarLogVSetField(TIFF* tif, ttag_t tag, va_list ap)
1165{
1166    PixarLogState *sp = (PixarLogState *)tif->tif_data;
1167    int result;
1168    static const char module[] = "PixarLogVSetField";
1169
1170    switch (tag) {
1171     case TIFFTAG_PIXARLOGQUALITY:
1172                sp->quality = va_arg(ap, int);
1173                if (tif->tif_mode != O_RDONLY && (sp->state&PLSTATE_INIT)) {
1174                        if (deflateParams(&sp->stream,
1175                            sp->quality, Z_DEFAULT_STRATEGY) != Z_OK) {
1176                                TIFFError(module, "%s: zlib error: %s",
1177                                        tif->tif_name, sp->stream.msg);
1178                                return (0);
1179                        }
1180                }
1181                return (1);
1182     case TIFFTAG_PIXARLOGDATAFMT:
1183        sp->user_datafmt = va_arg(ap, int);
1184        /* Tweak the TIFF header so that the rest of libtiff knows what
1185         * size of data will be passed between app and library, and
1186         * assume that the app knows what it is doing and is not
1187         * confused by these header manipulations...
1188         */
1189        switch (sp->user_datafmt) {
1190         case PIXARLOGDATAFMT_8BIT:
1191         case PIXARLOGDATAFMT_8BITABGR:
1192            TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
1193            TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
1194            break;
1195         case PIXARLOGDATAFMT_11BITLOG:
1196            TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
1197            TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
1198            break;
1199         case PIXARLOGDATAFMT_12BITPICIO:
1200            TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
1201            TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT);
1202            break;
1203         case PIXARLOGDATAFMT_16BIT:
1204            TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
1205            TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
1206            break;
1207         case PIXARLOGDATAFMT_FLOAT:
1208            TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32);
1209            TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
1210            break;
1211        }
1212        /*
1213         * Must recalculate sizes should bits/sample change.
1214         */
1215        tif->tif_tilesize = TIFFTileSize(tif);
1216        tif->tif_scanlinesize = TIFFScanlineSize(tif);
1217        result = 1;             /* NB: pseudo tag */
1218        break;
1219     default:
1220        result = (*sp->vsetparent)(tif, tag, ap);
1221    }
1222    return (result);
1223}
1224
1225static int
1226PixarLogVGetField(TIFF* tif, ttag_t tag, va_list ap)
1227{
1228    PixarLogState *sp = (PixarLogState *)tif->tif_data;
1229
1230    switch (tag) {
1231     case TIFFTAG_PIXARLOGQUALITY:
1232        *va_arg(ap, int*) = sp->quality;
1233        break;
1234     case TIFFTAG_PIXARLOGDATAFMT:
1235        *va_arg(ap, int*) = sp->user_datafmt;
1236        break;
1237     default:
1238        return (*sp->vgetparent)(tif, tag, ap);
1239    }
1240    return (1);
1241}
1242
1243static const TIFFFieldInfo pixarlogFieldInfo[] = {
1244    {TIFFTAG_PIXARLOGDATAFMT,0,0,TIFF_ANY,  FIELD_PSEUDO,FALSE,FALSE,""},
1245    {TIFFTAG_PIXARLOGQUALITY,0,0,TIFF_ANY,  FIELD_PSEUDO,FALSE,FALSE,""}
1246};
1247
1248int
1249TIFFInitPixarLog(TIFF* tif, int scheme)
1250{
1251        PixarLogState* sp;
1252
1253        assert(scheme == COMPRESSION_PIXARLOG);
1254
1255        /*
1256         * Allocate state block so tag methods have storage to record values.
1257         */
1258        tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (PixarLogState));
1259        if (tif->tif_data == NULL)
1260                goto bad;
1261        sp = (PixarLogState*) tif->tif_data;
1262        memset(sp, 0, sizeof (*sp));
1263        sp->stream.data_type = Z_BINARY;
1264        sp->user_datafmt = PIXARLOGDATAFMT_UNKNOWN;
1265
1266        /*
1267         * Install codec methods.
1268         */
1269        tif->tif_setupdecode = PixarLogSetupDecode;
1270        tif->tif_predecode = PixarLogPreDecode;
1271        tif->tif_decoderow = PixarLogDecode;
1272        tif->tif_decodestrip = PixarLogDecode;
1273        tif->tif_decodetile = PixarLogDecode;
1274        tif->tif_setupencode = PixarLogSetupEncode;
1275        tif->tif_preencode = PixarLogPreEncode;
1276        tif->tif_postencode = PixarLogPostEncode;
1277        tif->tif_encoderow = PixarLogEncode;
1278        tif->tif_encodestrip = PixarLogEncode;
1279        tif->tif_encodetile = PixarLogEncode;
1280        tif->tif_close = PixarLogClose;
1281        tif->tif_cleanup = PixarLogCleanup;
1282
1283        /* Override SetField so we can handle our private pseudo-tag */
1284        _TIFFMergeFieldInfo(tif, pixarlogFieldInfo, N(pixarlogFieldInfo));
1285        sp->vgetparent = tif->tif_vgetfield;
1286        tif->tif_vgetfield = PixarLogVGetField;   /* hook for codec tags */
1287        sp->vsetparent = tif->tif_vsetfield;
1288        tif->tif_vsetfield = PixarLogVSetField;   /* hook for codec tags */
1289
1290        /* Default values for codec-specific fields */
1291        sp->quality = Z_DEFAULT_COMPRESSION; /* default comp. level */
1292        sp->state = 0;
1293
1294        /* we don't wish to use the predictor,
1295         * the default is none, which predictor value 1
1296         */
1297        (void) TIFFPredictorInit(tif);
1298
1299        /*
1300         * build the companding tables
1301         */
1302        PixarLogMakeTables(sp);
1303
1304        return (1);
1305bad:
1306        TIFFError("TIFFInitPixarLog", "No space for PixarLog state block");
1307        return (0);
1308}
1309#endif /* PIXARLOG_SUPPORT */
Note: See TracBrowser for help on using the repository browser.