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