LCOV - code coverage report
Current view: directory - frmts/gtiff/libtiff - tif_pixarlog.c (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 740 0 0.0 %
Date: 2010-01-09 Functions: 25 0 0.0 %

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

Generated by: LCOV version 1.7