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