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