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