LCOV - code coverage report
Current view: directory - frmts/gtiff/libtiff - tif_pixarlog.c (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 748 0 0.0 %
Date: 2013-03-30 Functions: 26 0 0.0 %

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

Generated by: LCOV version 1.7