Coverage Report

Created: 2026-02-14 06:52

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