LCOV - code coverage report
Current view: top level - frmts/gtiff/libtiff - tif_pixarlog.c (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 0 904 0.0 %
Date: 2026-04-23 19:47:11 Functions: 0 26 0.0 %

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

Generated by: LCOV version 1.14