home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / tiff / tif_pixarlog.c < prev    next >
C/C++ Source or Header  |  2000-07-15  |  37KB  |  1,316 lines

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