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