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