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 916 0.0 %
Date: 2026-05-13 23:47:50 Functions: 0 27 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             :     /* Fix: ABGR with stride=3 expands 3 samples to 4 output bytes per pixel */
     880           0 :     if (sp->user_datafmt == PIXARLOGDATAFMT_8BITABGR && sp->stride == 3)
     881             :     {
     882           0 :         tmsize_t required = (tmsize_t)td->td_imagewidth * 4;
     883           0 :         if (occ < required)
     884             :         {
     885           0 :             TIFFErrorExtR(tif, module,
     886             :                           "Output buffer too small for PixarLog ABGR data");
     887           0 :             memset(op, 0, (size_t)occ);
     888           0 :             return (0);
     889             :         }
     890             :     }
     891             : 
     892             :     (void)s;
     893           0 :     assert(sp != NULL);
     894             : 
     895           0 :     sp->stream.next_in = tif->tif_rawcp;
     896           0 :     sp->stream.avail_in = (uInt)tif->tif_rawcc;
     897             : 
     898           0 :     sp->stream.next_out = (unsigned char *)sp->tbuf;
     899             :     assert(sizeof(sp->stream.avail_out) == 4); /* if this assert gets raised,
     900             :          we need to simplify this code to reflect a ZLib that is likely updated
     901             :          to deal with 8byte memory sizes, though this code will respond
     902             :          appropriately even before we simplify it */
     903           0 :     sp->stream.avail_out = (uInt)((unsigned long)nsamples * sizeof(uint16_t));
     904           0 :     if (sp->stream.avail_out != (unsigned long)nsamples * sizeof(uint16_t))
     905             :     {
     906           0 :         TIFFErrorExtR(tif, module, "ZLib cannot deal with buffers this size");
     907           0 :         memset(op, 0, (size_t)occ);
     908           0 :         return (0);
     909             :     }
     910             :     /* Check that we will not fill more than what was allocated */
     911           0 :     if ((tmsize_t)sp->stream.avail_out > sp->tbuf_size)
     912             :     {
     913           0 :         TIFFErrorExtR(tif, module, "sp->stream.avail_out > sp->tbuf_size");
     914           0 :         memset(op, 0, (size_t)occ);
     915           0 :         return (0);
     916             :     }
     917             :     do
     918             :     {
     919           0 :         int state = inflate(&sp->stream, Z_PARTIAL_FLUSH);
     920           0 :         if (state == Z_STREAM_END)
     921             :         {
     922           0 :             break; /* XXX */
     923             :         }
     924           0 :         if (state == Z_DATA_ERROR)
     925             :         {
     926           0 :             TIFFErrorExtR(tif, module,
     927             :                           "Decoding error at scanline %" PRIu32 ", %s",
     928             :                           tif->tif_dir.td_row,
     929           0 :                           sp->stream.msg ? sp->stream.msg : "(null)");
     930           0 :             memset(op, 0, (size_t)occ);
     931           0 :             return (0);
     932             :         }
     933           0 :         if (state != Z_OK)
     934             :         {
     935           0 :             TIFFErrorExtR(tif, module, "ZLib error: %s",
     936           0 :                           sp->stream.msg ? sp->stream.msg : "(null)");
     937           0 :             memset(op, 0, (size_t)occ);
     938           0 :             return (0);
     939             :         }
     940           0 :     } while (sp->stream.avail_out > 0);
     941             : 
     942             :     /* hopefully, we got all the bytes we needed */
     943           0 :     if (sp->stream.avail_out != 0)
     944             :     {
     945           0 :         TIFFErrorExtR(tif, module,
     946             :                       "Not enough data at scanline %" PRIu32
     947             :                       " (short %u bytes)",
     948             :                       tif->tif_dir.td_row, sp->stream.avail_out);
     949           0 :         memset(op, 0, (size_t)occ);
     950           0 :         return (0);
     951             :     }
     952             : 
     953           0 :     tif->tif_rawcp = sp->stream.next_in;
     954           0 :     tif->tif_rawcc = sp->stream.avail_in;
     955             : 
     956           0 :     up = sp->tbuf;
     957             :     /* Swap bytes in the data if from a different endian machine. */
     958           0 :     if (tif->tif_flags & TIFF_SWAB)
     959           0 :         TIFFSwabArrayOfShort(up, nsamples);
     960             : 
     961             :     /*
     962             :      * if llen is not an exact multiple of nsamples, the decode operation
     963             :      * may overflow the output buffer, so truncate it enough to prevent
     964             :      * that but still salvage as much data as possible.
     965             :      */
     966           0 :     if (nsamples % llen)
     967             :     {
     968           0 :         TIFFWarningExtR(tif, module,
     969             :                         "stride %" TIFF_SSIZE_FORMAT
     970             :                         " is not a multiple of sample count, "
     971             :                         "%" TIFF_SSIZE_FORMAT ", data truncated.",
     972             :                         llen, nsamples);
     973           0 :         nsamples -= nsamples % llen;
     974             :     }
     975             : 
     976           0 :     for (i = 0; i < nsamples; i += llen, up += llen)
     977             :     {
     978           0 :         switch (sp->user_datafmt)
     979             :         {
     980           0 :             case PIXARLOGDATAFMT_FLOAT:
     981           0 :                 horizontalAccumulateF(up, llen, sp->stride, (float *)op,
     982             :                                       sp->ToLinearF);
     983           0 :                 op += (unsigned long)llen * sizeof(float);
     984           0 :                 break;
     985           0 :             case PIXARLOGDATAFMT_16BIT:
     986           0 :                 horizontalAccumulate16(up, llen, sp->stride, (uint16_t *)op,
     987             :                                        sp->ToLinear16);
     988           0 :                 op += (unsigned long)llen * sizeof(uint16_t);
     989           0 :                 break;
     990           0 :             case PIXARLOGDATAFMT_12BITPICIO:
     991           0 :                 horizontalAccumulate12(up, llen, sp->stride, (int16_t *)op,
     992             :                                        sp->ToLinearF);
     993           0 :                 op += (unsigned long)llen * sizeof(int16_t);
     994           0 :                 break;
     995           0 :             case PIXARLOGDATAFMT_11BITLOG:
     996           0 :                 horizontalAccumulate11(up, llen, sp->stride, (uint16_t *)op);
     997           0 :                 op += (unsigned long)llen * sizeof(uint16_t);
     998           0 :                 break;
     999           0 :             case PIXARLOGDATAFMT_8BIT:
    1000           0 :                 horizontalAccumulate8(up, llen, sp->stride, (unsigned char *)op,
    1001             :                                       sp->ToLinear8);
    1002           0 :                 op += (unsigned long)llen * sizeof(unsigned char);
    1003           0 :                 break;
    1004           0 :             case PIXARLOGDATAFMT_8BITABGR:
    1005           0 :                 horizontalAccumulate8abgr(up, llen, sp->stride,
    1006             :                                           (unsigned char *)op, sp->ToLinear8);
    1007             : 
    1008             :                 /* For stride == 3 (RGB), horizontalAccumulate8abgr expands to 4
    1009             :                  * bytes/pixel (ABGR) */
    1010           0 :                 if (sp->stride == 3)
    1011           0 :                     op += (unsigned long)td->td_imagewidth * 4;
    1012             :                 else
    1013           0 :                     op += (unsigned long)llen * sizeof(unsigned char);
    1014           0 :                 break;
    1015           0 :             default:
    1016           0 :                 TIFFErrorExtR(tif, module, "Unsupported bits/sample: %" PRIu16,
    1017           0 :                               td->td_bitspersample);
    1018           0 :                 memset(op, 0, (size_t)occ);
    1019           0 :                 return (0);
    1020             :         }
    1021             :     }
    1022             : 
    1023           0 :     return (1);
    1024             : }
    1025             : 
    1026           0 : static int PixarLogSetupEncode(TIFF *tif)
    1027             : {
    1028             :     static const char module[] = "PixarLogSetupEncode";
    1029           0 :     TIFFDirectory *td = &tif->tif_dir;
    1030           0 :     PixarLogState *sp = PixarLogEncoderState(tif);
    1031             :     tmsize_t tbuf_size;
    1032             : 
    1033           0 :     assert(sp != NULL);
    1034             : 
    1035             :     /* for some reason, we can't do this in TIFFInitPixarLog */
    1036             : 
    1037           0 :     sp->stride =
    1038           0 :         (td->td_planarconfig == PLANARCONFIG_CONTIG ? td->td_samplesperpixel
    1039             :                                                     : 1);
    1040             :     tbuf_size =
    1041           0 :         multiply_ms(multiply_ms(multiply_ms(sp->stride, td->td_imagewidth),
    1042           0 :                                 td->td_rowsperstrip),
    1043             :                     sizeof(uint16_t));
    1044           0 :     if (tbuf_size == 0)
    1045           0 :         return (0); /* TODO: this is an error return without error report
    1046             :                        through TIFFErrorExt */
    1047           0 :     sp->tbuf = (uint16_t *)_TIFFmallocExt(tif, tbuf_size);
    1048           0 :     if (sp->tbuf == NULL)
    1049           0 :         return (0);
    1050           0 :     if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN)
    1051           0 :         sp->user_datafmt = PixarLogGuessDataFmt(td);
    1052           0 :     if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN)
    1053             :     {
    1054           0 :         TIFFErrorExtR(tif, module,
    1055             :                       "PixarLog compression can't handle %" PRIu16
    1056             :                       " bit linear encodings",
    1057           0 :                       td->td_bitspersample);
    1058           0 :         return (0);
    1059             :     }
    1060             : 
    1061           0 :     if (deflateInit(&sp->stream, sp->quality) != Z_OK)
    1062             :     {
    1063           0 :         TIFFErrorExtR(tif, module, "%s",
    1064           0 :                       sp->stream.msg ? sp->stream.msg : "(null)");
    1065           0 :         return (0);
    1066             :     }
    1067             :     else
    1068             :     {
    1069           0 :         sp->state |= PLSTATE_INIT;
    1070           0 :         return (1);
    1071             :     }
    1072             : }
    1073             : 
    1074             : /*
    1075             :  * Reset encoding state at the start of a strip.
    1076             :  */
    1077           0 : static int PixarLogPreEncode(TIFF *tif, uint16_t s)
    1078             : {
    1079             :     static const char module[] = "PixarLogPreEncode";
    1080           0 :     PixarLogState *sp = PixarLogEncoderState(tif);
    1081             : 
    1082             :     (void)s;
    1083           0 :     assert(sp != NULL);
    1084           0 :     sp->stream.next_out = tif->tif_rawdata;
    1085             :     assert(sizeof(sp->stream.avail_out) == 4); /* if this assert gets raised,
    1086             :          we need to simplify this code to reflect a ZLib that is likely updated
    1087             :          to deal with 8byte memory sizes, though this code will respond
    1088             :          appropriately even before we simplify it */
    1089           0 :     sp->stream.avail_out = (uInt)tif->tif_rawdatasize;
    1090           0 :     if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize)
    1091             :     {
    1092           0 :         TIFFErrorExtR(tif, module, "ZLib cannot deal with buffers this size");
    1093           0 :         return (0);
    1094             :     }
    1095           0 :     return (deflateReset(&sp->stream) == Z_OK);
    1096             : }
    1097             : 
    1098           0 : static void horizontalDifferenceF(float *ip, tmsize_t n, int stride,
    1099             :                                   uint16_t *wp, uint16_t *FromLT2)
    1100             : {
    1101             :     int32_t r1, g1, b1, a1, r2, g2, b2, a2, mask;
    1102           0 :     float fltsize = Fltsize;
    1103             : 
    1104             : #define CLAMP(v)                                                               \
    1105             :     ((v < (float)0.)   ? 0                                                     \
    1106             :      : (v < (float)2.) ? FromLT2[(int)(v * fltsize)]                           \
    1107             :      : (v > (float)24.2)                                                       \
    1108             :          ? 2047                                                                \
    1109             :          : (double)LogK1 * log((double)v * (double)LogK2) + 0.5)
    1110             : 
    1111           0 :     mask = CODE_MASK;
    1112           0 :     if (n >= stride)
    1113             :     {
    1114           0 :         if (stride == 3)
    1115             :         {
    1116           0 :             r2 = wp[0] = (uint16_t)CLAMP(ip[0]);
    1117           0 :             g2 = wp[1] = (uint16_t)CLAMP(ip[1]);
    1118           0 :             b2 = wp[2] = (uint16_t)CLAMP(ip[2]);
    1119           0 :             n -= 3;
    1120           0 :             while (n > 0)
    1121             :             {
    1122           0 :                 n -= 3;
    1123           0 :                 wp += 3;
    1124           0 :                 ip += 3;
    1125           0 :                 r1 = (int32_t)CLAMP(ip[0]);
    1126           0 :                 wp[0] = (uint16_t)((r1 - r2) & mask);
    1127           0 :                 r2 = r1;
    1128           0 :                 g1 = (int32_t)CLAMP(ip[1]);
    1129           0 :                 wp[1] = (uint16_t)((g1 - g2) & mask);
    1130           0 :                 g2 = g1;
    1131           0 :                 b1 = (int32_t)CLAMP(ip[2]);
    1132           0 :                 wp[2] = (uint16_t)((b1 - b2) & mask);
    1133           0 :                 b2 = b1;
    1134             :             }
    1135             :         }
    1136           0 :         else if (stride == 4)
    1137             :         {
    1138           0 :             r2 = wp[0] = (uint16_t)CLAMP(ip[0]);
    1139           0 :             g2 = wp[1] = (uint16_t)CLAMP(ip[1]);
    1140           0 :             b2 = wp[2] = (uint16_t)CLAMP(ip[2]);
    1141           0 :             a2 = wp[3] = (uint16_t)CLAMP(ip[3]);
    1142           0 :             n -= 4;
    1143           0 :             while (n > 0)
    1144             :             {
    1145           0 :                 n -= 4;
    1146           0 :                 wp += 4;
    1147           0 :                 ip += 4;
    1148           0 :                 r1 = (int32_t)CLAMP(ip[0]);
    1149           0 :                 wp[0] = (uint16_t)((r1 - r2) & mask);
    1150           0 :                 r2 = r1;
    1151           0 :                 g1 = (int32_t)CLAMP(ip[1]);
    1152           0 :                 wp[1] = (uint16_t)((g1 - g2) & mask);
    1153           0 :                 g2 = g1;
    1154           0 :                 b1 = (int32_t)CLAMP(ip[2]);
    1155           0 :                 wp[2] = (uint16_t)((b1 - b2) & mask);
    1156           0 :                 b2 = b1;
    1157           0 :                 a1 = (int32_t)CLAMP(ip[3]);
    1158           0 :                 wp[3] = (uint16_t)((a1 - a2) & mask);
    1159           0 :                 a2 = a1;
    1160             :             }
    1161             :         }
    1162             :         else
    1163             :         {
    1164           0 :             REPEAT(stride, wp[0] = (uint16_t)CLAMP(ip[0]); wp++; ip++)
    1165           0 :             n -= stride;
    1166           0 :             while (n > 0)
    1167             :             {
    1168           0 :                 REPEAT(stride,
    1169             :                        wp[0] = (uint16_t)(((int32_t)CLAMP(ip[0]) -
    1170             :                                            (int32_t)CLAMP(ip[-stride])) &
    1171             :                                           mask);
    1172             :                        wp++; ip++)
    1173           0 :                 n -= stride;
    1174             :             }
    1175             :         }
    1176             :     }
    1177           0 : }
    1178             : 
    1179           0 : static void horizontalDifference16(unsigned short *ip, tmsize_t n, int stride,
    1180             :                                    unsigned short *wp, uint16_t *From14)
    1181             : {
    1182             :     int r1, g1, b1, a1, r2, g2, b2, a2, mask;
    1183             : 
    1184             : /* assumption is unsigned pixel values */
    1185             : #undef CLAMP
    1186             : #define CLAMP(v) From14[(v) >> 2]
    1187             : 
    1188           0 :     mask = CODE_MASK;
    1189           0 :     if (n >= stride)
    1190             :     {
    1191           0 :         if (stride == 3)
    1192             :         {
    1193           0 :             r2 = wp[0] = CLAMP(ip[0]);
    1194           0 :             g2 = wp[1] = CLAMP(ip[1]);
    1195           0 :             b2 = wp[2] = CLAMP(ip[2]);
    1196           0 :             n -= 3;
    1197           0 :             while (n > 0)
    1198             :             {
    1199           0 :                 n -= 3;
    1200           0 :                 wp += 3;
    1201           0 :                 ip += 3;
    1202           0 :                 r1 = CLAMP(ip[0]);
    1203           0 :                 wp[0] = (uint16_t)((r1 - r2) & mask);
    1204           0 :                 r2 = r1;
    1205           0 :                 g1 = CLAMP(ip[1]);
    1206           0 :                 wp[1] = (uint16_t)((g1 - g2) & mask);
    1207           0 :                 g2 = g1;
    1208           0 :                 b1 = CLAMP(ip[2]);
    1209           0 :                 wp[2] = (uint16_t)((b1 - b2) & mask);
    1210           0 :                 b2 = b1;
    1211             :             }
    1212             :         }
    1213           0 :         else if (stride == 4)
    1214             :         {
    1215           0 :             r2 = wp[0] = CLAMP(ip[0]);
    1216           0 :             g2 = wp[1] = CLAMP(ip[1]);
    1217           0 :             b2 = wp[2] = CLAMP(ip[2]);
    1218           0 :             a2 = wp[3] = CLAMP(ip[3]);
    1219           0 :             n -= 4;
    1220           0 :             while (n > 0)
    1221             :             {
    1222           0 :                 n -= 4;
    1223           0 :                 wp += 4;
    1224           0 :                 ip += 4;
    1225           0 :                 r1 = CLAMP(ip[0]);
    1226           0 :                 wp[0] = (uint16_t)((r1 - r2) & mask);
    1227           0 :                 r2 = r1;
    1228           0 :                 g1 = CLAMP(ip[1]);
    1229           0 :                 wp[1] = (uint16_t)((g1 - g2) & mask);
    1230           0 :                 g2 = g1;
    1231           0 :                 b1 = CLAMP(ip[2]);
    1232           0 :                 wp[2] = (uint16_t)((b1 - b2) & mask);
    1233           0 :                 b2 = b1;
    1234           0 :                 a1 = CLAMP(ip[3]);
    1235           0 :                 wp[3] = (uint16_t)((a1 - a2) & mask);
    1236           0 :                 a2 = a1;
    1237             :             }
    1238             :         }
    1239             :         else
    1240             :         {
    1241           0 :             REPEAT(stride, wp[0] = CLAMP(ip[0]); wp++; ip++)
    1242           0 :             n -= stride;
    1243           0 :             while (n > 0)
    1244             :             {
    1245           0 :                 REPEAT(stride,
    1246             :                        wp[0] = (uint16_t)((CLAMP(ip[0]) - CLAMP(ip[-stride])) &
    1247             :                                           mask);
    1248             :                        wp++; ip++)
    1249           0 :                 n -= stride;
    1250             :             }
    1251             :         }
    1252             :     }
    1253           0 : }
    1254             : 
    1255           0 : static void horizontalDifference8(unsigned char *ip, tmsize_t n, int stride,
    1256             :                                   unsigned short *wp, uint16_t *From8)
    1257             : {
    1258             :     int r1, g1, b1, a1, r2, g2, b2, a2, mask;
    1259             : 
    1260             : #undef CLAMP
    1261             : #define CLAMP(v) (From8[(v)])
    1262             : 
    1263           0 :     mask = CODE_MASK;
    1264           0 :     if (n >= stride)
    1265             :     {
    1266           0 :         if (stride == 3)
    1267             :         {
    1268           0 :             r2 = wp[0] = CLAMP(ip[0]);
    1269           0 :             g2 = wp[1] = CLAMP(ip[1]);
    1270           0 :             b2 = wp[2] = CLAMP(ip[2]);
    1271           0 :             n -= 3;
    1272           0 :             while (n > 0)
    1273             :             {
    1274           0 :                 n -= 3;
    1275           0 :                 r1 = CLAMP(ip[3]);
    1276           0 :                 wp[3] = (uint16_t)((r1 - r2) & mask);
    1277           0 :                 r2 = r1;
    1278           0 :                 g1 = CLAMP(ip[4]);
    1279           0 :                 wp[4] = (uint16_t)((g1 - g2) & mask);
    1280           0 :                 g2 = g1;
    1281           0 :                 b1 = CLAMP(ip[5]);
    1282           0 :                 wp[5] = (uint16_t)((b1 - b2) & mask);
    1283           0 :                 b2 = b1;
    1284           0 :                 wp += 3;
    1285           0 :                 ip += 3;
    1286             :             }
    1287             :         }
    1288           0 :         else if (stride == 4)
    1289             :         {
    1290           0 :             r2 = wp[0] = CLAMP(ip[0]);
    1291           0 :             g2 = wp[1] = CLAMP(ip[1]);
    1292           0 :             b2 = wp[2] = CLAMP(ip[2]);
    1293           0 :             a2 = wp[3] = CLAMP(ip[3]);
    1294           0 :             n -= 4;
    1295           0 :             while (n > 0)
    1296             :             {
    1297           0 :                 n -= 4;
    1298           0 :                 r1 = CLAMP(ip[4]);
    1299           0 :                 wp[4] = (uint16_t)((r1 - r2) & mask);
    1300           0 :                 r2 = r1;
    1301           0 :                 g1 = CLAMP(ip[5]);
    1302           0 :                 wp[5] = (uint16_t)((g1 - g2) & mask);
    1303           0 :                 g2 = g1;
    1304           0 :                 b1 = CLAMP(ip[6]);
    1305           0 :                 wp[6] = (uint16_t)((b1 - b2) & mask);
    1306           0 :                 b2 = b1;
    1307           0 :                 a1 = CLAMP(ip[7]);
    1308           0 :                 wp[7] = (uint16_t)((a1 - a2) & mask);
    1309           0 :                 a2 = a1;
    1310           0 :                 wp += 4;
    1311           0 :                 ip += 4;
    1312             :             }
    1313             :         }
    1314             :         else
    1315             :         {
    1316           0 :             REPEAT(stride, wp[0] = CLAMP(ip[0]); wp++; ip++)
    1317           0 :             n -= stride;
    1318           0 :             while (n > 0)
    1319             :             {
    1320           0 :                 REPEAT(stride,
    1321             :                        wp[0] = (uint16_t)((CLAMP(ip[0]) - CLAMP(ip[-stride])) &
    1322             :                                           mask);
    1323             :                        wp++; ip++)
    1324           0 :                 n -= stride;
    1325             :             }
    1326             :         }
    1327             :     }
    1328           0 : }
    1329             : 
    1330             : /*
    1331             :  * Encode a chunk of pixels.
    1332             :  */
    1333           0 : static int PixarLogEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
    1334             : {
    1335             :     static const char module[] = "PixarLogEncode";
    1336           0 :     TIFFDirectory *td = &tif->tif_dir;
    1337           0 :     PixarLogState *sp = PixarLogEncoderState(tif);
    1338             :     tmsize_t i;
    1339             :     tmsize_t n;
    1340             :     tmsize_t llen;
    1341             :     unsigned short *up;
    1342             : 
    1343             :     (void)s;
    1344             : 
    1345           0 :     switch (sp->user_datafmt)
    1346             :     {
    1347           0 :         case PIXARLOGDATAFMT_FLOAT:
    1348           0 :             n = (tmsize_t)((unsigned long)cc /
    1349             :                            sizeof(float)); /* XXX float == 32 bits */
    1350           0 :             break;
    1351           0 :         case PIXARLOGDATAFMT_16BIT:
    1352             :         case PIXARLOGDATAFMT_12BITPICIO:
    1353             :         case PIXARLOGDATAFMT_11BITLOG:
    1354           0 :             n = (tmsize_t)((unsigned long)cc /
    1355             :                            sizeof(uint16_t)); /* XXX uint16_t == 16 bits */
    1356           0 :             break;
    1357           0 :         case PIXARLOGDATAFMT_8BIT:
    1358             :         case PIXARLOGDATAFMT_8BITABGR:
    1359           0 :             n = cc;
    1360           0 :             break;
    1361           0 :         default:
    1362           0 :             TIFFErrorExtR(tif, module,
    1363             :                           "%" PRIu16 " bit input not supported in PixarLog",
    1364           0 :                           td->td_bitspersample);
    1365           0 :             return 0;
    1366             :     }
    1367             : 
    1368           0 :     llen = (tmsize_t)sp->stride * td->td_imagewidth;
    1369             :     /* Check against the number of elements (of size uint16_t) of sp->tbuf */
    1370           0 :     if (n > ((tmsize_t)td->td_rowsperstrip * llen))
    1371             :     {
    1372           0 :         TIFFErrorExtR(tif, module, "Too many input bytes provided");
    1373           0 :         return 0;
    1374             :     }
    1375             : 
    1376           0 :     for (i = 0, up = sp->tbuf; i < n; i += llen, up += llen)
    1377             :     {
    1378           0 :         switch (sp->user_datafmt)
    1379             :         {
    1380           0 :             case PIXARLOGDATAFMT_FLOAT:
    1381           0 :                 horizontalDifferenceF((float *)bp, llen, sp->stride, up,
    1382             :                                       sp->FromLT2);
    1383           0 :                 bp += (unsigned long)llen * sizeof(float);
    1384           0 :                 break;
    1385           0 :             case PIXARLOGDATAFMT_16BIT:
    1386           0 :                 horizontalDifference16((uint16_t *)bp, llen, sp->stride, up,
    1387             :                                        sp->From14);
    1388           0 :                 bp += (unsigned long)llen * sizeof(uint16_t);
    1389           0 :                 break;
    1390           0 :             case PIXARLOGDATAFMT_8BIT:
    1391           0 :                 horizontalDifference8((unsigned char *)bp, llen, sp->stride, up,
    1392             :                                       sp->From8);
    1393           0 :                 bp += (unsigned long)llen * sizeof(unsigned char);
    1394           0 :                 break;
    1395           0 :             default:
    1396           0 :                 TIFFErrorExtR(tif, module,
    1397             :                               "%" PRIu16 " bit input not supported in PixarLog",
    1398           0 :                               td->td_bitspersample);
    1399           0 :                 return 0;
    1400             :         }
    1401             :     }
    1402             : 
    1403           0 :     sp->stream.next_in = (unsigned char *)sp->tbuf;
    1404             :     assert(sizeof(sp->stream.avail_in) == 4); /* if this assert gets raised,
    1405             :          we need to simplify this code to reflect a ZLib that is likely updated
    1406             :          to deal with 8byte memory sizes, though this code will respond
    1407             :          appropriately even before we simplify it */
    1408           0 :     sp->stream.avail_in = (uInt)((unsigned long)n * sizeof(uint16_t));
    1409           0 :     if ((sp->stream.avail_in / sizeof(uint16_t)) != (unsigned long)n)
    1410             :     {
    1411           0 :         TIFFErrorExtR(tif, module, "ZLib cannot deal with buffers this size");
    1412           0 :         return (0);
    1413             :     }
    1414             : 
    1415             :     do
    1416             :     {
    1417           0 :         if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK)
    1418             :         {
    1419           0 :             TIFFErrorExtR(tif, module, "Encoder error: %s",
    1420           0 :                           sp->stream.msg ? sp->stream.msg : "(null)");
    1421           0 :             return (0);
    1422             :         }
    1423           0 :         if (sp->stream.avail_out == 0)
    1424             :         {
    1425           0 :             tif->tif_rawcc = tif->tif_rawdatasize;
    1426           0 :             if (!TIFFFlushData1(tif))
    1427           0 :                 return 0;
    1428           0 :             sp->stream.next_out = tif->tif_rawdata;
    1429           0 :             sp->stream.avail_out =
    1430           0 :                 (uInt)tif
    1431           0 :                     ->tif_rawdatasize; /* this is a safe typecast, as check is
    1432             :                                           made already in PixarLogPreEncode */
    1433             :         }
    1434           0 :     } while (sp->stream.avail_in > 0);
    1435           0 :     return (1);
    1436             : }
    1437             : 
    1438             : /*
    1439             :  * Finish off an encoded strip by flushing the last
    1440             :  * string and tacking on an End Of Information code.
    1441             :  */
    1442             : 
    1443           0 : static int PixarLogPostEncode(TIFF *tif)
    1444             : {
    1445             :     static const char module[] = "PixarLogPostEncode";
    1446           0 :     PixarLogState *sp = PixarLogEncoderState(tif);
    1447             :     int state;
    1448             : 
    1449           0 :     sp->stream.avail_in = 0;
    1450             : 
    1451             :     do
    1452             :     {
    1453           0 :         state = deflate(&sp->stream, Z_FINISH);
    1454           0 :         switch (state)
    1455             :         {
    1456           0 :             case Z_STREAM_END:
    1457             :             case Z_OK:
    1458           0 :                 if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize)
    1459             :                 {
    1460           0 :                     tif->tif_rawcc =
    1461           0 :                         tif->tif_rawdatasize - sp->stream.avail_out;
    1462           0 :                     if (!TIFFFlushData1(tif))
    1463           0 :                         return 0;
    1464           0 :                     sp->stream.next_out = tif->tif_rawdata;
    1465           0 :                     sp->stream.avail_out =
    1466           0 :                         (uInt)tif->tif_rawdatasize; /* this is a safe typecast,
    1467             :                                                        as check is made already
    1468             :                                                        in PixarLogPreEncode */
    1469             :                 }
    1470           0 :                 break;
    1471           0 :             default:
    1472           0 :                 TIFFErrorExtR(tif, module, "ZLib error: %s",
    1473           0 :                               sp->stream.msg ? sp->stream.msg : "(null)");
    1474           0 :                 return (0);
    1475             :         }
    1476           0 :     } while (state != Z_STREAM_END);
    1477           0 :     return (1);
    1478             : }
    1479             : 
    1480           0 : static void PixarLogClose(TIFF *tif)
    1481             : {
    1482           0 :     PixarLogState *sp = (PixarLogState *)tif->tif_data;
    1483           0 :     TIFFDirectory *td = &tif->tif_dir;
    1484             : 
    1485           0 :     assert(sp != 0);
    1486             :     /* In a really sneaky (and really incorrect, and untruthful, and
    1487             :      * troublesome, and error-prone) maneuver that completely goes against
    1488             :      * the spirit of TIFF, and breaks TIFF, on close, we covertly
    1489             :      * modify both bitspersample and sampleformat in the directory to
    1490             :      * indicate 8-bit linear.  This way, the decode "just works" even for
    1491             :      * readers that don't know about PixarLog, or how to set
    1492             :      * the PIXARLOGDATFMT pseudo-tag.
    1493             :      */
    1494             : 
    1495           0 :     if (sp->state & PLSTATE_INIT)
    1496             :     {
    1497             :         /* We test the state to avoid an issue such as in
    1498             :          * http://bugzilla.maptools.org/show_bug.cgi?id=2604
    1499             :          * What appends in that case is that the bitspersample is 1 and
    1500             :          * a TransferFunction is set. The size of the TransferFunction
    1501             :          * depends on 1<<bitspersample. So if we increase it, an access
    1502             :          * out of the buffer will happen at directory flushing.
    1503             :          * Another option would be to clear those targs.
    1504             :          */
    1505           0 :         td->td_bitspersample = 8;
    1506           0 :         td->td_sampleformat = SAMPLEFORMAT_UINT;
    1507             :     }
    1508           0 : }
    1509             : 
    1510           0 : static void PixarLogCleanup(TIFF *tif)
    1511             : {
    1512           0 :     PixarLogState *sp = (PixarLogState *)tif->tif_data;
    1513             : 
    1514           0 :     assert(sp != 0);
    1515             : 
    1516           0 :     (void)TIFFPredictorCleanup(tif);
    1517             : 
    1518           0 :     tif->tif_tagmethods.vgetfield = sp->vgetparent;
    1519           0 :     tif->tif_tagmethods.vsetfield = sp->vsetparent;
    1520             : 
    1521           0 :     if (sp->FromLT2)
    1522           0 :         _TIFFfreeExt(tif, sp->FromLT2);
    1523           0 :     if (sp->From14)
    1524           0 :         _TIFFfreeExt(tif, sp->From14);
    1525           0 :     if (sp->From8)
    1526           0 :         _TIFFfreeExt(tif, sp->From8);
    1527           0 :     if (sp->ToLinearF)
    1528           0 :         _TIFFfreeExt(tif, sp->ToLinearF);
    1529           0 :     if (sp->ToLinear16)
    1530           0 :         _TIFFfreeExt(tif, sp->ToLinear16);
    1531           0 :     if (sp->ToLinear8)
    1532           0 :         _TIFFfreeExt(tif, sp->ToLinear8);
    1533           0 :     if (sp->state & PLSTATE_INIT)
    1534             :     {
    1535           0 :         if (tif->tif_mode == O_RDONLY)
    1536           0 :             inflateEnd(&sp->stream);
    1537             :         else
    1538           0 :             deflateEnd(&sp->stream);
    1539             :     }
    1540           0 :     if (sp->tbuf)
    1541           0 :         _TIFFfreeExt(tif, sp->tbuf);
    1542           0 :     _TIFFfreeExt(tif, sp);
    1543           0 :     tif->tif_data = NULL;
    1544             : 
    1545           0 :     _TIFFSetDefaultCompressionState(tif);
    1546           0 : }
    1547             : 
    1548           0 : static int PixarLogVSetField(TIFF *tif, uint32_t tag, va_list ap)
    1549             : {
    1550             :     static const char module[] = "PixarLogVSetField";
    1551           0 :     PixarLogState *sp = (PixarLogState *)tif->tif_data;
    1552             :     int result;
    1553             : 
    1554           0 :     switch (tag)
    1555             :     {
    1556           0 :         case TIFFTAG_PIXARLOGQUALITY:
    1557           0 :             sp->quality = (int)va_arg(ap, int);
    1558           0 :             if (tif->tif_mode != O_RDONLY && (sp->state & PLSTATE_INIT))
    1559             :             {
    1560           0 :                 if (deflateParams(&sp->stream, sp->quality,
    1561             :                                   Z_DEFAULT_STRATEGY) != Z_OK)
    1562             :                 {
    1563           0 :                     TIFFErrorExtR(tif, module, "ZLib error: %s",
    1564           0 :                                   sp->stream.msg ? sp->stream.msg : "(null)");
    1565           0 :                     return (0);
    1566             :                 }
    1567             :             }
    1568           0 :             return (1);
    1569           0 :         case TIFFTAG_PIXARLOGDATAFMT:
    1570           0 :             sp->user_datafmt = (int)va_arg(ap, int);
    1571             :             /* Tweak the TIFF header so that the rest of libtiff knows what
    1572             :              * size of data will be passed between app and library, and
    1573             :              * assume that the app knows what it is doing and is not
    1574             :              * confused by these header manipulations...
    1575             :              */
    1576           0 :             switch (sp->user_datafmt)
    1577             :             {
    1578           0 :                 case PIXARLOGDATAFMT_8BIT:
    1579             :                 case PIXARLOGDATAFMT_8BITABGR:
    1580           0 :                     TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
    1581           0 :                     TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
    1582           0 :                     break;
    1583           0 :                 case PIXARLOGDATAFMT_11BITLOG:
    1584           0 :                     TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
    1585           0 :                     TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
    1586           0 :                     break;
    1587           0 :                 case PIXARLOGDATAFMT_12BITPICIO:
    1588           0 :                     TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
    1589           0 :                     TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT);
    1590           0 :                     break;
    1591           0 :                 case PIXARLOGDATAFMT_16BIT:
    1592           0 :                     TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
    1593           0 :                     TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
    1594           0 :                     break;
    1595           0 :                 case PIXARLOGDATAFMT_FLOAT:
    1596           0 :                     TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32);
    1597           0 :                     TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT,
    1598             :                                  SAMPLEFORMAT_IEEEFP);
    1599           0 :                     break;
    1600           0 :                 default:
    1601           0 :                     break;
    1602             :             }
    1603             :             /*
    1604             :              * Must recalculate sizes should bits/sample change.
    1605             :              */
    1606           0 :             tif->tif_dir.td_tilesize =
    1607           0 :                 isTiled(tif) ? TIFFTileSize(tif) : (tmsize_t)(-1);
    1608           0 :             tif->tif_dir.td_scanlinesize = TIFFScanlineSize(tif);
    1609           0 :             result = 1; /* NB: pseudo tag */
    1610           0 :             break;
    1611           0 :         default:
    1612           0 :             result = (*sp->vsetparent)(tif, tag, ap);
    1613             :     }
    1614           0 :     return (result);
    1615             : }
    1616             : 
    1617           0 : static int PixarLogVGetField(TIFF *tif, uint32_t tag, va_list ap)
    1618             : {
    1619           0 :     PixarLogState *sp = (PixarLogState *)tif->tif_data;
    1620             : 
    1621           0 :     switch (tag)
    1622             :     {
    1623           0 :         case TIFFTAG_PIXARLOGQUALITY:
    1624           0 :             *va_arg(ap, int *) = sp->quality;
    1625           0 :             break;
    1626           0 :         case TIFFTAG_PIXARLOGDATAFMT:
    1627           0 :             *va_arg(ap, int *) = sp->user_datafmt;
    1628           0 :             break;
    1629           0 :         default:
    1630           0 :             return (*sp->vgetparent)(tif, tag, ap);
    1631             :     }
    1632           0 :     return (1);
    1633             : }
    1634             : 
    1635             : static const TIFFField pixarlogFields[] = {
    1636             :     {TIFFTAG_PIXARLOGDATAFMT, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, FIELD_PSEUDO,
    1637             :      FALSE, FALSE, "", NULL},
    1638             :     {TIFFTAG_PIXARLOGQUALITY, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, FIELD_PSEUDO,
    1639             :      FALSE, FALSE, "", NULL}};
    1640             : 
    1641           0 : static uint64_t PixarLogGetMaxCompressionRatio(TIFF *tif)
    1642             : {
    1643             :     (void)tif;
    1644             :     /* cf https://zlib.net/zlib_tech.html */
    1645           0 :     const uint64_t MAX_DEFLATE_RATIO = 1032;
    1646             : 
    1647             :     /* security margin as I don't understand what this codec does */
    1648           0 :     return MAX_DEFLATE_RATIO * (uint64_t)4;
    1649             : }
    1650             : 
    1651           0 : int TIFFInitPixarLog(TIFF *tif, int scheme)
    1652             : {
    1653             :     static const char module[] = "TIFFInitPixarLog";
    1654             : 
    1655             :     PixarLogState *sp;
    1656             : 
    1657             :     (void)scheme;
    1658           0 :     assert(scheme == COMPRESSION_PIXARLOG);
    1659             : 
    1660             :     /*
    1661             :      * Merge codec-specific tag information.
    1662             :      */
    1663           0 :     if (!_TIFFMergeFields(tif, pixarlogFields, TIFFArrayCount(pixarlogFields)))
    1664             :     {
    1665           0 :         TIFFErrorExtR(tif, module,
    1666             :                       "Merging PixarLog codec-specific tags failed");
    1667           0 :         return 0;
    1668             :     }
    1669             : 
    1670             :     /*
    1671             :      * Allocate state block so tag methods have storage to record values.
    1672             :      */
    1673           0 :     tif->tif_data = (uint8_t *)_TIFFmallocExt(tif, sizeof(PixarLogState));
    1674           0 :     if (tif->tif_data == NULL)
    1675           0 :         goto bad;
    1676           0 :     sp = (PixarLogState *)tif->tif_data;
    1677           0 :     _TIFFmemset(sp, 0, sizeof(*sp));
    1678           0 :     sp->stream.data_type = Z_BINARY;
    1679           0 :     sp->user_datafmt = PIXARLOGDATAFMT_UNKNOWN;
    1680             : 
    1681             :     /*
    1682             :      * Install codec methods.
    1683             :      */
    1684           0 :     tif->tif_fixuptags = PixarLogFixupTags;
    1685           0 :     tif->tif_setupdecode = PixarLogSetupDecode;
    1686           0 :     tif->tif_predecode = PixarLogPreDecode;
    1687           0 :     tif->tif_decoderow = PixarLogDecode;
    1688           0 :     tif->tif_decodestrip = PixarLogDecode;
    1689           0 :     tif->tif_decodetile = PixarLogDecode;
    1690           0 :     tif->tif_setupencode = PixarLogSetupEncode;
    1691           0 :     tif->tif_preencode = PixarLogPreEncode;
    1692           0 :     tif->tif_postencode = PixarLogPostEncode;
    1693           0 :     tif->tif_encoderow = PixarLogEncode;
    1694           0 :     tif->tif_encodestrip = PixarLogEncode;
    1695           0 :     tif->tif_encodetile = PixarLogEncode;
    1696           0 :     tif->tif_close = PixarLogClose;
    1697           0 :     tif->tif_cleanup = PixarLogCleanup;
    1698           0 :     tif->tif_getmaxcompressionratio = PixarLogGetMaxCompressionRatio;
    1699             : 
    1700             :     /* Override SetField so we can handle our private pseudo-tag */
    1701           0 :     sp->vgetparent = tif->tif_tagmethods.vgetfield;
    1702           0 :     tif->tif_tagmethods.vgetfield = PixarLogVGetField; /* hook for codec tags */
    1703           0 :     sp->vsetparent = tif->tif_tagmethods.vsetfield;
    1704           0 :     tif->tif_tagmethods.vsetfield = PixarLogVSetField; /* hook for codec tags */
    1705             : 
    1706             :     /* Default values for codec-specific fields */
    1707           0 :     sp->quality = Z_DEFAULT_COMPRESSION; /* default comp. level */
    1708           0 :     sp->state = 0;
    1709             : 
    1710             :     /* we don't wish to use the predictor,
    1711             :      * the default is none, which predictor value 1
    1712             :      */
    1713           0 :     (void)TIFFPredictorInit(tif);
    1714             : 
    1715             :     /*
    1716             :      * build the companding tables
    1717             :      */
    1718           0 :     PixarLogMakeTables(tif, sp);
    1719             : 
    1720           0 :     return (1);
    1721           0 : bad:
    1722           0 :     TIFFErrorExtR(tif, module, "No space for PixarLog state block");
    1723           0 :     return (0);
    1724             : }
    1725             : #endif /* PIXARLOG_SUPPORT */

Generated by: LCOV version 1.14