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