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