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