Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygentif_pixarlog.c
Go to the documentation of this file.
00001 /* $Id: tif_pixarlog.c,v 1.15.2.4 2010-06-08 18:50:42 bfriesen Exp $ */ 00002 00003 /* 00004 * Copyright (c) 1996-1997 Sam Leffler 00005 * Copyright (c) 1996 Pixar 00006 * 00007 * Permission to use, copy, modify, distribute, and sell this software and 00008 * its documentation for any purpose is hereby granted without fee, provided 00009 * that (i) the above copyright notices and this permission notice appear in 00010 * all copies of the software and related documentation, and (ii) the names of 00011 * Pixar, Sam Leffler and Silicon Graphics may not be used in any advertising or 00012 * publicity relating to the software without the specific, prior written 00013 * permission of Pixar, Sam Leffler and Silicon Graphics. 00014 * 00015 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 00016 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 00017 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 00018 * 00019 * IN NO EVENT SHALL PIXAR, SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR 00020 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, 00021 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 00022 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 00023 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 00024 * OF THIS SOFTWARE. 00025 */ 00026 00027 #include "tiffiop.h" 00028 #ifdef PIXARLOG_SUPPORT 00029 00030 /* 00031 * TIFF Library. 00032 * PixarLog Compression Support 00033 * 00034 * Contributed by Dan McCoy. 00035 * 00036 * PixarLog film support uses the TIFF library to store companded 00037 * 11 bit values into a tiff file, which are compressed using the 00038 * zip compressor. 00039 * 00040 * The codec can take as input and produce as output 32-bit IEEE float values 00041 * as well as 16-bit or 8-bit unsigned integer values. 00042 * 00043 * On writing any of the above are converted into the internal 00044 * 11-bit log format. In the case of 8 and 16 bit values, the 00045 * input is assumed to be unsigned linear color values that represent 00046 * the range 0-1. In the case of IEEE values, the 0-1 range is assumed to 00047 * be the normal linear color range, in addition over 1 values are 00048 * accepted up to a value of about 25.0 to encode "hot" hightlights and such. 00049 * The encoding is lossless for 8-bit values, slightly lossy for the 00050 * other bit depths. The actual color precision should be better 00051 * than the human eye can perceive with extra room to allow for 00052 * error introduced by further image computation. As with any quantized 00053 * color format, it is possible to perform image calculations which 00054 * expose the quantization error. This format should certainly be less 00055 * susceptable to such errors than standard 8-bit encodings, but more 00056 * susceptable than straight 16-bit or 32-bit encodings. 00057 * 00058 * On reading the internal format is converted to the desired output format. 00059 * The program can request which format it desires by setting the internal 00060 * pseudo tag TIFFTAG_PIXARLOGDATAFMT to one of these possible values: 00061 * PIXARLOGDATAFMT_FLOAT = provide IEEE float values. 00062 * PIXARLOGDATAFMT_16BIT = provide unsigned 16-bit integer values 00063 * PIXARLOGDATAFMT_8BIT = provide unsigned 8-bit integer values 00064 * 00065 * alternately PIXARLOGDATAFMT_8BITABGR provides unsigned 8-bit integer 00066 * values with the difference that if there are exactly three or four channels 00067 * (rgb or rgba) it swaps the channel order (bgr or abgr). 00068 * 00069 * PIXARLOGDATAFMT_11BITLOG provides the internal encoding directly 00070 * packed in 16-bit values. However no tools are supplied for interpreting 00071 * these values. 00072 * 00073 * "hot" (over 1.0) areas written in floating point get clamped to 00074 * 1.0 in the integer data types. 00075 * 00076 * When the file is closed after writing, the bit depth and sample format 00077 * are set always to appear as if 8-bit data has been written into it. 00078 * That way a naive program unaware of the particulars of the encoding 00079 * gets the format it is most likely able to handle. 00080 * 00081 * The codec does it's own horizontal differencing step on the coded 00082 * values so the libraries predictor stuff should be turned off. 00083 * The codec also handle byte swapping the encoded values as necessary 00084 * since the library does not have the information necessary 00085 * to know the bit depth of the raw unencoded buffer. 00086 * 00087 */ 00088 00089 #include "tif_predict.h" 00090 #include "zlib.h" 00091 00092 #include <stdio.h> 00093 #include <stdlib.h> 00094 #include <math.h> 00095 00096 /* Tables for converting to/from 11 bit coded values */ 00097 00098 #define TSIZE 2048 /* decode table size (11-bit tokens) */ 00099 #define TSIZEP1 2049 /* Plus one for slop */ 00100 #define ONE 1250 /* token value of 1.0 exactly */ 00101 #define RATIO 1.004 /* nominal ratio for log part */ 00102 00103 #define CODE_MASK 0x7ff /* 11 bits. */ 00104 00105 static float Fltsize; 00106 static float LogK1, LogK2; 00107 00108 #define REPEAT(n, op) { int i; i=n; do { i--; op; } while (i>0); } 00109 00110 static void 00111 horizontalAccumulateF(uint16 *wp, int n, int stride, float *op, 00112 float *ToLinearF) 00113 { 00114 register unsigned int cr, cg, cb, ca, mask; 00115 register float t0, t1, t2, t3; 00116 00117 if (n >= stride) { 00118 mask = CODE_MASK; 00119 if (stride == 3) { 00120 t0 = ToLinearF[cr = wp[0]]; 00121 t1 = ToLinearF[cg = wp[1]]; 00122 t2 = ToLinearF[cb = wp[2]]; 00123 op[0] = t0; 00124 op[1] = t1; 00125 op[2] = t2; 00126 n -= 3; 00127 while (n > 0) { 00128 wp += 3; 00129 op += 3; 00130 n -= 3; 00131 t0 = ToLinearF[(cr += wp[0]) & mask]; 00132 t1 = ToLinearF[(cg += wp[1]) & mask]; 00133 t2 = ToLinearF[(cb += wp[2]) & mask]; 00134 op[0] = t0; 00135 op[1] = t1; 00136 op[2] = t2; 00137 } 00138 } else if (stride == 4) { 00139 t0 = ToLinearF[cr = wp[0]]; 00140 t1 = ToLinearF[cg = wp[1]]; 00141 t2 = ToLinearF[cb = wp[2]]; 00142 t3 = ToLinearF[ca = wp[3]]; 00143 op[0] = t0; 00144 op[1] = t1; 00145 op[2] = t2; 00146 op[3] = t3; 00147 n -= 4; 00148 while (n > 0) { 00149 wp += 4; 00150 op += 4; 00151 n -= 4; 00152 t0 = ToLinearF[(cr += wp[0]) & mask]; 00153 t1 = ToLinearF[(cg += wp[1]) & mask]; 00154 t2 = ToLinearF[(cb += wp[2]) & mask]; 00155 t3 = ToLinearF[(ca += wp[3]) & mask]; 00156 op[0] = t0; 00157 op[1] = t1; 00158 op[2] = t2; 00159 op[3] = t3; 00160 } 00161 } else { 00162 REPEAT(stride, *op = ToLinearF[*wp&mask]; wp++; op++) 00163 n -= stride; 00164 while (n > 0) { 00165 REPEAT(stride, 00166 wp[stride] += *wp; *op = ToLinearF[*wp&mask]; wp++; op++) 00167 n -= stride; 00168 } 00169 } 00170 } 00171 } 00172 00173 static void 00174 horizontalAccumulate12(uint16 *wp, int n, int stride, int16 *op, 00175 float *ToLinearF) 00176 { 00177 register unsigned int cr, cg, cb, ca, mask; 00178 register float t0, t1, t2, t3; 00179 00180 #define SCALE12 2048.0F 00181 #define CLAMP12(t) (((t) < 3071) ? (uint16) (t) : 3071) 00182 00183 if (n >= stride) { 00184 mask = CODE_MASK; 00185 if (stride == 3) { 00186 t0 = ToLinearF[cr = wp[0]] * SCALE12; 00187 t1 = ToLinearF[cg = wp[1]] * SCALE12; 00188 t2 = ToLinearF[cb = wp[2]] * SCALE12; 00189 op[0] = CLAMP12(t0); 00190 op[1] = CLAMP12(t1); 00191 op[2] = CLAMP12(t2); 00192 n -= 3; 00193 while (n > 0) { 00194 wp += 3; 00195 op += 3; 00196 n -= 3; 00197 t0 = ToLinearF[(cr += wp[0]) & mask] * SCALE12; 00198 t1 = ToLinearF[(cg += wp[1]) & mask] * SCALE12; 00199 t2 = ToLinearF[(cb += wp[2]) & mask] * SCALE12; 00200 op[0] = CLAMP12(t0); 00201 op[1] = CLAMP12(t1); 00202 op[2] = CLAMP12(t2); 00203 } 00204 } else if (stride == 4) { 00205 t0 = ToLinearF[cr = wp[0]] * SCALE12; 00206 t1 = ToLinearF[cg = wp[1]] * SCALE12; 00207 t2 = ToLinearF[cb = wp[2]] * SCALE12; 00208 t3 = ToLinearF[ca = wp[3]] * SCALE12; 00209 op[0] = CLAMP12(t0); 00210 op[1] = CLAMP12(t1); 00211 op[2] = CLAMP12(t2); 00212 op[3] = CLAMP12(t3); 00213 n -= 4; 00214 while (n > 0) { 00215 wp += 4; 00216 op += 4; 00217 n -= 4; 00218 t0 = ToLinearF[(cr += wp[0]) & mask] * SCALE12; 00219 t1 = ToLinearF[(cg += wp[1]) & mask] * SCALE12; 00220 t2 = ToLinearF[(cb += wp[2]) & mask] * SCALE12; 00221 t3 = ToLinearF[(ca += wp[3]) & mask] * SCALE12; 00222 op[0] = CLAMP12(t0); 00223 op[1] = CLAMP12(t1); 00224 op[2] = CLAMP12(t2); 00225 op[3] = CLAMP12(t3); 00226 } 00227 } else { 00228 REPEAT(stride, t0 = ToLinearF[*wp&mask] * SCALE12; 00229 *op = CLAMP12(t0); wp++; op++) 00230 n -= stride; 00231 while (n > 0) { 00232 REPEAT(stride, 00233 wp[stride] += *wp; t0 = ToLinearF[wp[stride]&mask]*SCALE12; 00234 *op = CLAMP12(t0); wp++; op++) 00235 n -= stride; 00236 } 00237 } 00238 } 00239 } 00240 00241 static void 00242 horizontalAccumulate16(uint16 *wp, int n, int stride, uint16 *op, 00243 uint16 *ToLinear16) 00244 { 00245 register unsigned int cr, cg, cb, ca, mask; 00246 00247 if (n >= stride) { 00248 mask = CODE_MASK; 00249 if (stride == 3) { 00250 op[0] = ToLinear16[cr = wp[0]]; 00251 op[1] = ToLinear16[cg = wp[1]]; 00252 op[2] = ToLinear16[cb = wp[2]]; 00253 n -= 3; 00254 while (n > 0) { 00255 wp += 3; 00256 op += 3; 00257 n -= 3; 00258 op[0] = ToLinear16[(cr += wp[0]) & mask]; 00259 op[1] = ToLinear16[(cg += wp[1]) & mask]; 00260 op[2] = ToLinear16[(cb += wp[2]) & mask]; 00261 } 00262 } else if (stride == 4) { 00263 op[0] = ToLinear16[cr = wp[0]]; 00264 op[1] = ToLinear16[cg = wp[1]]; 00265 op[2] = ToLinear16[cb = wp[2]]; 00266 op[3] = ToLinear16[ca = wp[3]]; 00267 n -= 4; 00268 while (n > 0) { 00269 wp += 4; 00270 op += 4; 00271 n -= 4; 00272 op[0] = ToLinear16[(cr += wp[0]) & mask]; 00273 op[1] = ToLinear16[(cg += wp[1]) & mask]; 00274 op[2] = ToLinear16[(cb += wp[2]) & mask]; 00275 op[3] = ToLinear16[(ca += wp[3]) & mask]; 00276 } 00277 } else { 00278 REPEAT(stride, *op = ToLinear16[*wp&mask]; wp++; op++) 00279 n -= stride; 00280 while (n > 0) { 00281 REPEAT(stride, 00282 wp[stride] += *wp; *op = ToLinear16[*wp&mask]; wp++; op++) 00283 n -= stride; 00284 } 00285 } 00286 } 00287 } 00288 00289 /* 00290 * Returns the log encoded 11-bit values with the horizontal 00291 * differencing undone. 00292 */ 00293 static void 00294 horizontalAccumulate11(uint16 *wp, int n, int stride, uint16 *op) 00295 { 00296 register unsigned int cr, cg, cb, ca, mask; 00297 00298 if (n >= stride) { 00299 mask = CODE_MASK; 00300 if (stride == 3) { 00301 op[0] = cr = wp[0]; op[1] = cg = wp[1]; op[2] = cb = wp[2]; 00302 n -= 3; 00303 while (n > 0) { 00304 wp += 3; 00305 op += 3; 00306 n -= 3; 00307 op[0] = (cr += wp[0]) & mask; 00308 op[1] = (cg += wp[1]) & mask; 00309 op[2] = (cb += wp[2]) & mask; 00310 } 00311 } else if (stride == 4) { 00312 op[0] = cr = wp[0]; op[1] = cg = wp[1]; 00313 op[2] = cb = wp[2]; op[3] = ca = wp[3]; 00314 n -= 4; 00315 while (n > 0) { 00316 wp += 4; 00317 op += 4; 00318 n -= 4; 00319 op[0] = (cr += wp[0]) & mask; 00320 op[1] = (cg += wp[1]) & mask; 00321 op[2] = (cb += wp[2]) & mask; 00322 op[3] = (ca += wp[3]) & mask; 00323 } 00324 } else { 00325 REPEAT(stride, *op = *wp&mask; wp++; op++) 00326 n -= stride; 00327 while (n > 0) { 00328 REPEAT(stride, 00329 wp[stride] += *wp; *op = *wp&mask; wp++; op++) 00330 n -= stride; 00331 } 00332 } 00333 } 00334 } 00335 00336 static void 00337 horizontalAccumulate8(uint16 *wp, int n, int stride, unsigned char *op, 00338 unsigned char *ToLinear8) 00339 { 00340 register unsigned int cr, cg, cb, ca, mask; 00341 00342 if (n >= stride) { 00343 mask = CODE_MASK; 00344 if (stride == 3) { 00345 op[0] = ToLinear8[cr = wp[0]]; 00346 op[1] = ToLinear8[cg = wp[1]]; 00347 op[2] = ToLinear8[cb = wp[2]]; 00348 n -= 3; 00349 while (n > 0) { 00350 n -= 3; 00351 wp += 3; 00352 op += 3; 00353 op[0] = ToLinear8[(cr += wp[0]) & mask]; 00354 op[1] = ToLinear8[(cg += wp[1]) & mask]; 00355 op[2] = ToLinear8[(cb += wp[2]) & mask]; 00356 } 00357 } else if (stride == 4) { 00358 op[0] = ToLinear8[cr = wp[0]]; 00359 op[1] = ToLinear8[cg = wp[1]]; 00360 op[2] = ToLinear8[cb = wp[2]]; 00361 op[3] = ToLinear8[ca = wp[3]]; 00362 n -= 4; 00363 while (n > 0) { 00364 n -= 4; 00365 wp += 4; 00366 op += 4; 00367 op[0] = ToLinear8[(cr += wp[0]) & mask]; 00368 op[1] = ToLinear8[(cg += wp[1]) & mask]; 00369 op[2] = ToLinear8[(cb += wp[2]) & mask]; 00370 op[3] = ToLinear8[(ca += wp[3]) & mask]; 00371 } 00372 } else { 00373 REPEAT(stride, *op = ToLinear8[*wp&mask]; wp++; op++) 00374 n -= stride; 00375 while (n > 0) { 00376 REPEAT(stride, 00377 wp[stride] += *wp; *op = ToLinear8[*wp&mask]; wp++; op++) 00378 n -= stride; 00379 } 00380 } 00381 } 00382 } 00383 00384 00385 static void 00386 horizontalAccumulate8abgr(uint16 *wp, int n, int stride, unsigned char *op, 00387 unsigned char *ToLinear8) 00388 { 00389 register unsigned int cr, cg, cb, ca, mask; 00390 register unsigned char t0, t1, t2, t3; 00391 00392 if (n >= stride) { 00393 mask = CODE_MASK; 00394 if (stride == 3) { 00395 op[0] = 0; 00396 t1 = ToLinear8[cb = wp[2]]; 00397 t2 = ToLinear8[cg = wp[1]]; 00398 t3 = ToLinear8[cr = wp[0]]; 00399 op[1] = t1; 00400 op[2] = t2; 00401 op[3] = t3; 00402 n -= 3; 00403 while (n > 0) { 00404 n -= 3; 00405 wp += 3; 00406 op += 4; 00407 op[0] = 0; 00408 t1 = ToLinear8[(cb += wp[2]) & mask]; 00409 t2 = ToLinear8[(cg += wp[1]) & mask]; 00410 t3 = ToLinear8[(cr += wp[0]) & mask]; 00411 op[1] = t1; 00412 op[2] = t2; 00413 op[3] = t3; 00414 } 00415 } else if (stride == 4) { 00416 t0 = ToLinear8[ca = wp[3]]; 00417 t1 = ToLinear8[cb = wp[2]]; 00418 t2 = ToLinear8[cg = wp[1]]; 00419 t3 = ToLinear8[cr = wp[0]]; 00420 op[0] = t0; 00421 op[1] = t1; 00422 op[2] = t2; 00423 op[3] = t3; 00424 n -= 4; 00425 while (n > 0) { 00426 n -= 4; 00427 wp += 4; 00428 op += 4; 00429 t0 = ToLinear8[(ca += wp[3]) & mask]; 00430 t1 = ToLinear8[(cb += wp[2]) & mask]; 00431 t2 = ToLinear8[(cg += wp[1]) & mask]; 00432 t3 = ToLinear8[(cr += wp[0]) & mask]; 00433 op[0] = t0; 00434 op[1] = t1; 00435 op[2] = t2; 00436 op[3] = t3; 00437 } 00438 } else { 00439 REPEAT(stride, *op = ToLinear8[*wp&mask]; wp++; op++) 00440 n -= stride; 00441 while (n > 0) { 00442 REPEAT(stride, 00443 wp[stride] += *wp; *op = ToLinear8[*wp&mask]; wp++; op++) 00444 n -= stride; 00445 } 00446 } 00447 } 00448 } 00449 00450 /* 00451 * State block for each open TIFF 00452 * file using PixarLog compression/decompression. 00453 */ 00454 typedef struct { 00455 TIFFPredictorState predict; 00456 z_stream stream; 00457 uint16 *tbuf; 00458 uint16 stride; 00459 int state; 00460 int user_datafmt; 00461 int quality; 00462 #define PLSTATE_INIT 1 00463 00464 TIFFVSetMethod vgetparent; /* super-class method */ 00465 TIFFVSetMethod vsetparent; /* super-class method */ 00466 00467 float *ToLinearF; 00468 uint16 *ToLinear16; 00469 unsigned char *ToLinear8; 00470 uint16 *FromLT2; 00471 uint16 *From14; /* Really for 16-bit data, but we shift down 2 */ 00472 uint16 *From8; 00473 00474 } PixarLogState; 00475 00476 static int 00477 PixarLogMakeTables(PixarLogState *sp) 00478 { 00479 00480 /* 00481 * We make several tables here to convert between various external 00482 * representations (float, 16-bit, and 8-bit) and the internal 00483 * 11-bit companded representation. The 11-bit representation has two 00484 * distinct regions. A linear bottom end up through .018316 in steps 00485 * of about .000073, and a region of constant ratio up to about 25. 00486 * These floating point numbers are stored in the main table ToLinearF. 00487 * All other tables are derived from this one. The tables (and the 00488 * ratios) are continuous at the internal seam. 00489 */ 00490 00491 int nlin, lt2size; 00492 int i, j; 00493 double b, c, linstep, v; 00494 float *ToLinearF; 00495 uint16 *ToLinear16; 00496 unsigned char *ToLinear8; 00497 uint16 *FromLT2; 00498 uint16 *From14; /* Really for 16-bit data, but we shift down 2 */ 00499 uint16 *From8; 00500 00501 c = log(RATIO); 00502 nlin = (int)(1./c); /* nlin must be an integer */ 00503 c = 1./nlin; 00504 b = exp(-c*ONE); /* multiplicative scale factor [b*exp(c*ONE) = 1] */ 00505 linstep = b*c*exp(1.); 00506 00507 LogK1 = (float)(1./c); /* if (v >= 2) token = k1*log(v*k2) */ 00508 LogK2 = (float)(1./b); 00509 lt2size = (int)(2./linstep) + 1; 00510 FromLT2 = (uint16 *)_TIFFmalloc(lt2size*sizeof(uint16)); 00511 From14 = (uint16 *)_TIFFmalloc(16384*sizeof(uint16)); 00512 From8 = (uint16 *)_TIFFmalloc(256*sizeof(uint16)); 00513 ToLinearF = (float *)_TIFFmalloc(TSIZEP1 * sizeof(float)); 00514 ToLinear16 = (uint16 *)_TIFFmalloc(TSIZEP1 * sizeof(uint16)); 00515 ToLinear8 = (unsigned char *)_TIFFmalloc(TSIZEP1 * sizeof(unsigned char)); 00516 if (FromLT2 == NULL || From14 == NULL || From8 == NULL || 00517 ToLinearF == NULL || ToLinear16 == NULL || ToLinear8 == NULL) { 00518 if (FromLT2) _TIFFfree(FromLT2); 00519 if (From14) _TIFFfree(From14); 00520 if (From8) _TIFFfree(From8); 00521 if (ToLinearF) _TIFFfree(ToLinearF); 00522 if (ToLinear16) _TIFFfree(ToLinear16); 00523 if (ToLinear8) _TIFFfree(ToLinear8); 00524 sp->FromLT2 = NULL; 00525 sp->From14 = NULL; 00526 sp->From8 = NULL; 00527 sp->ToLinearF = NULL; 00528 sp->ToLinear16 = NULL; 00529 sp->ToLinear8 = NULL; 00530 return 0; 00531 } 00532 00533 j = 0; 00534 00535 for (i = 0; i < nlin; i++) { 00536 v = i * linstep; 00537 ToLinearF[j++] = (float)v; 00538 } 00539 00540 for (i = nlin; i < TSIZE; i++) 00541 ToLinearF[j++] = (float)(b*exp(c*i)); 00542 00543 ToLinearF[2048] = ToLinearF[2047]; 00544 00545 for (i = 0; i < TSIZEP1; i++) { 00546 v = ToLinearF[i]*65535.0 + 0.5; 00547 ToLinear16[i] = (v > 65535.0) ? 65535 : (uint16)v; 00548 v = ToLinearF[i]*255.0 + 0.5; 00549 ToLinear8[i] = (v > 255.0) ? 255 : (unsigned char)v; 00550 } 00551 00552 j = 0; 00553 for (i = 0; i < lt2size; i++) { 00554 if ((i*linstep)*(i*linstep) > ToLinearF[j]*ToLinearF[j+1]) 00555 j++; 00556 FromLT2[i] = j; 00557 } 00558 00559 /* 00560 * Since we lose info anyway on 16-bit data, we set up a 14-bit 00561 * table and shift 16-bit values down two bits on input. 00562 * saves a little table space. 00563 */ 00564 j = 0; 00565 for (i = 0; i < 16384; i++) { 00566 while ((i/16383.)*(i/16383.) > ToLinearF[j]*ToLinearF[j+1]) 00567 j++; 00568 From14[i] = j; 00569 } 00570 00571 j = 0; 00572 for (i = 0; i < 256; i++) { 00573 while ((i/255.)*(i/255.) > ToLinearF[j]*ToLinearF[j+1]) 00574 j++; 00575 From8[i] = j; 00576 } 00577 00578 Fltsize = (float)(lt2size/2); 00579 00580 sp->ToLinearF = ToLinearF; 00581 sp->ToLinear16 = ToLinear16; 00582 sp->ToLinear8 = ToLinear8; 00583 sp->FromLT2 = FromLT2; 00584 sp->From14 = From14; 00585 sp->From8 = From8; 00586 00587 return 1; 00588 } 00589 00590 #define DecoderState(tif) ((PixarLogState*) (tif)->tif_data) 00591 #define EncoderState(tif) ((PixarLogState*) (tif)->tif_data) 00592 00593 static int PixarLogEncode(TIFF*, tidata_t, tsize_t, tsample_t); 00594 static int PixarLogDecode(TIFF*, tidata_t, tsize_t, tsample_t); 00595 00596 #define PIXARLOGDATAFMT_UNKNOWN -1 00597 00598 static int 00599 PixarLogGuessDataFmt(TIFFDirectory *td) 00600 { 00601 int guess = PIXARLOGDATAFMT_UNKNOWN; 00602 int format = td->td_sampleformat; 00603 00604 /* If the user didn't tell us his datafmt, 00605 * take our best guess from the bitspersample. 00606 */ 00607 switch (td->td_bitspersample) { 00608 case 32: 00609 if (format == SAMPLEFORMAT_IEEEFP) 00610 guess = PIXARLOGDATAFMT_FLOAT; 00611 break; 00612 case 16: 00613 if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT) 00614 guess = PIXARLOGDATAFMT_16BIT; 00615 break; 00616 case 12: 00617 if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_INT) 00618 guess = PIXARLOGDATAFMT_12BITPICIO; 00619 break; 00620 case 11: 00621 if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT) 00622 guess = PIXARLOGDATAFMT_11BITLOG; 00623 break; 00624 case 8: 00625 if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT) 00626 guess = PIXARLOGDATAFMT_8BIT; 00627 break; 00628 } 00629 00630 return guess; 00631 } 00632 00633 static uint32 00634 multiply(size_t m1, size_t m2) 00635 { 00636 uint32 bytes = m1 * m2; 00637 00638 if (m1 && bytes / m1 != m2) 00639 bytes = 0; 00640 00641 return bytes; 00642 } 00643 00644 static int 00645 PixarLogSetupDecode(TIFF* tif) 00646 { 00647 TIFFDirectory *td = &tif->tif_dir; 00648 PixarLogState* sp = DecoderState(tif); 00649 tsize_t tbuf_size; 00650 static const char module[] = "PixarLogSetupDecode"; 00651 00652 assert(sp != NULL); 00653 00654 /* Make sure no byte swapping happens on the data 00655 * after decompression. */ 00656 tif->tif_postdecode = _TIFFNoPostDecode; 00657 00658 /* for some reason, we can't do this in TIFFInitPixarLog */ 00659 00660 sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ? 00661 td->td_samplesperpixel : 1); 00662 tbuf_size = multiply(multiply(multiply(sp->stride, td->td_imagewidth), 00663 td->td_rowsperstrip), sizeof(uint16)); 00664 if (tbuf_size == 0) 00665 return (0); 00666 sp->tbuf = (uint16 *) _TIFFmalloc(tbuf_size); 00667 if (sp->tbuf == NULL) 00668 return (0); 00669 if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) 00670 sp->user_datafmt = PixarLogGuessDataFmt(td); 00671 if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) { 00672 TIFFErrorExt(tif->tif_clientdata, module, 00673 "PixarLog compression can't handle bits depth/data format combination (depth: %d)", 00674 td->td_bitspersample); 00675 return (0); 00676 } 00677 00678 if (inflateInit(&sp->stream) != Z_OK) { 00679 TIFFErrorExt(tif->tif_clientdata, module, "%s: %s", tif->tif_name, sp->stream.msg); 00680 return (0); 00681 } else { 00682 sp->state |= PLSTATE_INIT; 00683 return (1); 00684 } 00685 } 00686 00687 /* 00688 * Setup state for decoding a strip. 00689 */ 00690 static int 00691 PixarLogPreDecode(TIFF* tif, tsample_t s) 00692 { 00693 PixarLogState* sp = DecoderState(tif); 00694 00695 (void) s; 00696 assert(sp != NULL); 00697 sp->stream.next_in = tif->tif_rawdata; 00698 sp->stream.avail_in = tif->tif_rawcc; 00699 return (inflateReset(&sp->stream) == Z_OK); 00700 } 00701 00702 static int 00703 PixarLogDecode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s) 00704 { 00705 TIFFDirectory *td = &tif->tif_dir; 00706 PixarLogState* sp = DecoderState(tif); 00707 static const char module[] = "PixarLogDecode"; 00708 int i, nsamples, llen; 00709 uint16 *up; 00710 00711 switch (sp->user_datafmt) { 00712 case PIXARLOGDATAFMT_FLOAT: 00713 nsamples = occ / sizeof(float); /* XXX float == 32 bits */ 00714 break; 00715 case PIXARLOGDATAFMT_16BIT: 00716 case PIXARLOGDATAFMT_12BITPICIO: 00717 case PIXARLOGDATAFMT_11BITLOG: 00718 nsamples = occ / sizeof(uint16); /* XXX uint16 == 16 bits */ 00719 break; 00720 case PIXARLOGDATAFMT_8BIT: 00721 case PIXARLOGDATAFMT_8BITABGR: 00722 nsamples = occ; 00723 break; 00724 default: 00725 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 00726 "%d bit input not supported in PixarLog", 00727 td->td_bitspersample); 00728 return 0; 00729 } 00730 00731 llen = sp->stride * td->td_imagewidth; 00732 00733 (void) s; 00734 assert(sp != NULL); 00735 sp->stream.next_out = (unsigned char *) sp->tbuf; 00736 sp->stream.avail_out = nsamples * sizeof(uint16); 00737 do { 00738 int state = inflate(&sp->stream, Z_PARTIAL_FLUSH); 00739 if (state == Z_STREAM_END) { 00740 break; /* XXX */ 00741 } 00742 if (state == Z_DATA_ERROR) { 00743 TIFFErrorExt(tif->tif_clientdata, module, 00744 "%s: Decoding error at scanline %d, %s", 00745 tif->tif_name, tif->tif_row, sp->stream.msg); 00746 if (inflateSync(&sp->stream) != Z_OK) 00747 return (0); 00748 continue; 00749 } 00750 if (state != Z_OK) { 00751 TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s", 00752 tif->tif_name, sp->stream.msg); 00753 return (0); 00754 } 00755 } while (sp->stream.avail_out > 0); 00756 00757 /* hopefully, we got all the bytes we needed */ 00758 if (sp->stream.avail_out != 0) { 00759 TIFFErrorExt(tif->tif_clientdata, module, 00760 "%s: Not enough data at scanline %d (short %d bytes)", 00761 tif->tif_name, tif->tif_row, sp->stream.avail_out); 00762 return (0); 00763 } 00764 00765 up = sp->tbuf; 00766 /* Swap bytes in the data if from a different endian machine. */ 00767 if (tif->tif_flags & TIFF_SWAB) 00768 TIFFSwabArrayOfShort(up, nsamples); 00769 00770 /* 00771 * if llen is not an exact multiple of nsamples, the decode operation 00772 * may overflow the output buffer, so truncate it enough to prevent 00773 * that but still salvage as much data as possible. 00774 */ 00775 if (nsamples % llen) { 00776 TIFFWarningExt(tif->tif_clientdata, module, 00777 "%s: stride %d is not a multiple of sample count, " 00778 "%d, data truncated.", tif->tif_name, llen, nsamples); 00779 nsamples -= nsamples % llen; 00780 } 00781 00782 for (i = 0; i < nsamples; i += llen, up += llen) { 00783 switch (sp->user_datafmt) { 00784 case PIXARLOGDATAFMT_FLOAT: 00785 horizontalAccumulateF(up, llen, sp->stride, 00786 (float *)op, sp->ToLinearF); 00787 op += llen * sizeof(float); 00788 break; 00789 case PIXARLOGDATAFMT_16BIT: 00790 horizontalAccumulate16(up, llen, sp->stride, 00791 (uint16 *)op, sp->ToLinear16); 00792 op += llen * sizeof(uint16); 00793 break; 00794 case PIXARLOGDATAFMT_12BITPICIO: 00795 horizontalAccumulate12(up, llen, sp->stride, 00796 (int16 *)op, sp->ToLinearF); 00797 op += llen * sizeof(int16); 00798 break; 00799 case PIXARLOGDATAFMT_11BITLOG: 00800 horizontalAccumulate11(up, llen, sp->stride, 00801 (uint16 *)op); 00802 op += llen * sizeof(uint16); 00803 break; 00804 case PIXARLOGDATAFMT_8BIT: 00805 horizontalAccumulate8(up, llen, sp->stride, 00806 (unsigned char *)op, sp->ToLinear8); 00807 op += llen * sizeof(unsigned char); 00808 break; 00809 case PIXARLOGDATAFMT_8BITABGR: 00810 horizontalAccumulate8abgr(up, llen, sp->stride, 00811 (unsigned char *)op, sp->ToLinear8); 00812 op += llen * sizeof(unsigned char); 00813 break; 00814 default: 00815 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 00816 "PixarLogDecode: unsupported bits/sample: %d", 00817 td->td_bitspersample); 00818 return (0); 00819 } 00820 } 00821 00822 return (1); 00823 } 00824 00825 static int 00826 PixarLogSetupEncode(TIFF* tif) 00827 { 00828 TIFFDirectory *td = &tif->tif_dir; 00829 PixarLogState* sp = EncoderState(tif); 00830 tsize_t tbuf_size; 00831 static const char module[] = "PixarLogSetupEncode"; 00832 00833 assert(sp != NULL); 00834 00835 /* for some reason, we can't do this in TIFFInitPixarLog */ 00836 00837 sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ? 00838 td->td_samplesperpixel : 1); 00839 tbuf_size = multiply(multiply(multiply(sp->stride, td->td_imagewidth), 00840 td->td_rowsperstrip), sizeof(uint16)); 00841 if (tbuf_size == 0) 00842 return (0); 00843 sp->tbuf = (uint16 *) _TIFFmalloc(tbuf_size); 00844 if (sp->tbuf == NULL) 00845 return (0); 00846 if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) 00847 sp->user_datafmt = PixarLogGuessDataFmt(td); 00848 if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) { 00849 TIFFErrorExt(tif->tif_clientdata, module, "PixarLog compression can't handle %d bit linear encodings", td->td_bitspersample); 00850 return (0); 00851 } 00852 00853 if (deflateInit(&sp->stream, sp->quality) != Z_OK) { 00854 TIFFErrorExt(tif->tif_clientdata, module, "%s: %s", tif->tif_name, sp->stream.msg); 00855 return (0); 00856 } else { 00857 sp->state |= PLSTATE_INIT; 00858 return (1); 00859 } 00860 } 00861 00862 /* 00863 * Reset encoding state at the start of a strip. 00864 */ 00865 static int 00866 PixarLogPreEncode(TIFF* tif, tsample_t s) 00867 { 00868 PixarLogState *sp = EncoderState(tif); 00869 00870 (void) s; 00871 assert(sp != NULL); 00872 sp->stream.next_out = tif->tif_rawdata; 00873 sp->stream.avail_out = tif->tif_rawdatasize; 00874 return (deflateReset(&sp->stream) == Z_OK); 00875 } 00876 00877 static void 00878 horizontalDifferenceF(float *ip, int n, int stride, uint16 *wp, uint16 *FromLT2) 00879 { 00880 00881 int32 r1, g1, b1, a1, r2, g2, b2, a2, mask; 00882 float fltsize = Fltsize; 00883 00884 #define CLAMP(v) ( (v<(float)0.) ? 0 \ 00885 : (v<(float)2.) ? FromLT2[(int)(v*fltsize)] \ 00886 : (v>(float)24.2) ? 2047 \ 00887 : LogK1*log(v*LogK2) + 0.5 ) 00888 00889 mask = CODE_MASK; 00890 if (n >= stride) { 00891 if (stride == 3) { 00892 r2 = wp[0] = (uint16) CLAMP(ip[0]); 00893 g2 = wp[1] = (uint16) CLAMP(ip[1]); 00894 b2 = wp[2] = (uint16) CLAMP(ip[2]); 00895 n -= 3; 00896 while (n > 0) { 00897 n -= 3; 00898 wp += 3; 00899 ip += 3; 00900 r1 = (int32) CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1; 00901 g1 = (int32) CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1; 00902 b1 = (int32) CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1; 00903 } 00904 } else if (stride == 4) { 00905 r2 = wp[0] = (uint16) CLAMP(ip[0]); 00906 g2 = wp[1] = (uint16) CLAMP(ip[1]); 00907 b2 = wp[2] = (uint16) CLAMP(ip[2]); 00908 a2 = wp[3] = (uint16) CLAMP(ip[3]); 00909 n -= 4; 00910 while (n > 0) { 00911 n -= 4; 00912 wp += 4; 00913 ip += 4; 00914 r1 = (int32) CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1; 00915 g1 = (int32) CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1; 00916 b1 = (int32) CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1; 00917 a1 = (int32) CLAMP(ip[3]); wp[3] = (a1-a2) & mask; a2 = a1; 00918 } 00919 } else { 00920 ip += n - 1; /* point to last one */ 00921 wp += n - 1; /* point to last one */ 00922 n -= stride; 00923 while (n > 0) { 00924 REPEAT(stride, wp[0] = (uint16) CLAMP(ip[0]); 00925 wp[stride] -= wp[0]; 00926 wp[stride] &= mask; 00927 wp--; ip--) 00928 n -= stride; 00929 } 00930 REPEAT(stride, wp[0] = (uint16) CLAMP(ip[0]); wp--; ip--) 00931 } 00932 } 00933 } 00934 00935 static void 00936 horizontalDifference16(unsigned short *ip, int n, int stride, 00937 unsigned short *wp, uint16 *From14) 00938 { 00939 register int r1, g1, b1, a1, r2, g2, b2, a2, mask; 00940 00941 /* assumption is unsigned pixel values */ 00942 #undef CLAMP 00943 #define CLAMP(v) From14[(v) >> 2] 00944 00945 mask = CODE_MASK; 00946 if (n >= stride) { 00947 if (stride == 3) { 00948 r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]); 00949 b2 = wp[2] = CLAMP(ip[2]); 00950 n -= 3; 00951 while (n > 0) { 00952 n -= 3; 00953 wp += 3; 00954 ip += 3; 00955 r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1; 00956 g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1; 00957 b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1; 00958 } 00959 } else if (stride == 4) { 00960 r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]); 00961 b2 = wp[2] = CLAMP(ip[2]); a2 = wp[3] = CLAMP(ip[3]); 00962 n -= 4; 00963 while (n > 0) { 00964 n -= 4; 00965 wp += 4; 00966 ip += 4; 00967 r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1; 00968 g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1; 00969 b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1; 00970 a1 = CLAMP(ip[3]); wp[3] = (a1-a2) & mask; a2 = a1; 00971 } 00972 } else { 00973 ip += n - 1; /* point to last one */ 00974 wp += n - 1; /* point to last one */ 00975 n -= stride; 00976 while (n > 0) { 00977 REPEAT(stride, wp[0] = CLAMP(ip[0]); 00978 wp[stride] -= wp[0]; 00979 wp[stride] &= mask; 00980 wp--; ip--) 00981 n -= stride; 00982 } 00983 REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--) 00984 } 00985 } 00986 } 00987 00988 00989 static void 00990 horizontalDifference8(unsigned char *ip, int n, int stride, 00991 unsigned short *wp, uint16 *From8) 00992 { 00993 register int r1, g1, b1, a1, r2, g2, b2, a2, mask; 00994 00995 #undef CLAMP 00996 #define CLAMP(v) (From8[(v)]) 00997 00998 mask = CODE_MASK; 00999 if (n >= stride) { 01000 if (stride == 3) { 01001 r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]); 01002 b2 = wp[2] = CLAMP(ip[2]); 01003 n -= 3; 01004 while (n > 0) { 01005 n -= 3; 01006 r1 = CLAMP(ip[3]); wp[3] = (r1-r2) & mask; r2 = r1; 01007 g1 = CLAMP(ip[4]); wp[4] = (g1-g2) & mask; g2 = g1; 01008 b1 = CLAMP(ip[5]); wp[5] = (b1-b2) & mask; b2 = b1; 01009 wp += 3; 01010 ip += 3; 01011 } 01012 } else if (stride == 4) { 01013 r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]); 01014 b2 = wp[2] = CLAMP(ip[2]); a2 = wp[3] = CLAMP(ip[3]); 01015 n -= 4; 01016 while (n > 0) { 01017 n -= 4; 01018 r1 = CLAMP(ip[4]); wp[4] = (r1-r2) & mask; r2 = r1; 01019 g1 = CLAMP(ip[5]); wp[5] = (g1-g2) & mask; g2 = g1; 01020 b1 = CLAMP(ip[6]); wp[6] = (b1-b2) & mask; b2 = b1; 01021 a1 = CLAMP(ip[7]); wp[7] = (a1-a2) & mask; a2 = a1; 01022 wp += 4; 01023 ip += 4; 01024 } 01025 } else { 01026 wp += n + stride - 1; /* point to last one */ 01027 ip += n + stride - 1; /* point to last one */ 01028 n -= stride; 01029 while (n > 0) { 01030 REPEAT(stride, wp[0] = CLAMP(ip[0]); 01031 wp[stride] -= wp[0]; 01032 wp[stride] &= mask; 01033 wp--; ip--) 01034 n -= stride; 01035 } 01036 REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--) 01037 } 01038 } 01039 } 01040 01041 /* 01042 * Encode a chunk of pixels. 01043 */ 01044 static int 01045 PixarLogEncode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) 01046 { 01047 TIFFDirectory *td = &tif->tif_dir; 01048 PixarLogState *sp = EncoderState(tif); 01049 static const char module[] = "PixarLogEncode"; 01050 int i, n, llen; 01051 unsigned short * up; 01052 01053 (void) s; 01054 01055 switch (sp->user_datafmt) { 01056 case PIXARLOGDATAFMT_FLOAT: 01057 n = cc / sizeof(float); /* XXX float == 32 bits */ 01058 break; 01059 case PIXARLOGDATAFMT_16BIT: 01060 case PIXARLOGDATAFMT_12BITPICIO: 01061 case PIXARLOGDATAFMT_11BITLOG: 01062 n = cc / sizeof(uint16); /* XXX uint16 == 16 bits */ 01063 break; 01064 case PIXARLOGDATAFMT_8BIT: 01065 case PIXARLOGDATAFMT_8BITABGR: 01066 n = cc; 01067 break; 01068 default: 01069 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 01070 "%d bit input not supported in PixarLog", 01071 td->td_bitspersample); 01072 return 0; 01073 } 01074 01075 llen = sp->stride * td->td_imagewidth; 01076 01077 for (i = 0, up = sp->tbuf; i < n; i += llen, up += llen) { 01078 switch (sp->user_datafmt) { 01079 case PIXARLOGDATAFMT_FLOAT: 01080 horizontalDifferenceF((float *)bp, llen, 01081 sp->stride, up, sp->FromLT2); 01082 bp += llen * sizeof(float); 01083 break; 01084 case PIXARLOGDATAFMT_16BIT: 01085 horizontalDifference16((uint16 *)bp, llen, 01086 sp->stride, up, sp->From14); 01087 bp += llen * sizeof(uint16); 01088 break; 01089 case PIXARLOGDATAFMT_8BIT: 01090 horizontalDifference8((unsigned char *)bp, llen, 01091 sp->stride, up, sp->From8); 01092 bp += llen * sizeof(unsigned char); 01093 break; 01094 default: 01095 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 01096 "%d bit input not supported in PixarLog", 01097 td->td_bitspersample); 01098 return 0; 01099 } 01100 } 01101 01102 sp->stream.next_in = (unsigned char *) sp->tbuf; 01103 sp->stream.avail_in = n * sizeof(uint16); 01104 01105 do { 01106 if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) { 01107 TIFFErrorExt(tif->tif_clientdata, module, "%s: Encoder error: %s", 01108 tif->tif_name, sp->stream.msg); 01109 return (0); 01110 } 01111 if (sp->stream.avail_out == 0) { 01112 tif->tif_rawcc = tif->tif_rawdatasize; 01113 TIFFFlushData1(tif); 01114 sp->stream.next_out = tif->tif_rawdata; 01115 sp->stream.avail_out = tif->tif_rawdatasize; 01116 } 01117 } while (sp->stream.avail_in > 0); 01118 return (1); 01119 } 01120 01121 /* 01122 * Finish off an encoded strip by flushing the last 01123 * string and tacking on an End Of Information code. 01124 */ 01125 01126 static int 01127 PixarLogPostEncode(TIFF* tif) 01128 { 01129 PixarLogState *sp = EncoderState(tif); 01130 static const char module[] = "PixarLogPostEncode"; 01131 int state; 01132 01133 sp->stream.avail_in = 0; 01134 01135 do { 01136 state = deflate(&sp->stream, Z_FINISH); 01137 switch (state) { 01138 case Z_STREAM_END: 01139 case Z_OK: 01140 if (sp->stream.avail_out != (uint32)tif->tif_rawdatasize) { 01141 tif->tif_rawcc = 01142 tif->tif_rawdatasize - sp->stream.avail_out; 01143 TIFFFlushData1(tif); 01144 sp->stream.next_out = tif->tif_rawdata; 01145 sp->stream.avail_out = tif->tif_rawdatasize; 01146 } 01147 break; 01148 default: 01149 TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s", 01150 tif->tif_name, sp->stream.msg); 01151 return (0); 01152 } 01153 } while (state != Z_STREAM_END); 01154 return (1); 01155 } 01156 01157 static void 01158 PixarLogClose(TIFF* tif) 01159 { 01160 TIFFDirectory *td = &tif->tif_dir; 01161 01162 /* In a really sneaky maneuver, on close, we covertly modify both 01163 * bitspersample and sampleformat in the directory to indicate 01164 * 8-bit linear. This way, the decode "just works" even for 01165 * readers that don't know about PixarLog, or how to set 01166 * the PIXARLOGDATFMT pseudo-tag. 01167 */ 01168 td->td_bitspersample = 8; 01169 td->td_sampleformat = SAMPLEFORMAT_UINT; 01170 } 01171 01172 static void 01173 PixarLogCleanup(TIFF* tif) 01174 { 01175 PixarLogState* sp = (PixarLogState*) tif->tif_data; 01176 01177 assert(sp != 0); 01178 01179 (void)TIFFPredictorCleanup(tif); 01180 01181 tif->tif_tagmethods.vgetfield = sp->vgetparent; 01182 tif->tif_tagmethods.vsetfield = sp->vsetparent; 01183 01184 if (sp->FromLT2) _TIFFfree(sp->FromLT2); 01185 if (sp->From14) _TIFFfree(sp->From14); 01186 if (sp->From8) _TIFFfree(sp->From8); 01187 if (sp->ToLinearF) _TIFFfree(sp->ToLinearF); 01188 if (sp->ToLinear16) _TIFFfree(sp->ToLinear16); 01189 if (sp->ToLinear8) _TIFFfree(sp->ToLinear8); 01190 if (sp->state&PLSTATE_INIT) { 01191 if (tif->tif_mode == O_RDONLY) 01192 inflateEnd(&sp->stream); 01193 else 01194 deflateEnd(&sp->stream); 01195 } 01196 if (sp->tbuf) 01197 _TIFFfree(sp->tbuf); 01198 _TIFFfree(sp); 01199 tif->tif_data = NULL; 01200 01201 _TIFFSetDefaultCompressionState(tif); 01202 } 01203 01204 static int 01205 PixarLogVSetField(TIFF* tif, ttag_t tag, va_list ap) 01206 { 01207 PixarLogState *sp = (PixarLogState *)tif->tif_data; 01208 int result; 01209 static const char module[] = "PixarLogVSetField"; 01210 01211 switch (tag) { 01212 case TIFFTAG_PIXARLOGQUALITY: 01213 sp->quality = va_arg(ap, int); 01214 if (tif->tif_mode != O_RDONLY && (sp->state&PLSTATE_INIT)) { 01215 if (deflateParams(&sp->stream, 01216 sp->quality, Z_DEFAULT_STRATEGY) != Z_OK) { 01217 TIFFErrorExt(tif->tif_clientdata, module, "%s: zlib error: %s", 01218 tif->tif_name, sp->stream.msg); 01219 return (0); 01220 } 01221 } 01222 return (1); 01223 case TIFFTAG_PIXARLOGDATAFMT: 01224 sp->user_datafmt = va_arg(ap, int); 01225 /* Tweak the TIFF header so that the rest of libtiff knows what 01226 * size of data will be passed between app and library, and 01227 * assume that the app knows what it is doing and is not 01228 * confused by these header manipulations... 01229 */ 01230 switch (sp->user_datafmt) { 01231 case PIXARLOGDATAFMT_8BIT: 01232 case PIXARLOGDATAFMT_8BITABGR: 01233 TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8); 01234 TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); 01235 break; 01236 case PIXARLOGDATAFMT_11BITLOG: 01237 TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16); 01238 TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); 01239 break; 01240 case PIXARLOGDATAFMT_12BITPICIO: 01241 TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16); 01242 TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT); 01243 break; 01244 case PIXARLOGDATAFMT_16BIT: 01245 TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16); 01246 TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT); 01247 break; 01248 case PIXARLOGDATAFMT_FLOAT: 01249 TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32); 01250 TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP); 01251 break; 01252 } 01253 /* 01254 * Must recalculate sizes should bits/sample change. 01255 */ 01256 tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1; 01257 tif->tif_scanlinesize = TIFFScanlineSize(tif); 01258 result = 1; /* NB: pseudo tag */ 01259 break; 01260 default: 01261 result = (*sp->vsetparent)(tif, tag, ap); 01262 } 01263 return (result); 01264 } 01265 01266 static int 01267 PixarLogVGetField(TIFF* tif, ttag_t tag, va_list ap) 01268 { 01269 PixarLogState *sp = (PixarLogState *)tif->tif_data; 01270 01271 switch (tag) { 01272 case TIFFTAG_PIXARLOGQUALITY: 01273 *va_arg(ap, int*) = sp->quality; 01274 break; 01275 case TIFFTAG_PIXARLOGDATAFMT: 01276 *va_arg(ap, int*) = sp->user_datafmt; 01277 break; 01278 default: 01279 return (*sp->vgetparent)(tif, tag, ap); 01280 } 01281 return (1); 01282 } 01283 01284 static const TIFFFieldInfo pixarlogFieldInfo[] = { 01285 {TIFFTAG_PIXARLOGDATAFMT,0,0,TIFF_ANY, FIELD_PSEUDO,FALSE,FALSE,""}, 01286 {TIFFTAG_PIXARLOGQUALITY,0,0,TIFF_ANY, FIELD_PSEUDO,FALSE,FALSE,""} 01287 }; 01288 01289 int 01290 TIFFInitPixarLog(TIFF* tif, int scheme) 01291 { 01292 static const char module[] = "TIFFInitPixarLog"; 01293 01294 PixarLogState* sp; 01295 01296 assert(scheme == COMPRESSION_PIXARLOG); 01297 01298 /* 01299 * Merge codec-specific tag information. 01300 */ 01301 if (!_TIFFMergeFieldInfo(tif, pixarlogFieldInfo, 01302 TIFFArrayCount(pixarlogFieldInfo))) { 01303 TIFFErrorExt(tif->tif_clientdata, module, 01304 "Merging PixarLog codec-specific tags failed"); 01305 return 0; 01306 } 01307 01308 /* 01309 * Allocate state block so tag methods have storage to record values. 01310 */ 01311 tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (PixarLogState)); 01312 if (tif->tif_data == NULL) 01313 goto bad; 01314 sp = (PixarLogState*) tif->tif_data; 01315 _TIFFmemset(sp, 0, sizeof (*sp)); 01316 sp->stream.data_type = Z_BINARY; 01317 sp->user_datafmt = PIXARLOGDATAFMT_UNKNOWN; 01318 01319 /* 01320 * Install codec methods. 01321 */ 01322 tif->tif_setupdecode = PixarLogSetupDecode; 01323 tif->tif_predecode = PixarLogPreDecode; 01324 tif->tif_decoderow = PixarLogDecode; 01325 tif->tif_decodestrip = PixarLogDecode; 01326 tif->tif_decodetile = PixarLogDecode; 01327 tif->tif_setupencode = PixarLogSetupEncode; 01328 tif->tif_preencode = PixarLogPreEncode; 01329 tif->tif_postencode = PixarLogPostEncode; 01330 tif->tif_encoderow = PixarLogEncode; 01331 tif->tif_encodestrip = PixarLogEncode; 01332 tif->tif_encodetile = PixarLogEncode; 01333 tif->tif_close = PixarLogClose; 01334 tif->tif_cleanup = PixarLogCleanup; 01335 01336 /* Override SetField so we can handle our private pseudo-tag */ 01337 sp->vgetparent = tif->tif_tagmethods.vgetfield; 01338 tif->tif_tagmethods.vgetfield = PixarLogVGetField; /* hook for codec tags */ 01339 sp->vsetparent = tif->tif_tagmethods.vsetfield; 01340 tif->tif_tagmethods.vsetfield = PixarLogVSetField; /* hook for codec tags */ 01341 01342 /* Default values for codec-specific fields */ 01343 sp->quality = Z_DEFAULT_COMPRESSION; /* default comp. level */ 01344 sp->state = 0; 01345 01346 /* we don't wish to use the predictor, 01347 * the default is none, which predictor value 1 01348 */ 01349 (void) TIFFPredictorInit(tif); 01350 01351 /* 01352 * build the companding tables 01353 */ 01354 PixarLogMakeTables(sp); 01355 01356 return (1); 01357 bad: 01358 TIFFErrorExt(tif->tif_clientdata, module, 01359 "No space for PixarLog state block"); 01360 return (0); 01361 } 01362 #endif /* PIXARLOG_SUPPORT */ 01363 01364 /* vim: set ts=8 sts=8 sw=8 noet: */ 01365 /* 01366 * Local Variables: 01367 * mode: c 01368 * c-basic-offset: 8 01369 * fill-column: 78 01370 * End: 01371 */ Generated on Sun May 27 2012 04:19:35 for ReactOS by
1.7.6.1
|