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