"Initial commit to Gerrit"
[profile/ivi/libtiff.git] / libtiff / tif_pixarlog.c
1 /* $Id: tif_pixarlog.c,v 1.15.2.4 2010-06-08 18:50:42 bfriesen Exp $ */
2
3 /*
4  * Copyright (c) 1996-1997 Sam Leffler
5  * Copyright (c) 1996 Pixar
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  * Pixar, 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 Pixar, 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 PIXAR, 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 #include "tiffiop.h"
28 #ifdef PIXARLOG_SUPPORT
29
30 /*
31  * TIFF Library.
32  * PixarLog Compression Support
33  *
34  * Contributed by Dan McCoy.
35  *
36  * PixarLog film support uses the TIFF library to store companded
37  * 11 bit values into a tiff file, which are compressed using the 
38  * zip compressor.  
39  *
40  * The codec can take as input and produce as output 32-bit IEEE float values 
41  * as well as 16-bit or 8-bit unsigned integer values.
42  *
43  * On writing any of the above are converted into the internal
44  * 11-bit log format.   In the case of  8 and 16 bit values, the
45  * input is assumed to be unsigned linear color values that represent
46  * the range 0-1.  In the case of IEEE values, the 0-1 range is assumed to
47  * be the normal linear color range, in addition over 1 values are
48  * accepted up to a value of about 25.0 to encode "hot" hightlights and such.
49  * The encoding is lossless for 8-bit values, slightly lossy for the
50  * other bit depths.  The actual color precision should be better
51  * than the human eye can perceive with extra room to allow for
52  * error introduced by further image computation.  As with any quantized
53  * color format, it is possible to perform image calculations which
54  * expose the quantization error. This format should certainly be less 
55  * susceptable to such errors than standard 8-bit encodings, but more
56  * susceptable than straight 16-bit or 32-bit encodings.
57  *
58  * On reading the internal format is converted to the desired output format.
59  * The program can request which format it desires by setting the internal
60  * pseudo tag TIFFTAG_PIXARLOGDATAFMT to one of these possible values:
61  *  PIXARLOGDATAFMT_FLOAT     = provide IEEE float values.
62  *  PIXARLOGDATAFMT_16BIT     = provide unsigned 16-bit integer values
63  *  PIXARLOGDATAFMT_8BIT      = provide unsigned 8-bit integer values
64  *
65  * alternately PIXARLOGDATAFMT_8BITABGR provides unsigned 8-bit integer
66  * values with the difference that if there are exactly three or four channels
67  * (rgb or rgba) it swaps the channel order (bgr or abgr).
68  *
69  * PIXARLOGDATAFMT_11BITLOG provides the internal encoding directly
70  * packed in 16-bit values.   However no tools are supplied for interpreting
71  * these values.
72  *
73  * "hot" (over 1.0) areas written in floating point get clamped to
74  * 1.0 in the integer data types.
75  *
76  * When the file is closed after writing, the bit depth and sample format
77  * are set always to appear as if 8-bit data has been written into it.
78  * That way a naive program unaware of the particulars of the encoding
79  * gets the format it is most likely able to handle.
80  *
81  * The codec does it's own horizontal differencing step on the coded
82  * values so the libraries predictor stuff should be turned off.
83  * The codec also handle byte swapping the encoded values as necessary
84  * since the library does not have the information necessary
85  * to know the bit depth of the raw unencoded buffer.
86  * 
87  */
88
89 #include "tif_predict.h"
90 #include "zlib.h"
91
92 #include <stdio.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
105 static float  Fltsize;
106 static float  LogK1, LogK2;
107
108 #define REPEAT(n, op)   { int i; i=n; do { i--; op; } while (i>0); }
109
110 static void
111 horizontalAccumulateF(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
173 static void
174 horizontalAccumulate12(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.0F
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
241 static void
242 horizontalAccumulate16(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  */
293 static void
294 horizontalAccumulate11(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
336 static void
337 horizontalAccumulate8(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
385 static void
386 horizontalAccumulate8abgr(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  */
454 typedef 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
476 static int
477 PixarLogMakeTables(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, v;
494     float *ToLinearF;
495     uint16 *ToLinear16;
496     unsigned char *ToLinear8;
497     uint16  *FromLT2;
498     uint16  *From14; /* Really for 16-bit data, but we shift down 2 */
499     uint16  *From8;
500
501     c = log(RATIO);     
502     nlin = (int)(1./c); /* nlin must be an integer */
503     c = 1./nlin;
504     b = exp(-c*ONE);    /* multiplicative scale factor [b*exp(c*ONE) = 1] */
505     linstep = b*c*exp(1.);
506
507     LogK1 = (float)(1./c);      /* if (v >= 2)  token = k1*log(v*k2) */
508     LogK2 = (float)(1./b);
509     lt2size = (int)(2./linstep) + 1;
510     FromLT2 = (uint16 *)_TIFFmalloc(lt2size*sizeof(uint16));
511     From14 = (uint16 *)_TIFFmalloc(16384*sizeof(uint16));
512     From8 = (uint16 *)_TIFFmalloc(256*sizeof(uint16));
513     ToLinearF = (float *)_TIFFmalloc(TSIZEP1 * sizeof(float));
514     ToLinear16 = (uint16 *)_TIFFmalloc(TSIZEP1 * sizeof(uint16));
515     ToLinear8 = (unsigned char *)_TIFFmalloc(TSIZEP1 * sizeof(unsigned char));
516     if (FromLT2 == NULL || From14  == NULL || From8   == NULL ||
517          ToLinearF == NULL || ToLinear16 == NULL || ToLinear8 == NULL) {
518         if (FromLT2) _TIFFfree(FromLT2);
519         if (From14) _TIFFfree(From14);
520         if (From8) _TIFFfree(From8);
521         if (ToLinearF) _TIFFfree(ToLinearF);
522         if (ToLinear16) _TIFFfree(ToLinear16);
523         if (ToLinear8) _TIFFfree(ToLinear8);
524         sp->FromLT2 = NULL;
525         sp->From14 = NULL;
526         sp->From8 = NULL;
527         sp->ToLinearF = NULL;
528         sp->ToLinear16 = NULL;
529         sp->ToLinear8 = NULL;
530         return 0;
531     }
532
533     j = 0;
534
535     for (i = 0; i < nlin; i++)  {
536         v = i * linstep;
537         ToLinearF[j++] = (float)v;
538     }
539
540     for (i = nlin; i < TSIZE; i++)
541         ToLinearF[j++] = (float)(b*exp(c*i));
542
543     ToLinearF[2048] = ToLinearF[2047];
544
545     for (i = 0; i < TSIZEP1; i++)  {
546         v = ToLinearF[i]*65535.0 + 0.5;
547         ToLinear16[i] = (v > 65535.0) ? 65535 : (uint16)v;
548         v = ToLinearF[i]*255.0  + 0.5;
549         ToLinear8[i]  = (v > 255.0) ? 255 : (unsigned char)v;
550     }
551
552     j = 0;
553     for (i = 0; i < lt2size; i++)  {
554         if ((i*linstep)*(i*linstep) > ToLinearF[j]*ToLinearF[j+1])
555             j++;
556         FromLT2[i] = j;
557     }
558
559     /*
560      * Since we lose info anyway on 16-bit data, we set up a 14-bit
561      * table and shift 16-bit values down two bits on input.
562      * saves a little table space.
563      */
564     j = 0;
565     for (i = 0; i < 16384; i++)  {
566         while ((i/16383.)*(i/16383.) > ToLinearF[j]*ToLinearF[j+1])
567             j++;
568         From14[i] = j;
569     }
570
571     j = 0;
572     for (i = 0; i < 256; i++)  {
573         while ((i/255.)*(i/255.) > ToLinearF[j]*ToLinearF[j+1])
574             j++;
575         From8[i] = j;
576     }
577
578     Fltsize = (float)(lt2size/2);
579
580     sp->ToLinearF = ToLinearF;
581     sp->ToLinear16 = ToLinear16;
582     sp->ToLinear8 = ToLinear8;
583     sp->FromLT2 = FromLT2;
584     sp->From14 = From14;
585     sp->From8 = From8;
586
587     return 1;
588 }
589
590 #define DecoderState(tif)       ((PixarLogState*) (tif)->tif_data)
591 #define EncoderState(tif)       ((PixarLogState*) (tif)->tif_data)
592
593 static  int PixarLogEncode(TIFF*, tidata_t, tsize_t, tsample_t);
594 static  int PixarLogDecode(TIFF*, tidata_t, tsize_t, tsample_t);
595
596 #define PIXARLOGDATAFMT_UNKNOWN -1
597
598 static int
599 PixarLogGuessDataFmt(TIFFDirectory *td)
600 {
601         int guess = PIXARLOGDATAFMT_UNKNOWN;
602         int format = td->td_sampleformat;
603
604         /* If the user didn't tell us his datafmt,
605          * take our best guess from the bitspersample.
606          */
607         switch (td->td_bitspersample) {
608          case 32:
609                 if (format == SAMPLEFORMAT_IEEEFP)
610                         guess = PIXARLOGDATAFMT_FLOAT;
611                 break;
612          case 16:
613                 if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT)
614                         guess = PIXARLOGDATAFMT_16BIT;
615                 break;
616          case 12:
617                 if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_INT)
618                         guess = PIXARLOGDATAFMT_12BITPICIO;
619                 break;
620          case 11:
621                 if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT)
622                         guess = PIXARLOGDATAFMT_11BITLOG;
623                 break;
624          case 8:
625                 if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT)
626                         guess = PIXARLOGDATAFMT_8BIT;
627                 break;
628         }
629
630         return guess;
631 }
632
633 static uint32
634 multiply(size_t m1, size_t m2)
635 {
636         uint32  bytes = m1 * m2;
637
638         if (m1 && bytes / m1 != m2)
639                 bytes = 0;
640
641         return bytes;
642 }
643
644 static int
645 PixarLogSetupDecode(TIFF* tif)
646 {
647         TIFFDirectory *td = &tif->tif_dir;
648         PixarLogState* sp = DecoderState(tif);
649         tsize_t tbuf_size;
650         static const char module[] = "PixarLogSetupDecode";
651
652         assert(sp != NULL);
653
654         /* Make sure no byte swapping happens on the data
655          * after decompression. */
656         tif->tif_postdecode = _TIFFNoPostDecode;
657
658         /* for some reason, we can't do this in TIFFInitPixarLog */
659
660         sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ?
661             td->td_samplesperpixel : 1);
662         tbuf_size = multiply(multiply(multiply(sp->stride, td->td_imagewidth),
663                                       td->td_rowsperstrip), sizeof(uint16));
664         if (tbuf_size == 0)
665                 return (0);
666         sp->tbuf = (uint16 *) _TIFFmalloc(tbuf_size);
667         if (sp->tbuf == NULL)
668                 return (0);
669         if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN)
670                 sp->user_datafmt = PixarLogGuessDataFmt(td);
671         if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) {
672                 TIFFErrorExt(tif->tif_clientdata, module,
673                         "PixarLog compression can't handle bits depth/data format combination (depth: %d)", 
674                         td->td_bitspersample);
675                 return (0);
676         }
677
678         if (inflateInit(&sp->stream) != Z_OK) {
679                 TIFFErrorExt(tif->tif_clientdata, module, "%s: %s", tif->tif_name, sp->stream.msg);
680                 return (0);
681         } else {
682                 sp->state |= PLSTATE_INIT;
683                 return (1);
684         }
685 }
686
687 /*
688  * Setup state for decoding a strip.
689  */
690 static int
691 PixarLogPreDecode(TIFF* tif, tsample_t s)
692 {
693         PixarLogState* sp = DecoderState(tif);
694
695         (void) s;
696         assert(sp != NULL);
697         sp->stream.next_in = tif->tif_rawdata;
698         sp->stream.avail_in = tif->tif_rawcc;
699         return (inflateReset(&sp->stream) == Z_OK);
700 }
701
702 static int
703 PixarLogDecode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
704 {
705         TIFFDirectory *td = &tif->tif_dir;
706         PixarLogState* sp = DecoderState(tif);
707         static const char module[] = "PixarLogDecode";
708         int i, nsamples, llen;
709         uint16 *up;
710
711         switch (sp->user_datafmt) {
712         case PIXARLOGDATAFMT_FLOAT:
713                 nsamples = occ / sizeof(float); /* XXX float == 32 bits */
714                 break;
715         case PIXARLOGDATAFMT_16BIT:
716         case PIXARLOGDATAFMT_12BITPICIO:
717         case PIXARLOGDATAFMT_11BITLOG:
718                 nsamples = occ / sizeof(uint16); /* XXX uint16 == 16 bits */
719                 break;
720         case PIXARLOGDATAFMT_8BIT:
721         case PIXARLOGDATAFMT_8BITABGR:
722                 nsamples = occ;
723                 break;
724         default:
725                 TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
726                         "%d bit input not supported in PixarLog",
727                         td->td_bitspersample);
728                 return 0;
729         }
730
731         llen = sp->stride * td->td_imagewidth;
732
733         (void) s;
734         assert(sp != NULL);
735         sp->stream.next_out = (unsigned char *) sp->tbuf;
736         sp->stream.avail_out = nsamples * sizeof(uint16);
737         do {
738                 int state = inflate(&sp->stream, Z_PARTIAL_FLUSH);
739                 if (state == Z_STREAM_END) {
740                         break;                  /* XXX */
741                 }
742                 if (state == Z_DATA_ERROR) {
743                         TIFFErrorExt(tif->tif_clientdata, module,
744                             "%s: Decoding error at scanline %d, %s",
745                             tif->tif_name, tif->tif_row, sp->stream.msg);
746                         if (inflateSync(&sp->stream) != Z_OK)
747                                 return (0);
748                         continue;
749                 }
750                 if (state != Z_OK) {
751                         TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s",
752                             tif->tif_name, sp->stream.msg);
753                         return (0);
754                 }
755         } while (sp->stream.avail_out > 0);
756
757         /* hopefully, we got all the bytes we needed */
758         if (sp->stream.avail_out != 0) {
759                 TIFFErrorExt(tif->tif_clientdata, module,
760                     "%s: Not enough data at scanline %d (short %d bytes)",
761                     tif->tif_name, tif->tif_row, sp->stream.avail_out);
762                 return (0);
763         }
764
765         up = sp->tbuf;
766         /* Swap bytes in the data if from a different endian machine. */
767         if (tif->tif_flags & TIFF_SWAB)
768                 TIFFSwabArrayOfShort(up, nsamples);
769
770         /* 
771          * if llen is not an exact multiple of nsamples, the decode operation
772          * may overflow the output buffer, so truncate it enough to prevent
773          * that but still salvage as much data as possible.
774          */
775         if (nsamples % llen) { 
776                 TIFFWarningExt(tif->tif_clientdata, module,
777                         "%s: stride %d is not a multiple of sample count, "
778                         "%d, data truncated.", tif->tif_name, llen, nsamples);
779                 nsamples -= nsamples % llen;
780         }
781
782         for (i = 0; i < nsamples; i += llen, up += llen) {
783                 switch (sp->user_datafmt)  {
784                 case PIXARLOGDATAFMT_FLOAT:
785                         horizontalAccumulateF(up, llen, sp->stride,
786                                         (float *)op, sp->ToLinearF);
787                         op += llen * sizeof(float);
788                         break;
789                 case PIXARLOGDATAFMT_16BIT:
790                         horizontalAccumulate16(up, llen, sp->stride,
791                                         (uint16 *)op, sp->ToLinear16);
792                         op += llen * sizeof(uint16);
793                         break;
794                 case PIXARLOGDATAFMT_12BITPICIO:
795                         horizontalAccumulate12(up, llen, sp->stride,
796                                         (int16 *)op, sp->ToLinearF);
797                         op += llen * sizeof(int16);
798                         break;
799                 case PIXARLOGDATAFMT_11BITLOG:
800                         horizontalAccumulate11(up, llen, sp->stride,
801                                         (uint16 *)op);
802                         op += llen * sizeof(uint16);
803                         break;
804                 case PIXARLOGDATAFMT_8BIT:
805                         horizontalAccumulate8(up, llen, sp->stride,
806                                         (unsigned char *)op, sp->ToLinear8);
807                         op += llen * sizeof(unsigned char);
808                         break;
809                 case PIXARLOGDATAFMT_8BITABGR:
810                         horizontalAccumulate8abgr(up, llen, sp->stride,
811                                         (unsigned char *)op, sp->ToLinear8);
812                         op += llen * sizeof(unsigned char);
813                         break;
814                 default:
815                         TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
816                                   "PixarLogDecode: unsupported bits/sample: %d", 
817                                   td->td_bitspersample);
818                         return (0);
819                 }
820         }
821
822         return (1);
823 }
824
825 static int
826 PixarLogSetupEncode(TIFF* tif)
827 {
828         TIFFDirectory *td = &tif->tif_dir;
829         PixarLogState* sp = EncoderState(tif);
830         tsize_t tbuf_size;
831         static const char module[] = "PixarLogSetupEncode";
832
833         assert(sp != NULL);
834
835         /* for some reason, we can't do this in TIFFInitPixarLog */
836
837         sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ?
838             td->td_samplesperpixel : 1);
839         tbuf_size = multiply(multiply(multiply(sp->stride, td->td_imagewidth),
840                                       td->td_rowsperstrip), sizeof(uint16));
841         if (tbuf_size == 0)
842                 return (0);
843         sp->tbuf = (uint16 *) _TIFFmalloc(tbuf_size);
844         if (sp->tbuf == NULL)
845                 return (0);
846         if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN)
847                 sp->user_datafmt = PixarLogGuessDataFmt(td);
848         if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) {
849                 TIFFErrorExt(tif->tif_clientdata, module, "PixarLog compression can't handle %d bit linear encodings", td->td_bitspersample);
850                 return (0);
851         }
852
853         if (deflateInit(&sp->stream, sp->quality) != Z_OK) {
854                 TIFFErrorExt(tif->tif_clientdata, module, "%s: %s", tif->tif_name, sp->stream.msg);
855                 return (0);
856         } else {
857                 sp->state |= PLSTATE_INIT;
858                 return (1);
859         }
860 }
861
862 /*
863  * Reset encoding state at the start of a strip.
864  */
865 static int
866 PixarLogPreEncode(TIFF* tif, tsample_t s)
867 {
868         PixarLogState *sp = EncoderState(tif);
869
870         (void) s;
871         assert(sp != NULL);
872         sp->stream.next_out = tif->tif_rawdata;
873         sp->stream.avail_out = tif->tif_rawdatasize;
874         return (deflateReset(&sp->stream) == Z_OK);
875 }
876
877 static void
878 horizontalDifferenceF(float *ip, int n, int stride, uint16 *wp, uint16 *FromLT2)
879 {
880
881     int32 r1, g1, b1, a1, r2, g2, b2, a2, mask;
882     float fltsize = Fltsize;
883
884 #define  CLAMP(v) ( (v<(float)0.)   ? 0                         \
885                   : (v<(float)2.)   ? FromLT2[(int)(v*fltsize)] \
886                   : (v>(float)24.2) ? 2047                      \
887                   : LogK1*log(v*LogK2) + 0.5 )
888
889     mask = CODE_MASK;
890     if (n >= stride) {
891         if (stride == 3) {
892             r2 = wp[0] = (uint16) CLAMP(ip[0]);
893             g2 = wp[1] = (uint16) CLAMP(ip[1]);
894             b2 = wp[2] = (uint16) CLAMP(ip[2]);
895             n -= 3;
896             while (n > 0) {
897                 n -= 3;
898                 wp += 3;
899                 ip += 3;
900                 r1 = (int32) CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1;
901                 g1 = (int32) CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1;
902                 b1 = (int32) CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1;
903             }
904         } else if (stride == 4) {
905             r2 = wp[0] = (uint16) CLAMP(ip[0]);
906             g2 = wp[1] = (uint16) CLAMP(ip[1]);
907             b2 = wp[2] = (uint16) CLAMP(ip[2]);
908             a2 = wp[3] = (uint16) CLAMP(ip[3]);
909             n -= 4;
910             while (n > 0) {
911                 n -= 4;
912                 wp += 4;
913                 ip += 4;
914                 r1 = (int32) CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1;
915                 g1 = (int32) CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1;
916                 b1 = (int32) CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1;
917                 a1 = (int32) CLAMP(ip[3]); wp[3] = (a1-a2) & mask; a2 = a1;
918             }
919         } else {
920             ip += n - 1;        /* point to last one */
921             wp += n - 1;        /* point to last one */
922             n -= stride;
923             while (n > 0) {
924                 REPEAT(stride, wp[0] = (uint16) CLAMP(ip[0]);
925                                 wp[stride] -= wp[0];
926                                 wp[stride] &= mask;
927                                 wp--; ip--)
928                 n -= stride;
929             }
930             REPEAT(stride, wp[0] = (uint16) CLAMP(ip[0]); wp--; ip--)
931         }
932     }
933 }
934
935 static void
936 horizontalDifference16(unsigned short *ip, int n, int stride, 
937         unsigned short *wp, uint16 *From14)
938 {
939     register int  r1, g1, b1, a1, r2, g2, b2, a2, mask;
940
941 /* assumption is unsigned pixel values */
942 #undef   CLAMP
943 #define  CLAMP(v) From14[(v) >> 2]
944
945     mask = CODE_MASK;
946     if (n >= stride) {
947         if (stride == 3) {
948             r2 = wp[0] = CLAMP(ip[0]);  g2 = wp[1] = CLAMP(ip[1]);
949             b2 = wp[2] = CLAMP(ip[2]);
950             n -= 3;
951             while (n > 0) {
952                 n -= 3;
953                 wp += 3;
954                 ip += 3;
955                 r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1;
956                 g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1;
957                 b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1;
958             }
959         } else if (stride == 4) {
960             r2 = wp[0] = CLAMP(ip[0]);  g2 = wp[1] = CLAMP(ip[1]);
961             b2 = wp[2] = CLAMP(ip[2]);  a2 = wp[3] = CLAMP(ip[3]);
962             n -= 4;
963             while (n > 0) {
964                 n -= 4;
965                 wp += 4;
966                 ip += 4;
967                 r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1;
968                 g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1;
969                 b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1;
970                 a1 = CLAMP(ip[3]); wp[3] = (a1-a2) & mask; a2 = a1;
971             }
972         } else {
973             ip += n - 1;        /* point to last one */
974             wp += n - 1;        /* point to last one */
975             n -= stride;
976             while (n > 0) {
977                 REPEAT(stride, wp[0] = CLAMP(ip[0]);
978                                 wp[stride] -= wp[0];
979                                 wp[stride] &= mask;
980                                 wp--; ip--)
981                 n -= stride;
982             }
983             REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--)
984         }
985     }
986 }
987
988
989 static void
990 horizontalDifference8(unsigned char *ip, int n, int stride, 
991         unsigned short *wp, uint16 *From8)
992 {
993     register int  r1, g1, b1, a1, r2, g2, b2, a2, mask;
994
995 #undef   CLAMP
996 #define  CLAMP(v) (From8[(v)])
997
998     mask = CODE_MASK;
999     if (n >= stride) {
1000         if (stride == 3) {
1001             r2 = wp[0] = CLAMP(ip[0]);  g2 = wp[1] = CLAMP(ip[1]);
1002             b2 = wp[2] = CLAMP(ip[2]);
1003             n -= 3;
1004             while (n > 0) {
1005                 n -= 3;
1006                 r1 = CLAMP(ip[3]); wp[3] = (r1-r2) & mask; r2 = r1;
1007                 g1 = CLAMP(ip[4]); wp[4] = (g1-g2) & mask; g2 = g1;
1008                 b1 = CLAMP(ip[5]); wp[5] = (b1-b2) & mask; b2 = b1;
1009                 wp += 3;
1010                 ip += 3;
1011             }
1012         } else if (stride == 4) {
1013             r2 = wp[0] = CLAMP(ip[0]);  g2 = wp[1] = CLAMP(ip[1]);
1014             b2 = wp[2] = CLAMP(ip[2]);  a2 = wp[3] = CLAMP(ip[3]);
1015             n -= 4;
1016             while (n > 0) {
1017                 n -= 4;
1018                 r1 = CLAMP(ip[4]); wp[4] = (r1-r2) & mask; r2 = r1;
1019                 g1 = CLAMP(ip[5]); wp[5] = (g1-g2) & mask; g2 = g1;
1020                 b1 = CLAMP(ip[6]); wp[6] = (b1-b2) & mask; b2 = b1;
1021                 a1 = CLAMP(ip[7]); wp[7] = (a1-a2) & mask; a2 = a1;
1022                 wp += 4;
1023                 ip += 4;
1024             }
1025         } else {
1026             wp += n + stride - 1;       /* point to last one */
1027             ip += n + stride - 1;       /* point to last one */
1028             n -= stride;
1029             while (n > 0) {
1030                 REPEAT(stride, wp[0] = CLAMP(ip[0]);
1031                                 wp[stride] -= wp[0];
1032                                 wp[stride] &= mask;
1033                                 wp--; ip--)
1034                 n -= stride;
1035             }
1036             REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--)
1037         }
1038     }
1039 }
1040
1041 /*
1042  * Encode a chunk of pixels.
1043  */
1044 static int
1045 PixarLogEncode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
1046 {
1047         TIFFDirectory *td = &tif->tif_dir;
1048         PixarLogState *sp = EncoderState(tif);
1049         static const char module[] = "PixarLogEncode";
1050         int     i, n, llen;
1051         unsigned short * up;
1052
1053         (void) s;
1054
1055         switch (sp->user_datafmt) {
1056         case PIXARLOGDATAFMT_FLOAT:
1057                 n = cc / sizeof(float);         /* XXX float == 32 bits */
1058                 break;
1059         case PIXARLOGDATAFMT_16BIT:
1060         case PIXARLOGDATAFMT_12BITPICIO:
1061         case PIXARLOGDATAFMT_11BITLOG:
1062                 n = cc / sizeof(uint16);        /* XXX uint16 == 16 bits */
1063                 break;
1064         case PIXARLOGDATAFMT_8BIT:
1065         case PIXARLOGDATAFMT_8BITABGR:
1066                 n = cc;
1067                 break;
1068         default:
1069                 TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
1070                         "%d bit input not supported in PixarLog",
1071                         td->td_bitspersample);
1072                 return 0;
1073         }
1074
1075         llen = sp->stride * td->td_imagewidth;
1076
1077         for (i = 0, up = sp->tbuf; i < n; i += llen, up += llen) {
1078                 switch (sp->user_datafmt)  {
1079                 case PIXARLOGDATAFMT_FLOAT:
1080                         horizontalDifferenceF((float *)bp, llen, 
1081                                 sp->stride, up, sp->FromLT2);
1082                         bp += llen * sizeof(float);
1083                         break;
1084                 case PIXARLOGDATAFMT_16BIT:
1085                         horizontalDifference16((uint16 *)bp, llen, 
1086                                 sp->stride, up, sp->From14);
1087                         bp += llen * sizeof(uint16);
1088                         break;
1089                 case PIXARLOGDATAFMT_8BIT:
1090                         horizontalDifference8((unsigned char *)bp, llen, 
1091                                 sp->stride, up, sp->From8);
1092                         bp += llen * sizeof(unsigned char);
1093                         break;
1094                 default:
1095                         TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
1096                                 "%d bit input not supported in PixarLog",
1097                                 td->td_bitspersample);
1098                         return 0;
1099                 }
1100         }
1101  
1102         sp->stream.next_in = (unsigned char *) sp->tbuf;
1103         sp->stream.avail_in = n * sizeof(uint16);
1104
1105         do {
1106                 if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) {
1107                         TIFFErrorExt(tif->tif_clientdata, module, "%s: Encoder error: %s",
1108                             tif->tif_name, sp->stream.msg);
1109                         return (0);
1110                 }
1111                 if (sp->stream.avail_out == 0) {
1112                         tif->tif_rawcc = tif->tif_rawdatasize;
1113                         TIFFFlushData1(tif);
1114                         sp->stream.next_out = tif->tif_rawdata;
1115                         sp->stream.avail_out = tif->tif_rawdatasize;
1116                 }
1117         } while (sp->stream.avail_in > 0);
1118         return (1);
1119 }
1120
1121 /*
1122  * Finish off an encoded strip by flushing the last
1123  * string and tacking on an End Of Information code.
1124  */
1125
1126 static int
1127 PixarLogPostEncode(TIFF* tif)
1128 {
1129         PixarLogState *sp = EncoderState(tif);
1130         static const char module[] = "PixarLogPostEncode";
1131         int state;
1132
1133         sp->stream.avail_in = 0;
1134
1135         do {
1136                 state = deflate(&sp->stream, Z_FINISH);
1137                 switch (state) {
1138                 case Z_STREAM_END:
1139                 case Z_OK:
1140                     if (sp->stream.avail_out != (uint32)tif->tif_rawdatasize) {
1141                             tif->tif_rawcc =
1142                                 tif->tif_rawdatasize - sp->stream.avail_out;
1143                             TIFFFlushData1(tif);
1144                             sp->stream.next_out = tif->tif_rawdata;
1145                             sp->stream.avail_out = tif->tif_rawdatasize;
1146                     }
1147                     break;
1148                 default:
1149                         TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s",
1150                         tif->tif_name, sp->stream.msg);
1151                     return (0);
1152                 }
1153         } while (state != Z_STREAM_END);
1154         return (1);
1155 }
1156
1157 static void
1158 PixarLogClose(TIFF* tif)
1159 {
1160         TIFFDirectory *td = &tif->tif_dir;
1161
1162         /* In a really sneaky maneuver, on close, we covertly modify both
1163          * bitspersample and sampleformat in the directory to indicate
1164          * 8-bit linear.  This way, the decode "just works" even for
1165          * readers that don't know about PixarLog, or how to set
1166          * the PIXARLOGDATFMT pseudo-tag.
1167          */
1168         td->td_bitspersample = 8;
1169         td->td_sampleformat = SAMPLEFORMAT_UINT;
1170 }
1171
1172 static void
1173 PixarLogCleanup(TIFF* tif)
1174 {
1175         PixarLogState* sp = (PixarLogState*) tif->tif_data;
1176
1177         assert(sp != 0);
1178
1179         (void)TIFFPredictorCleanup(tif);
1180
1181         tif->tif_tagmethods.vgetfield = sp->vgetparent;
1182         tif->tif_tagmethods.vsetfield = sp->vsetparent;
1183
1184         if (sp->FromLT2) _TIFFfree(sp->FromLT2);
1185         if (sp->From14) _TIFFfree(sp->From14);
1186         if (sp->From8) _TIFFfree(sp->From8);
1187         if (sp->ToLinearF) _TIFFfree(sp->ToLinearF);
1188         if (sp->ToLinear16) _TIFFfree(sp->ToLinear16);
1189         if (sp->ToLinear8) _TIFFfree(sp->ToLinear8);
1190         if (sp->state&PLSTATE_INIT) {
1191                 if (tif->tif_mode == O_RDONLY)
1192                         inflateEnd(&sp->stream);
1193                 else
1194                         deflateEnd(&sp->stream);
1195         }
1196         if (sp->tbuf)
1197                 _TIFFfree(sp->tbuf);
1198         _TIFFfree(sp);
1199         tif->tif_data = NULL;
1200
1201         _TIFFSetDefaultCompressionState(tif);
1202 }
1203
1204 static int
1205 PixarLogVSetField(TIFF* tif, ttag_t tag, va_list ap)
1206 {
1207     PixarLogState *sp = (PixarLogState *)tif->tif_data;
1208     int result;
1209     static const char module[] = "PixarLogVSetField";
1210
1211     switch (tag) {
1212      case TIFFTAG_PIXARLOGQUALITY:
1213                 sp->quality = va_arg(ap, int);
1214                 if (tif->tif_mode != O_RDONLY && (sp->state&PLSTATE_INIT)) {
1215                         if (deflateParams(&sp->stream,
1216                             sp->quality, Z_DEFAULT_STRATEGY) != Z_OK) {
1217                                 TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s",
1218                                         tif->tif_name, sp->stream.msg);
1219                                 return (0);
1220                         }
1221                 }
1222                 return (1);
1223      case TIFFTAG_PIXARLOGDATAFMT:
1224         sp->user_datafmt = va_arg(ap, int);
1225         /* Tweak the TIFF header so that the rest of libtiff knows what
1226          * size of data will be passed between app and library, and
1227          * assume that the app knows what it is doing and is not
1228          * confused by these header manipulations...
1229          */
1230         switch (sp->user_datafmt) {
1231          case PIXARLOGDATAFMT_8BIT:
1232          case PIXARLOGDATAFMT_8BITABGR:
1233             TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
1234             TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
1235             break;
1236          case PIXARLOGDATAFMT_11BITLOG:
1237             TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
1238             TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
1239             break;
1240          case PIXARLOGDATAFMT_12BITPICIO:
1241             TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
1242             TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT);
1243             break;
1244          case PIXARLOGDATAFMT_16BIT:
1245             TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
1246             TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
1247             break;
1248          case PIXARLOGDATAFMT_FLOAT:
1249             TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32);
1250             TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
1251             break;
1252         }
1253         /*
1254          * Must recalculate sizes should bits/sample change.
1255          */
1256         tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1;
1257         tif->tif_scanlinesize = TIFFScanlineSize(tif);
1258         result = 1;             /* NB: pseudo tag */
1259         break;
1260      default:
1261         result = (*sp->vsetparent)(tif, tag, ap);
1262     }
1263     return (result);
1264 }
1265
1266 static int
1267 PixarLogVGetField(TIFF* tif, ttag_t tag, va_list ap)
1268 {
1269     PixarLogState *sp = (PixarLogState *)tif->tif_data;
1270
1271     switch (tag) {
1272      case TIFFTAG_PIXARLOGQUALITY:
1273         *va_arg(ap, int*) = sp->quality;
1274         break;
1275      case TIFFTAG_PIXARLOGDATAFMT:
1276         *va_arg(ap, int*) = sp->user_datafmt;
1277         break;
1278      default:
1279         return (*sp->vgetparent)(tif, tag, ap);
1280     }
1281     return (1);
1282 }
1283
1284 static const TIFFFieldInfo pixarlogFieldInfo[] = {
1285     {TIFFTAG_PIXARLOGDATAFMT,0,0,TIFF_ANY,  FIELD_PSEUDO,FALSE,FALSE,""},
1286     {TIFFTAG_PIXARLOGQUALITY,0,0,TIFF_ANY,  FIELD_PSEUDO,FALSE,FALSE,""}
1287 };
1288
1289 int
1290 TIFFInitPixarLog(TIFF* tif, int scheme)
1291 {
1292         static const char module[] = "TIFFInitPixarLog";
1293
1294         PixarLogState* sp;
1295
1296         assert(scheme == COMPRESSION_PIXARLOG);
1297
1298         /*
1299          * Merge codec-specific tag information.
1300          */
1301         if (!_TIFFMergeFieldInfo(tif, pixarlogFieldInfo,
1302                                  TIFFArrayCount(pixarlogFieldInfo))) {
1303                 TIFFErrorExt(tif->tif_clientdata, module,
1304                              "Merging PixarLog codec-specific tags failed");
1305                 return 0;
1306         }
1307
1308         /*
1309          * Allocate state block so tag methods have storage to record values.
1310          */
1311         tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (PixarLogState));
1312         if (tif->tif_data == NULL)
1313                 goto bad;
1314         sp = (PixarLogState*) tif->tif_data;
1315         _TIFFmemset(sp, 0, sizeof (*sp));
1316         sp->stream.data_type = Z_BINARY;
1317         sp->user_datafmt = PIXARLOGDATAFMT_UNKNOWN;
1318
1319         /*
1320          * Install codec methods.
1321          */
1322         tif->tif_setupdecode = PixarLogSetupDecode;
1323         tif->tif_predecode = PixarLogPreDecode;
1324         tif->tif_decoderow = PixarLogDecode;
1325         tif->tif_decodestrip = PixarLogDecode;
1326         tif->tif_decodetile = PixarLogDecode;
1327         tif->tif_setupencode = PixarLogSetupEncode;
1328         tif->tif_preencode = PixarLogPreEncode;
1329         tif->tif_postencode = PixarLogPostEncode;
1330         tif->tif_encoderow = PixarLogEncode;
1331         tif->tif_encodestrip = PixarLogEncode;
1332         tif->tif_encodetile = PixarLogEncode;
1333         tif->tif_close = PixarLogClose;
1334         tif->tif_cleanup = PixarLogCleanup;
1335
1336         /* Override SetField so we can handle our private pseudo-tag */
1337         sp->vgetparent = tif->tif_tagmethods.vgetfield;
1338         tif->tif_tagmethods.vgetfield = PixarLogVGetField;   /* hook for codec tags */
1339         sp->vsetparent = tif->tif_tagmethods.vsetfield;
1340         tif->tif_tagmethods.vsetfield = PixarLogVSetField;   /* hook for codec tags */
1341
1342         /* Default values for codec-specific fields */
1343         sp->quality = Z_DEFAULT_COMPRESSION; /* default comp. level */
1344         sp->state = 0;
1345
1346         /* we don't wish to use the predictor, 
1347          * the default is none, which predictor value 1
1348          */
1349         (void) TIFFPredictorInit(tif);
1350
1351         /*
1352          * build the companding tables 
1353          */
1354         PixarLogMakeTables(sp);
1355
1356         return (1);
1357 bad:
1358         TIFFErrorExt(tif->tif_clientdata, module,
1359                      "No space for PixarLog state block");
1360         return (0);
1361 }
1362 #endif /* PIXARLOG_SUPPORT */
1363
1364 /* vim: set ts=8 sts=8 sw=8 noet: */
1365 /*
1366  * Local Variables:
1367  * mode: c
1368  * c-basic-offset: 8
1369  * fill-column: 78
1370  * End:
1371  */