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