]> git.saurik.com Git - wxWidgets.git/blob - src/tiff/libtiff/tif_pixarlog.c
Remove all lines containing cvs/svn "$Id$" keyword.
[wxWidgets.git] / src / tiff / libtiff / tif_pixarlog.c
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
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
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
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
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
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
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
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
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
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
647 PixarLogFixupTags(TIFF* tif)
648 {
649 (void) tif;
650 return (1);
651 }
652
653 static int
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 */