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