ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

tif_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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.