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 895 0.0 %
Date: 2024-11-25 23:50:41 Functions: 0 26 0.0 %

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

Generated by: LCOV version 1.14