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