opencv

Форк
0
/
tif_pixarlog.c 
1670 строк · 53.9 Кб
1
/*
2
 * Copyright (c) 1996-1997 Sam Leffler
3
 * Copyright (c) 1996 Pixar
4
 *
5
 * Permission to use, copy, modify, distribute, and sell this software and
6
 * its documentation for any purpose is hereby granted without fee, provided
7
 * that (i) the above copyright notices and this permission notice appear in
8
 * all copies of the software and related documentation, and (ii) the names of
9
 * Pixar, Sam Leffler and Silicon Graphics may not be used in any advertising or
10
 * publicity relating to the software without the specific, prior written
11
 * permission of Pixar, Sam Leffler and Silicon Graphics.
12
 *
13
 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
14
 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
15
 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
16
 *
17
 * IN NO EVENT SHALL PIXAR, SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
18
 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
19
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20
 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
21
 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
22
 * OF THIS SOFTWARE.
23
 */
24

25
#include "tiffiop.h"
26
#ifdef PIXARLOG_SUPPORT
27

28
/*
29
 * TIFF Library.
30
 * PixarLog Compression Support
31
 *
32
 * Contributed by Dan McCoy.
33
 *
34
 * PixarLog film support uses the TIFF library to store companded
35
 * 11 bit values into a tiff file, which are compressed using the
36
 * zip compressor.
37
 *
38
 * The codec can take as input and produce as output 32-bit IEEE float values
39
 * as well as 16-bit or 8-bit unsigned integer values.
40
 *
41
 * On writing any of the above are converted into the internal
42
 * 11-bit log format.   In the case of  8 and 16 bit values, the
43
 * input is assumed to be unsigned linear color values that represent
44
 * the range 0-1.  In the case of IEEE values, the 0-1 range is assumed to
45
 * be the normal linear color range, in addition over 1 values are
46
 * accepted up to a value of about 25.0 to encode "hot" highlights and such.
47
 * The encoding is lossless for 8-bit values, slightly lossy for the
48
 * other bit depths.  The actual color precision should be better
49
 * than the human eye can perceive with extra room to allow for
50
 * error introduced by further image computation.  As with any quantized
51
 * color format, it is possible to perform image calculations which
52
 * expose the quantization error. This format should certainly be less
53
 * susceptible to such errors than standard 8-bit encodings, but more
54
 * susceptible than straight 16-bit or 32-bit encodings.
55
 *
56
 * On reading the internal format is converted to the desired output format.
57
 * The program can request which format it desires by setting the internal
58
 * pseudo tag TIFFTAG_PIXARLOGDATAFMT to one of these possible values:
59
 *  PIXARLOGDATAFMT_FLOAT     = provide IEEE float values.
60
 *  PIXARLOGDATAFMT_16BIT     = provide unsigned 16-bit integer values
61
 *  PIXARLOGDATAFMT_8BIT      = provide unsigned 8-bit integer values
62
 *
63
 * alternately PIXARLOGDATAFMT_8BITABGR provides unsigned 8-bit integer
64
 * values with the difference that if there are exactly three or four channels
65
 * (rgb or rgba) it swaps the channel order (bgr or abgr).
66
 *
67
 * PIXARLOGDATAFMT_11BITLOG provides the internal encoding directly
68
 * packed in 16-bit values.   However no tools are supplied for interpreting
69
 * these values.
70
 *
71
 * "hot" (over 1.0) areas written in floating point get clamped to
72
 * 1.0 in the integer data types.
73
 *
74
 * When the file is closed after writing, the bit depth and sample format
75
 * are set always to appear as if 8-bit data has been written into it.
76
 * That way a naive program unaware of the particulars of the encoding
77
 * gets the format it is most likely able to handle.
78
 *
79
 * The codec does it's own horizontal differencing step on the coded
80
 * values so the libraries predictor stuff should be turned off.
81
 * The codec also handle byte swapping the encoded values as necessary
82
 * since the library does not have the information necessary
83
 * to know the bit depth of the raw unencoded buffer.
84
 *
85
 * NOTE: This decoder does not appear to update tif_rawcp, and tif_rawcc.
86
 * This can cause problems with the implementation of CHUNKY_STRIP_READ_SUPPORT
87
 * as noted in http://trac.osgeo.org/gdal/ticket/3894.   FrankW - Jan'11
88
 */
89

90
#include "tif_predict.h"
91
#include "zlib.h"
92

93
#include <math.h>
94
#include <stdio.h>
95
#include <stdlib.h>
96

97
/* Tables for converting to/from 11 bit coded values */
98

99
#define TSIZE 2048   /* decode table size (11-bit tokens) */
100
#define TSIZEP1 2049 /* Plus one for slop */
101
#define ONE 1250     /* token value of 1.0 exactly */
102
#define RATIO 1.004  /* nominal ratio for log part */
103

104
#define CODE_MASK 0x7ff /* 11 bits. */
105

106
static float Fltsize;
107
static float LogK1, LogK2;
108

109
#define REPEAT(n, op)                                                          \
110
    {                                                                          \
111
        int i;                                                                 \
112
        i = n;                                                                 \
113
        do                                                                     \
114
        {                                                                      \
115
            i--;                                                               \
116
            op;                                                                \
117
        } while (i > 0);                                                       \
118
    }
119

120
static void horizontalAccumulateF(uint16_t *wp, int n, int stride, float *op,
121
                                  float *ToLinearF)
122
{
123
    register unsigned int cr, cg, cb, ca, mask;
124
    register float t0, t1, t2, t3;
125

126
    if (n >= stride)
127
    {
128
        mask = CODE_MASK;
129
        if (stride == 3)
130
        {
131
            t0 = ToLinearF[cr = (wp[0] & mask)];
132
            t1 = ToLinearF[cg = (wp[1] & mask)];
133
            t2 = ToLinearF[cb = (wp[2] & mask)];
134
            op[0] = t0;
135
            op[1] = t1;
136
            op[2] = t2;
137
            n -= 3;
138
            while (n > 0)
139
            {
140
                wp += 3;
141
                op += 3;
142
                n -= 3;
143
                t0 = ToLinearF[(cr += wp[0]) & mask];
144
                t1 = ToLinearF[(cg += wp[1]) & mask];
145
                t2 = ToLinearF[(cb += wp[2]) & mask];
146
                op[0] = t0;
147
                op[1] = t1;
148
                op[2] = t2;
149
            }
150
        }
151
        else if (stride == 4)
152
        {
153
            t0 = ToLinearF[cr = (wp[0] & mask)];
154
            t1 = ToLinearF[cg = (wp[1] & mask)];
155
            t2 = ToLinearF[cb = (wp[2] & mask)];
156
            t3 = ToLinearF[ca = (wp[3] & mask)];
157
            op[0] = t0;
158
            op[1] = t1;
159
            op[2] = t2;
160
            op[3] = t3;
161
            n -= 4;
162
            while (n > 0)
163
            {
164
                wp += 4;
165
                op += 4;
166
                n -= 4;
167
                t0 = ToLinearF[(cr += wp[0]) & mask];
168
                t1 = ToLinearF[(cg += wp[1]) & mask];
169
                t2 = ToLinearF[(cb += wp[2]) & mask];
170
                t3 = ToLinearF[(ca += wp[3]) & mask];
171
                op[0] = t0;
172
                op[1] = t1;
173
                op[2] = t2;
174
                op[3] = t3;
175
            }
176
        }
177
        else
178
        {
179
            REPEAT(stride, *op = ToLinearF[*wp & mask]; wp++; op++)
180
            n -= stride;
181
            while (n > 0)
182
            {
183
                REPEAT(stride, wp[stride] += *wp; *op = ToLinearF[*wp & mask];
184
                       wp++; op++)
185
                n -= stride;
186
            }
187
        }
188
    }
189
}
190

191
static void horizontalAccumulate12(uint16_t *wp, int n, int stride, int16_t *op,
192
                                   float *ToLinearF)
193
{
194
    register unsigned int cr, cg, cb, ca, mask;
195
    register float t0, t1, t2, t3;
196

197
#define SCALE12 2048.0F
198
#define CLAMP12(t) (((t) < 3071) ? (uint16_t)(t) : 3071)
199

200
    if (n >= stride)
201
    {
202
        mask = CODE_MASK;
203
        if (stride == 3)
204
        {
205
            t0 = ToLinearF[cr = (wp[0] & mask)] * SCALE12;
206
            t1 = ToLinearF[cg = (wp[1] & mask)] * SCALE12;
207
            t2 = ToLinearF[cb = (wp[2] & mask)] * SCALE12;
208
            op[0] = CLAMP12(t0);
209
            op[1] = CLAMP12(t1);
210
            op[2] = CLAMP12(t2);
211
            n -= 3;
212
            while (n > 0)
213
            {
214
                wp += 3;
215
                op += 3;
216
                n -= 3;
217
                t0 = ToLinearF[(cr += wp[0]) & mask] * SCALE12;
218
                t1 = ToLinearF[(cg += wp[1]) & mask] * SCALE12;
219
                t2 = ToLinearF[(cb += wp[2]) & mask] * SCALE12;
220
                op[0] = CLAMP12(t0);
221
                op[1] = CLAMP12(t1);
222
                op[2] = CLAMP12(t2);
223
            }
224
        }
225
        else if (stride == 4)
226
        {
227
            t0 = ToLinearF[cr = (wp[0] & mask)] * SCALE12;
228
            t1 = ToLinearF[cg = (wp[1] & mask)] * SCALE12;
229
            t2 = ToLinearF[cb = (wp[2] & mask)] * SCALE12;
230
            t3 = ToLinearF[ca = (wp[3] & mask)] * SCALE12;
231
            op[0] = CLAMP12(t0);
232
            op[1] = CLAMP12(t1);
233
            op[2] = CLAMP12(t2);
234
            op[3] = CLAMP12(t3);
235
            n -= 4;
236
            while (n > 0)
237
            {
238
                wp += 4;
239
                op += 4;
240
                n -= 4;
241
                t0 = ToLinearF[(cr += wp[0]) & mask] * SCALE12;
242
                t1 = ToLinearF[(cg += wp[1]) & mask] * SCALE12;
243
                t2 = ToLinearF[(cb += wp[2]) & mask] * SCALE12;
244
                t3 = ToLinearF[(ca += wp[3]) & mask] * SCALE12;
245
                op[0] = CLAMP12(t0);
246
                op[1] = CLAMP12(t1);
247
                op[2] = CLAMP12(t2);
248
                op[3] = CLAMP12(t3);
249
            }
250
        }
251
        else
252
        {
253
            REPEAT(stride, t0 = ToLinearF[*wp & mask] * SCALE12;
254
                   *op = CLAMP12(t0); wp++; op++)
255
            n -= stride;
256
            while (n > 0)
257
            {
258
                REPEAT(stride, wp[stride] += *wp;
259
                       t0 = ToLinearF[wp[stride] & mask] * SCALE12;
260
                       *op = CLAMP12(t0); wp++; op++)
261
                n -= stride;
262
            }
263
        }
264
    }
265
}
266

267
static void horizontalAccumulate16(uint16_t *wp, int n, int stride,
268
                                   uint16_t *op, uint16_t *ToLinear16)
269
{
270
    register unsigned int cr, cg, cb, ca, mask;
271

272
    if (n >= stride)
273
    {
274
        mask = CODE_MASK;
275
        if (stride == 3)
276
        {
277
            op[0] = ToLinear16[cr = (wp[0] & mask)];
278
            op[1] = ToLinear16[cg = (wp[1] & mask)];
279
            op[2] = ToLinear16[cb = (wp[2] & mask)];
280
            n -= 3;
281
            while (n > 0)
282
            {
283
                wp += 3;
284
                op += 3;
285
                n -= 3;
286
                op[0] = ToLinear16[(cr += wp[0]) & mask];
287
                op[1] = ToLinear16[(cg += wp[1]) & mask];
288
                op[2] = ToLinear16[(cb += wp[2]) & mask];
289
            }
290
        }
291
        else if (stride == 4)
292
        {
293
            op[0] = ToLinear16[cr = (wp[0] & mask)];
294
            op[1] = ToLinear16[cg = (wp[1] & mask)];
295
            op[2] = ToLinear16[cb = (wp[2] & mask)];
296
            op[3] = ToLinear16[ca = (wp[3] & mask)];
297
            n -= 4;
298
            while (n > 0)
299
            {
300
                wp += 4;
301
                op += 4;
302
                n -= 4;
303
                op[0] = ToLinear16[(cr += wp[0]) & mask];
304
                op[1] = ToLinear16[(cg += wp[1]) & mask];
305
                op[2] = ToLinear16[(cb += wp[2]) & mask];
306
                op[3] = ToLinear16[(ca += wp[3]) & mask];
307
            }
308
        }
309
        else
310
        {
311
            REPEAT(stride, *op = ToLinear16[*wp & mask]; wp++; op++)
312
            n -= stride;
313
            while (n > 0)
314
            {
315
                REPEAT(stride, wp[stride] += *wp; *op = ToLinear16[*wp & mask];
316
                       wp++; op++)
317
                n -= stride;
318
            }
319
        }
320
    }
321
}
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
{
330
    register unsigned int cr, cg, cb, ca, mask;
331

332
    if (n >= stride)
333
    {
334
        mask = CODE_MASK;
335
        if (stride == 3)
336
        {
337
            op[0] = wp[0];
338
            op[1] = wp[1];
339
            op[2] = wp[2];
340
            cr = wp[0];
341
            cg = wp[1];
342
            cb = wp[2];
343
            n -= 3;
344
            while (n > 0)
345
            {
346
                wp += 3;
347
                op += 3;
348
                n -= 3;
349
                op[0] = (uint16_t)((cr += wp[0]) & mask);
350
                op[1] = (uint16_t)((cg += wp[1]) & mask);
351
                op[2] = (uint16_t)((cb += wp[2]) & mask);
352
            }
353
        }
354
        else if (stride == 4)
355
        {
356
            op[0] = wp[0];
357
            op[1] = wp[1];
358
            op[2] = wp[2];
359
            op[3] = wp[3];
360
            cr = wp[0];
361
            cg = wp[1];
362
            cb = wp[2];
363
            ca = wp[3];
364
            n -= 4;
365
            while (n > 0)
366
            {
367
                wp += 4;
368
                op += 4;
369
                n -= 4;
370
                op[0] = (uint16_t)((cr += wp[0]) & mask);
371
                op[1] = (uint16_t)((cg += wp[1]) & mask);
372
                op[2] = (uint16_t)((cb += wp[2]) & mask);
373
                op[3] = (uint16_t)((ca += wp[3]) & mask);
374
            }
375
        }
376
        else
377
        {
378
            REPEAT(stride, *op = *wp & mask; wp++; op++)
379
            n -= stride;
380
            while (n > 0)
381
            {
382
                REPEAT(stride, wp[stride] += *wp; *op = *wp & mask; wp++; op++)
383
                n -= stride;
384
            }
385
        }
386
    }
387
}
388

389
static void horizontalAccumulate8(uint16_t *wp, int n, int stride,
390
                                  unsigned char *op, unsigned char *ToLinear8)
391
{
392
    register unsigned int cr, cg, cb, ca, mask;
393

394
    if (n >= stride)
395
    {
396
        mask = CODE_MASK;
397
        if (stride == 3)
398
        {
399
            op[0] = ToLinear8[cr = (wp[0] & mask)];
400
            op[1] = ToLinear8[cg = (wp[1] & mask)];
401
            op[2] = ToLinear8[cb = (wp[2] & mask)];
402
            n -= 3;
403
            while (n > 0)
404
            {
405
                n -= 3;
406
                wp += 3;
407
                op += 3;
408
                op[0] = ToLinear8[(cr += wp[0]) & mask];
409
                op[1] = ToLinear8[(cg += wp[1]) & mask];
410
                op[2] = ToLinear8[(cb += wp[2]) & mask];
411
            }
412
        }
413
        else if (stride == 4)
414
        {
415
            op[0] = ToLinear8[cr = (wp[0] & mask)];
416
            op[1] = ToLinear8[cg = (wp[1] & mask)];
417
            op[2] = ToLinear8[cb = (wp[2] & mask)];
418
            op[3] = ToLinear8[ca = (wp[3] & mask)];
419
            n -= 4;
420
            while (n > 0)
421
            {
422
                n -= 4;
423
                wp += 4;
424
                op += 4;
425
                op[0] = ToLinear8[(cr += wp[0]) & mask];
426
                op[1] = ToLinear8[(cg += wp[1]) & mask];
427
                op[2] = ToLinear8[(cb += wp[2]) & mask];
428
                op[3] = ToLinear8[(ca += wp[3]) & mask];
429
            }
430
        }
431
        else
432
        {
433
            REPEAT(stride, *op = ToLinear8[*wp & mask]; wp++; op++)
434
            n -= stride;
435
            while (n > 0)
436
            {
437
                REPEAT(stride, wp[stride] += *wp; *op = ToLinear8[*wp & mask];
438
                       wp++; op++)
439
                n -= stride;
440
            }
441
        }
442
    }
443
}
444

445
static void horizontalAccumulate8abgr(uint16_t *wp, int n, int stride,
446
                                      unsigned char *op,
447
                                      unsigned char *ToLinear8)
448
{
449
    register unsigned int cr, cg, cb, ca, mask;
450
    register unsigned char t0, t1, t2, t3;
451

452
    if (n >= stride)
453
    {
454
        mask = CODE_MASK;
455
        if (stride == 3)
456
        {
457
            op[0] = 0;
458
            t1 = ToLinear8[cb = (wp[2] & mask)];
459
            t2 = ToLinear8[cg = (wp[1] & mask)];
460
            t3 = ToLinear8[cr = (wp[0] & mask)];
461
            op[1] = t1;
462
            op[2] = t2;
463
            op[3] = t3;
464
            n -= 3;
465
            while (n > 0)
466
            {
467
                n -= 3;
468
                wp += 3;
469
                op += 4;
470
                op[0] = 0;
471
                t1 = ToLinear8[(cb += wp[2]) & mask];
472
                t2 = ToLinear8[(cg += wp[1]) & mask];
473
                t3 = ToLinear8[(cr += wp[0]) & mask];
474
                op[1] = t1;
475
                op[2] = t2;
476
                op[3] = t3;
477
            }
478
        }
479
        else if (stride == 4)
480
        {
481
            t0 = ToLinear8[ca = (wp[3] & mask)];
482
            t1 = ToLinear8[cb = (wp[2] & mask)];
483
            t2 = ToLinear8[cg = (wp[1] & mask)];
484
            t3 = ToLinear8[cr = (wp[0] & mask)];
485
            op[0] = t0;
486
            op[1] = t1;
487
            op[2] = t2;
488
            op[3] = t3;
489
            n -= 4;
490
            while (n > 0)
491
            {
492
                n -= 4;
493
                wp += 4;
494
                op += 4;
495
                t0 = ToLinear8[(ca += wp[3]) & mask];
496
                t1 = ToLinear8[(cb += wp[2]) & mask];
497
                t2 = ToLinear8[(cg += wp[1]) & mask];
498
                t3 = ToLinear8[(cr += wp[0]) & mask];
499
                op[0] = t0;
500
                op[1] = t1;
501
                op[2] = t2;
502
                op[3] = t3;
503
            }
504
        }
505
        else
506
        {
507
            REPEAT(stride, *op = ToLinear8[*wp & mask]; wp++; op++)
508
            n -= stride;
509
            while (n > 0)
510
            {
511
                REPEAT(stride, wp[stride] += *wp; *op = ToLinear8[*wp & mask];
512
                       wp++; op++)
513
                n -= stride;
514
            }
515
        }
516
    }
517
}
518

519
/*
520
 * State block for each open TIFF
521
 * file using PixarLog compression/decompression.
522
 */
523
typedef struct
524
{
525
    TIFFPredictorState predict;
526
    z_stream stream;
527
    tmsize_t tbuf_size; /* only set/used on reading for now */
528
    uint16_t *tbuf;
529
    uint16_t stride;
530
    int state;
531
    int user_datafmt;
532
    int quality;
533
#define PLSTATE_INIT 1
534

535
    TIFFVSetMethod vgetparent; /* super-class method */
536
    TIFFVSetMethod vsetparent; /* super-class method */
537

538
    float *ToLinearF;
539
    uint16_t *ToLinear16;
540
    unsigned char *ToLinear8;
541
    uint16_t *FromLT2;
542
    uint16_t *From14; /* Really for 16-bit data, but we shift down 2 */
543
    uint16_t *From8;
544

545
} PixarLogState;
546

547
static int PixarLogMakeTables(TIFF *tif, PixarLogState *sp)
548
{
549

550
    /*
551
     *    We make several tables here to convert between various external
552
     *    representations (float, 16-bit, and 8-bit) and the internal
553
     *    11-bit companded representation.  The 11-bit representation has two
554
     *    distinct regions.  A linear bottom end up through .018316 in steps
555
     *    of about .000073, and a region of constant ratio up to about 25.
556
     *    These floating point numbers are stored in the main table ToLinearF.
557
     *    All other tables are derived from this one.  The tables (and the
558
     *    ratios) are continuous at the internal seam.
559
     */
560

561
    int nlin, lt2size;
562
    int i, j;
563
    double b, c, linstep, v;
564
    float *ToLinearF;
565
    uint16_t *ToLinear16;
566
    unsigned char *ToLinear8;
567
    uint16_t *FromLT2;
568
    uint16_t *From14; /* Really for 16-bit data, but we shift down 2 */
569
    uint16_t *From8;
570

571
    c = log(RATIO);
572
    nlin = (int)(1. / c); /* nlin must be an integer */
573
    c = 1. / nlin;
574
    b = exp(-c * ONE); /* multiplicative scale factor [b*exp(c*ONE) = 1] */
575
    linstep = b * c * exp(1.);
576

577
    LogK1 = (float)(1. / c); /* if (v >= 2)  token = k1*log(v*k2) */
578
    LogK2 = (float)(1. / b);
579
    lt2size = (int)(2. / linstep) + 1;
580
    FromLT2 = (uint16_t *)_TIFFmallocExt(tif, lt2size * sizeof(uint16_t));
581
    From14 = (uint16_t *)_TIFFmallocExt(tif, 16384 * sizeof(uint16_t));
582
    From8 = (uint16_t *)_TIFFmallocExt(tif, 256 * sizeof(uint16_t));
583
    ToLinearF = (float *)_TIFFmallocExt(tif, TSIZEP1 * sizeof(float));
584
    ToLinear16 = (uint16_t *)_TIFFmallocExt(tif, TSIZEP1 * sizeof(uint16_t));
585
    ToLinear8 =
586
        (unsigned char *)_TIFFmallocExt(tif, TSIZEP1 * sizeof(unsigned char));
587
    if (FromLT2 == NULL || From14 == NULL || From8 == NULL ||
588
        ToLinearF == NULL || ToLinear16 == NULL || ToLinear8 == NULL)
589
    {
590
        if (FromLT2)
591
            _TIFFfreeExt(tif, FromLT2);
592
        if (From14)
593
            _TIFFfreeExt(tif, From14);
594
        if (From8)
595
            _TIFFfreeExt(tif, From8);
596
        if (ToLinearF)
597
            _TIFFfreeExt(tif, ToLinearF);
598
        if (ToLinear16)
599
            _TIFFfreeExt(tif, ToLinear16);
600
        if (ToLinear8)
601
            _TIFFfreeExt(tif, ToLinear8);
602
        sp->FromLT2 = NULL;
603
        sp->From14 = NULL;
604
        sp->From8 = NULL;
605
        sp->ToLinearF = NULL;
606
        sp->ToLinear16 = NULL;
607
        sp->ToLinear8 = NULL;
608
        return 0;
609
    }
610

611
    j = 0;
612

613
    for (i = 0; i < nlin; i++)
614
    {
615
        v = i * linstep;
616
        ToLinearF[j++] = (float)v;
617
    }
618

619
    for (i = nlin; i < TSIZE; i++)
620
        ToLinearF[j++] = (float)(b * exp(c * i));
621

622
    ToLinearF[2048] = ToLinearF[2047];
623

624
    for (i = 0; i < TSIZEP1; i++)
625
    {
626
        v = ToLinearF[i] * 65535.0 + 0.5;
627
        ToLinear16[i] = (v > 65535.0) ? 65535 : (uint16_t)v;
628
        v = ToLinearF[i] * 255.0 + 0.5;
629
        ToLinear8[i] = (v > 255.0) ? 255 : (unsigned char)v;
630
    }
631

632
    j = 0;
633
    for (i = 0; i < lt2size; i++)
634
    {
635
        if ((i * linstep) * (i * linstep) > ToLinearF[j] * ToLinearF[j + 1])
636
            j++;
637
        FromLT2[i] = (uint16_t)j;
638
    }
639

640
    /*
641
     * Since we lose info anyway on 16-bit data, we set up a 14-bit
642
     * table and shift 16-bit values down two bits on input.
643
     * saves a little table space.
644
     */
645
    j = 0;
646
    for (i = 0; i < 16384; i++)
647
    {
648
        while ((i / 16383.) * (i / 16383.) > ToLinearF[j] * ToLinearF[j + 1])
649
            j++;
650
        From14[i] = (uint16_t)j;
651
    }
652

653
    j = 0;
654
    for (i = 0; i < 256; i++)
655
    {
656
        while ((i / 255.) * (i / 255.) > ToLinearF[j] * ToLinearF[j + 1])
657
            j++;
658
        From8[i] = (uint16_t)j;
659
    }
660

661
    Fltsize = (float)(lt2size / 2);
662

663
    sp->ToLinearF = ToLinearF;
664
    sp->ToLinear16 = ToLinear16;
665
    sp->ToLinear8 = ToLinear8;
666
    sp->FromLT2 = FromLT2;
667
    sp->From14 = From14;
668
    sp->From8 = From8;
669

670
    return 1;
671
}
672

673
#define DecoderState(tif) ((PixarLogState *)(tif)->tif_data)
674
#define EncoderState(tif) ((PixarLogState *)(tif)->tif_data)
675

676
static int PixarLogEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s);
677
static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s);
678

679
#define PIXARLOGDATAFMT_UNKNOWN -1
680

681
static int PixarLogGuessDataFmt(TIFFDirectory *td)
682
{
683
    int guess = PIXARLOGDATAFMT_UNKNOWN;
684
    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
    switch (td->td_bitspersample)
690
    {
691
        case 32:
692
            if (format == SAMPLEFORMAT_IEEEFP)
693
                guess = PIXARLOGDATAFMT_FLOAT;
694
            break;
695
        case 16:
696
            if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT)
697
                guess = PIXARLOGDATAFMT_16BIT;
698
            break;
699
        case 12:
700
            if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_INT)
701
                guess = PIXARLOGDATAFMT_12BITPICIO;
702
            break;
703
        case 11:
704
            if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT)
705
                guess = PIXARLOGDATAFMT_11BITLOG;
706
            break;
707
        case 8:
708
            if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT)
709
                guess = PIXARLOGDATAFMT_8BIT;
710
            break;
711
    }
712

713
    return guess;
714
}
715

716
static tmsize_t multiply_ms(tmsize_t m1, tmsize_t m2)
717
{
718
    return _TIFFMultiplySSize(NULL, m1, m2, NULL);
719
}
720

721
static tmsize_t add_ms(tmsize_t m1, tmsize_t m2)
722
{
723
    assert(m1 >= 0 && m2 >= 0);
724
    /* if either input is zero, assume overflow already occurred */
725
    if (m1 == 0 || m2 == 0)
726
        return 0;
727
    else if (m1 > TIFF_TMSIZE_T_MAX - m2)
728
        return 0;
729

730
    return m1 + m2;
731
}
732

733
static int PixarLogFixupTags(TIFF *tif)
734
{
735
    (void)tif;
736
    return (1);
737
}
738

739
static int PixarLogSetupDecode(TIFF *tif)
740
{
741
    static const char module[] = "PixarLogSetupDecode";
742
    TIFFDirectory *td = &tif->tif_dir;
743
    PixarLogState *sp = DecoderState(tif);
744
    tmsize_t tbuf_size;
745
    uint32_t strip_height;
746

747
    assert(sp != NULL);
748

749
    /* This function can possibly be called several times by */
750
    /* PredictorSetupDecode() if this function succeeds but */
751
    /* PredictorSetup() fails */
752
    if ((sp->state & PLSTATE_INIT) != 0)
753
        return 1;
754

755
    strip_height = td->td_rowsperstrip;
756
    if (strip_height > td->td_imagelength)
757
        strip_height = td->td_imagelength;
758

759
    /* Make sure no byte swapping happens on the data
760
     * after decompression. */
761
    tif->tif_postdecode = _TIFFNoPostDecode;
762

763
    /* for some reason, we can't do this in TIFFInitPixarLog */
764

765
    sp->stride =
766
        (td->td_planarconfig == PLANARCONFIG_CONTIG ? td->td_samplesperpixel
767
                                                    : 1);
768
    tbuf_size = multiply_ms(
769
        multiply_ms(multiply_ms(sp->stride, td->td_imagewidth), strip_height),
770
        sizeof(uint16_t));
771
    /* add one more stride in case input ends mid-stride */
772
    tbuf_size = add_ms(tbuf_size, sizeof(uint16_t) * sp->stride);
773
    if (tbuf_size == 0)
774
        return (0); /* TODO: this is an error return without error report
775
                       through TIFFErrorExt */
776
    sp->tbuf = (uint16_t *)_TIFFmallocExt(tif, tbuf_size);
777
    if (sp->tbuf == NULL)
778
        return (0);
779
    sp->tbuf_size = tbuf_size;
780
    if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN)
781
        sp->user_datafmt = PixarLogGuessDataFmt(td);
782
    if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN)
783
    {
784
        _TIFFfreeExt(tif, sp->tbuf);
785
        sp->tbuf = NULL;
786
        sp->tbuf_size = 0;
787
        TIFFErrorExtR(tif, module,
788
                      "PixarLog compression can't handle bits depth/data "
789
                      "format combination (depth: %" PRIu16 ")",
790
                      td->td_bitspersample);
791
        return (0);
792
    }
793

794
    if (inflateInit(&sp->stream) != Z_OK)
795
    {
796
        _TIFFfreeExt(tif, sp->tbuf);
797
        sp->tbuf = NULL;
798
        sp->tbuf_size = 0;
799
        TIFFErrorExtR(tif, module, "%s",
800
                      sp->stream.msg ? sp->stream.msg : "(null)");
801
        return (0);
802
    }
803
    else
804
    {
805
        sp->state |= PLSTATE_INIT;
806
        return (1);
807
    }
808
}
809

810
/*
811
 * Setup state for decoding a strip.
812
 */
813
static int PixarLogPreDecode(TIFF *tif, uint16_t s)
814
{
815
    static const char module[] = "PixarLogPreDecode";
816
    PixarLogState *sp = DecoderState(tif);
817

818
    (void)s;
819
    assert(sp != NULL);
820
    sp->stream.next_in = tif->tif_rawdata;
821
    assert(sizeof(sp->stream.avail_in) == 4); /* if this assert gets raised,
822
         we need to simplify this code to reflect a ZLib that is likely updated
823
         to deal with 8byte memory sizes, though this code will respond
824
         appropriately even before we simplify it */
825
    sp->stream.avail_in = (uInt)tif->tif_rawcc;
826
    if ((tmsize_t)sp->stream.avail_in != tif->tif_rawcc)
827
    {
828
        TIFFErrorExtR(tif, module, "ZLib cannot deal with buffers this size");
829
        return (0);
830
    }
831
    return (inflateReset(&sp->stream) == Z_OK);
832
}
833

834
static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
835
{
836
    static const char module[] = "PixarLogDecode";
837
    TIFFDirectory *td = &tif->tif_dir;
838
    PixarLogState *sp = DecoderState(tif);
839
    tmsize_t i;
840
    tmsize_t nsamples;
841
    int llen;
842
    uint16_t *up;
843

844
    switch (sp->user_datafmt)
845
    {
846
        case PIXARLOGDATAFMT_FLOAT:
847
            nsamples = occ / sizeof(float); /* XXX float == 32 bits */
848
            break;
849
        case PIXARLOGDATAFMT_16BIT:
850
        case PIXARLOGDATAFMT_12BITPICIO:
851
        case PIXARLOGDATAFMT_11BITLOG:
852
            nsamples = occ / sizeof(uint16_t); /* XXX uint16_t == 16 bits */
853
            break;
854
        case PIXARLOGDATAFMT_8BIT:
855
        case PIXARLOGDATAFMT_8BITABGR:
856
            nsamples = occ;
857
            break;
858
        default:
859
            TIFFErrorExtR(tif, module,
860
                          "%" PRIu16 " bit input not supported in PixarLog",
861
                          td->td_bitspersample);
862
            return 0;
863
    }
864

865
    llen = sp->stride * td->td_imagewidth;
866

867
    (void)s;
868
    assert(sp != NULL);
869

870
    sp->stream.next_in = tif->tif_rawcp;
871
    sp->stream.avail_in = (uInt)tif->tif_rawcc;
872

873
    sp->stream.next_out = (unsigned char *)sp->tbuf;
874
    assert(sizeof(sp->stream.avail_out) == 4); /* if this assert gets raised,
875
         we need to simplify this code to reflect a ZLib that is likely updated
876
         to deal with 8byte memory sizes, though this code will respond
877
         appropriately even before we simplify it */
878
    sp->stream.avail_out = (uInt)(nsamples * sizeof(uint16_t));
879
    if (sp->stream.avail_out != nsamples * sizeof(uint16_t))
880
    {
881
        TIFFErrorExtR(tif, module, "ZLib cannot deal with buffers this size");
882
        return (0);
883
    }
884
    /* Check that we will not fill more than what was allocated */
885
    if ((tmsize_t)sp->stream.avail_out > sp->tbuf_size)
886
    {
887
        TIFFErrorExtR(tif, module, "sp->stream.avail_out > sp->tbuf_size");
888
        return (0);
889
    }
890
    do
891
    {
892
        int state = inflate(&sp->stream, Z_PARTIAL_FLUSH);
893
        if (state == Z_STREAM_END)
894
        {
895
            break; /* XXX */
896
        }
897
        if (state == Z_DATA_ERROR)
898
        {
899
            TIFFErrorExtR(
900
                tif, module, "Decoding error at scanline %" PRIu32 ", %s",
901
                tif->tif_row, sp->stream.msg ? sp->stream.msg : "(null)");
902
            return (0);
903
        }
904
        if (state != Z_OK)
905
        {
906
            TIFFErrorExtR(tif, module, "ZLib error: %s",
907
                          sp->stream.msg ? sp->stream.msg : "(null)");
908
            return (0);
909
        }
910
    } while (sp->stream.avail_out > 0);
911

912
    /* hopefully, we got all the bytes we needed */
913
    if (sp->stream.avail_out != 0)
914
    {
915
        TIFFErrorExtR(tif, module,
916
                      "Not enough data at scanline %" PRIu32
917
                      " (short %u bytes)",
918
                      tif->tif_row, sp->stream.avail_out);
919
        return (0);
920
    }
921

922
    tif->tif_rawcp = sp->stream.next_in;
923
    tif->tif_rawcc = sp->stream.avail_in;
924

925
    up = sp->tbuf;
926
    /* Swap bytes in the data if from a different endian machine. */
927
    if (tif->tif_flags & TIFF_SWAB)
928
        TIFFSwabArrayOfShort(up, nsamples);
929

930
    /*
931
     * if llen is not an exact multiple of nsamples, the decode operation
932
     * may overflow the output buffer, so truncate it enough to prevent
933
     * that but still salvage as much data as possible.
934
     */
935
    if (nsamples % llen)
936
    {
937
        TIFFWarningExtR(tif, module,
938
                        "stride %d is not a multiple of sample count, "
939
                        "%" TIFF_SSIZE_FORMAT ", data truncated.",
940
                        llen, nsamples);
941
        nsamples -= nsamples % llen;
942
    }
943

944
    for (i = 0; i < nsamples; i += llen, up += llen)
945
    {
946
        switch (sp->user_datafmt)
947
        {
948
            case PIXARLOGDATAFMT_FLOAT:
949
                horizontalAccumulateF(up, llen, sp->stride, (float *)op,
950
                                      sp->ToLinearF);
951
                op += llen * sizeof(float);
952
                break;
953
            case PIXARLOGDATAFMT_16BIT:
954
                horizontalAccumulate16(up, llen, sp->stride, (uint16_t *)op,
955
                                       sp->ToLinear16);
956
                op += llen * sizeof(uint16_t);
957
                break;
958
            case PIXARLOGDATAFMT_12BITPICIO:
959
                horizontalAccumulate12(up, llen, sp->stride, (int16_t *)op,
960
                                       sp->ToLinearF);
961
                op += llen * sizeof(int16_t);
962
                break;
963
            case PIXARLOGDATAFMT_11BITLOG:
964
                horizontalAccumulate11(up, llen, sp->stride, (uint16_t *)op);
965
                op += llen * sizeof(uint16_t);
966
                break;
967
            case PIXARLOGDATAFMT_8BIT:
968
                horizontalAccumulate8(up, llen, sp->stride, (unsigned char *)op,
969
                                      sp->ToLinear8);
970
                op += llen * sizeof(unsigned char);
971
                break;
972
            case PIXARLOGDATAFMT_8BITABGR:
973
                horizontalAccumulate8abgr(up, llen, sp->stride,
974
                                          (unsigned char *)op, sp->ToLinear8);
975
                op += llen * sizeof(unsigned char);
976
                break;
977
            default:
978
                TIFFErrorExtR(tif, module, "Unsupported bits/sample: %" PRIu16,
979
                              td->td_bitspersample);
980
                return (0);
981
        }
982
    }
983

984
    return (1);
985
}
986

987
static int PixarLogSetupEncode(TIFF *tif)
988
{
989
    static const char module[] = "PixarLogSetupEncode";
990
    TIFFDirectory *td = &tif->tif_dir;
991
    PixarLogState *sp = EncoderState(tif);
992
    tmsize_t tbuf_size;
993

994
    assert(sp != NULL);
995

996
    /* for some reason, we can't do this in TIFFInitPixarLog */
997

998
    sp->stride =
999
        (td->td_planarconfig == PLANARCONFIG_CONTIG ? td->td_samplesperpixel
1000
                                                    : 1);
1001
    tbuf_size =
1002
        multiply_ms(multiply_ms(multiply_ms(sp->stride, td->td_imagewidth),
1003
                                td->td_rowsperstrip),
1004
                    sizeof(uint16_t));
1005
    if (tbuf_size == 0)
1006
        return (0); /* TODO: this is an error return without error report
1007
                       through TIFFErrorExt */
1008
    sp->tbuf = (uint16_t *)_TIFFmallocExt(tif, tbuf_size);
1009
    if (sp->tbuf == NULL)
1010
        return (0);
1011
    if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN)
1012
        sp->user_datafmt = PixarLogGuessDataFmt(td);
1013
    if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN)
1014
    {
1015
        TIFFErrorExtR(tif, module,
1016
                      "PixarLog compression can't handle %" PRIu16
1017
                      " bit linear encodings",
1018
                      td->td_bitspersample);
1019
        return (0);
1020
    }
1021

1022
    if (deflateInit(&sp->stream, sp->quality) != Z_OK)
1023
    {
1024
        TIFFErrorExtR(tif, module, "%s",
1025
                      sp->stream.msg ? sp->stream.msg : "(null)");
1026
        return (0);
1027
    }
1028
    else
1029
    {
1030
        sp->state |= PLSTATE_INIT;
1031
        return (1);
1032
    }
1033
}
1034

1035
/*
1036
 * Reset encoding state at the start of a strip.
1037
 */
1038
static int PixarLogPreEncode(TIFF *tif, uint16_t s)
1039
{
1040
    static const char module[] = "PixarLogPreEncode";
1041
    PixarLogState *sp = EncoderState(tif);
1042

1043
    (void)s;
1044
    assert(sp != NULL);
1045
    sp->stream.next_out = tif->tif_rawdata;
1046
    assert(sizeof(sp->stream.avail_out) == 4); /* if this assert gets raised,
1047
         we need to simplify this code to reflect a ZLib that is likely updated
1048
         to deal with 8byte memory sizes, though this code will respond
1049
         appropriately even before we simplify it */
1050
    sp->stream.avail_out = (uInt)tif->tif_rawdatasize;
1051
    if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize)
1052
    {
1053
        TIFFErrorExtR(tif, module, "ZLib cannot deal with buffers this size");
1054
        return (0);
1055
    }
1056
    return (deflateReset(&sp->stream) == Z_OK);
1057
}
1058

1059
static void horizontalDifferenceF(float *ip, int n, int stride, uint16_t *wp,
1060
                                  uint16_t *FromLT2)
1061
{
1062
    int32_t r1, g1, b1, a1, r2, g2, b2, a2, mask;
1063
    float fltsize = Fltsize;
1064

1065
#define CLAMP(v)                                                               \
1066
    ((v < (float)0.)     ? 0                                                   \
1067
     : (v < (float)2.)   ? FromLT2[(int)(v * fltsize)]                         \
1068
     : (v > (float)24.2) ? 2047                                                \
1069
                         : LogK1 * log(v * LogK2) + 0.5)
1070

1071
    mask = CODE_MASK;
1072
    if (n >= stride)
1073
    {
1074
        if (stride == 3)
1075
        {
1076
            r2 = wp[0] = (uint16_t)CLAMP(ip[0]);
1077
            g2 = wp[1] = (uint16_t)CLAMP(ip[1]);
1078
            b2 = wp[2] = (uint16_t)CLAMP(ip[2]);
1079
            n -= 3;
1080
            while (n > 0)
1081
            {
1082
                n -= 3;
1083
                wp += 3;
1084
                ip += 3;
1085
                r1 = (int32_t)CLAMP(ip[0]);
1086
                wp[0] = (uint16_t)((r1 - r2) & mask);
1087
                r2 = r1;
1088
                g1 = (int32_t)CLAMP(ip[1]);
1089
                wp[1] = (uint16_t)((g1 - g2) & mask);
1090
                g2 = g1;
1091
                b1 = (int32_t)CLAMP(ip[2]);
1092
                wp[2] = (uint16_t)((b1 - b2) & mask);
1093
                b2 = b1;
1094
            }
1095
        }
1096
        else if (stride == 4)
1097
        {
1098
            r2 = wp[0] = (uint16_t)CLAMP(ip[0]);
1099
            g2 = wp[1] = (uint16_t)CLAMP(ip[1]);
1100
            b2 = wp[2] = (uint16_t)CLAMP(ip[2]);
1101
            a2 = wp[3] = (uint16_t)CLAMP(ip[3]);
1102
            n -= 4;
1103
            while (n > 0)
1104
            {
1105
                n -= 4;
1106
                wp += 4;
1107
                ip += 4;
1108
                r1 = (int32_t)CLAMP(ip[0]);
1109
                wp[0] = (uint16_t)((r1 - r2) & mask);
1110
                r2 = r1;
1111
                g1 = (int32_t)CLAMP(ip[1]);
1112
                wp[1] = (uint16_t)((g1 - g2) & mask);
1113
                g2 = g1;
1114
                b1 = (int32_t)CLAMP(ip[2]);
1115
                wp[2] = (uint16_t)((b1 - b2) & mask);
1116
                b2 = b1;
1117
                a1 = (int32_t)CLAMP(ip[3]);
1118
                wp[3] = (uint16_t)((a1 - a2) & mask);
1119
                a2 = a1;
1120
            }
1121
        }
1122
        else
1123
        {
1124
            REPEAT(stride, wp[0] = (uint16_t)CLAMP(ip[0]); wp++; ip++)
1125
            n -= stride;
1126
            while (n > 0)
1127
            {
1128
                REPEAT(stride,
1129
                       wp[0] = (uint16_t)(((int32_t)CLAMP(ip[0]) -
1130
                                           (int32_t)CLAMP(ip[-stride])) &
1131
                                          mask);
1132
                       wp++; ip++)
1133
                n -= stride;
1134
            }
1135
        }
1136
    }
1137
}
1138

1139
static void horizontalDifference16(unsigned short *ip, int n, int stride,
1140
                                   unsigned short *wp, uint16_t *From14)
1141
{
1142
    register int r1, g1, b1, a1, r2, g2, b2, a2, mask;
1143

1144
/* assumption is unsigned pixel values */
1145
#undef CLAMP
1146
#define CLAMP(v) From14[(v) >> 2]
1147

1148
    mask = CODE_MASK;
1149
    if (n >= stride)
1150
    {
1151
        if (stride == 3)
1152
        {
1153
            r2 = wp[0] = CLAMP(ip[0]);
1154
            g2 = wp[1] = CLAMP(ip[1]);
1155
            b2 = wp[2] = CLAMP(ip[2]);
1156
            n -= 3;
1157
            while (n > 0)
1158
            {
1159
                n -= 3;
1160
                wp += 3;
1161
                ip += 3;
1162
                r1 = CLAMP(ip[0]);
1163
                wp[0] = (uint16_t)((r1 - r2) & mask);
1164
                r2 = r1;
1165
                g1 = CLAMP(ip[1]);
1166
                wp[1] = (uint16_t)((g1 - g2) & mask);
1167
                g2 = g1;
1168
                b1 = CLAMP(ip[2]);
1169
                wp[2] = (uint16_t)((b1 - b2) & mask);
1170
                b2 = b1;
1171
            }
1172
        }
1173
        else if (stride == 4)
1174
        {
1175
            r2 = wp[0] = CLAMP(ip[0]);
1176
            g2 = wp[1] = CLAMP(ip[1]);
1177
            b2 = wp[2] = CLAMP(ip[2]);
1178
            a2 = wp[3] = CLAMP(ip[3]);
1179
            n -= 4;
1180
            while (n > 0)
1181
            {
1182
                n -= 4;
1183
                wp += 4;
1184
                ip += 4;
1185
                r1 = CLAMP(ip[0]);
1186
                wp[0] = (uint16_t)((r1 - r2) & mask);
1187
                r2 = r1;
1188
                g1 = CLAMP(ip[1]);
1189
                wp[1] = (uint16_t)((g1 - g2) & mask);
1190
                g2 = g1;
1191
                b1 = CLAMP(ip[2]);
1192
                wp[2] = (uint16_t)((b1 - b2) & mask);
1193
                b2 = b1;
1194
                a1 = CLAMP(ip[3]);
1195
                wp[3] = (uint16_t)((a1 - a2) & mask);
1196
                a2 = a1;
1197
            }
1198
        }
1199
        else
1200
        {
1201
            REPEAT(stride, wp[0] = CLAMP(ip[0]); wp++; ip++)
1202
            n -= stride;
1203
            while (n > 0)
1204
            {
1205
                REPEAT(stride,
1206
                       wp[0] = (uint16_t)((CLAMP(ip[0]) - CLAMP(ip[-stride])) &
1207
                                          mask);
1208
                       wp++; ip++)
1209
                n -= stride;
1210
            }
1211
        }
1212
    }
1213
}
1214

1215
static void horizontalDifference8(unsigned char *ip, int n, int stride,
1216
                                  unsigned short *wp, uint16_t *From8)
1217
{
1218
    register int r1, g1, b1, a1, r2, g2, b2, a2, mask;
1219

1220
#undef CLAMP
1221
#define CLAMP(v) (From8[(v)])
1222

1223
    mask = CODE_MASK;
1224
    if (n >= stride)
1225
    {
1226
        if (stride == 3)
1227
        {
1228
            r2 = wp[0] = CLAMP(ip[0]);
1229
            g2 = wp[1] = CLAMP(ip[1]);
1230
            b2 = wp[2] = CLAMP(ip[2]);
1231
            n -= 3;
1232
            while (n > 0)
1233
            {
1234
                n -= 3;
1235
                r1 = CLAMP(ip[3]);
1236
                wp[3] = (uint16_t)((r1 - r2) & mask);
1237
                r2 = r1;
1238
                g1 = CLAMP(ip[4]);
1239
                wp[4] = (uint16_t)((g1 - g2) & mask);
1240
                g2 = g1;
1241
                b1 = CLAMP(ip[5]);
1242
                wp[5] = (uint16_t)((b1 - b2) & mask);
1243
                b2 = b1;
1244
                wp += 3;
1245
                ip += 3;
1246
            }
1247
        }
1248
        else if (stride == 4)
1249
        {
1250
            r2 = wp[0] = CLAMP(ip[0]);
1251
            g2 = wp[1] = CLAMP(ip[1]);
1252
            b2 = wp[2] = CLAMP(ip[2]);
1253
            a2 = wp[3] = CLAMP(ip[3]);
1254
            n -= 4;
1255
            while (n > 0)
1256
            {
1257
                n -= 4;
1258
                r1 = CLAMP(ip[4]);
1259
                wp[4] = (uint16_t)((r1 - r2) & mask);
1260
                r2 = r1;
1261
                g1 = CLAMP(ip[5]);
1262
                wp[5] = (uint16_t)((g1 - g2) & mask);
1263
                g2 = g1;
1264
                b1 = CLAMP(ip[6]);
1265
                wp[6] = (uint16_t)((b1 - b2) & mask);
1266
                b2 = b1;
1267
                a1 = CLAMP(ip[7]);
1268
                wp[7] = (uint16_t)((a1 - a2) & mask);
1269
                a2 = a1;
1270
                wp += 4;
1271
                ip += 4;
1272
            }
1273
        }
1274
        else
1275
        {
1276
            REPEAT(stride, wp[0] = CLAMP(ip[0]); wp++; ip++)
1277
            n -= stride;
1278
            while (n > 0)
1279
            {
1280
                REPEAT(stride,
1281
                       wp[0] = (uint16_t)((CLAMP(ip[0]) - CLAMP(ip[-stride])) &
1282
                                          mask);
1283
                       wp++; ip++)
1284
                n -= stride;
1285
            }
1286
        }
1287
    }
1288
}
1289

1290
/*
1291
 * Encode a chunk of pixels.
1292
 */
1293
static int PixarLogEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
1294
{
1295
    static const char module[] = "PixarLogEncode";
1296
    TIFFDirectory *td = &tif->tif_dir;
1297
    PixarLogState *sp = EncoderState(tif);
1298
    tmsize_t i;
1299
    tmsize_t n;
1300
    int llen;
1301
    unsigned short *up;
1302

1303
    (void)s;
1304

1305
    switch (sp->user_datafmt)
1306
    {
1307
        case PIXARLOGDATAFMT_FLOAT:
1308
            n = cc / sizeof(float); /* XXX float == 32 bits */
1309
            break;
1310
        case PIXARLOGDATAFMT_16BIT:
1311
        case PIXARLOGDATAFMT_12BITPICIO:
1312
        case PIXARLOGDATAFMT_11BITLOG:
1313
            n = cc / sizeof(uint16_t); /* XXX uint16_t == 16 bits */
1314
            break;
1315
        case PIXARLOGDATAFMT_8BIT:
1316
        case PIXARLOGDATAFMT_8BITABGR:
1317
            n = cc;
1318
            break;
1319
        default:
1320
            TIFFErrorExtR(tif, module,
1321
                          "%" PRIu16 " bit input not supported in PixarLog",
1322
                          td->td_bitspersample);
1323
            return 0;
1324
    }
1325

1326
    llen = sp->stride * td->td_imagewidth;
1327
    /* Check against the number of elements (of size uint16_t) of sp->tbuf */
1328
    if (n > ((tmsize_t)td->td_rowsperstrip * llen))
1329
    {
1330
        TIFFErrorExtR(tif, module, "Too many input bytes provided");
1331
        return 0;
1332
    }
1333

1334
    for (i = 0, up = sp->tbuf; i < n; i += llen, up += llen)
1335
    {
1336
        switch (sp->user_datafmt)
1337
        {
1338
            case PIXARLOGDATAFMT_FLOAT:
1339
                horizontalDifferenceF((float *)bp, llen, sp->stride, up,
1340
                                      sp->FromLT2);
1341
                bp += llen * sizeof(float);
1342
                break;
1343
            case PIXARLOGDATAFMT_16BIT:
1344
                horizontalDifference16((uint16_t *)bp, llen, sp->stride, up,
1345
                                       sp->From14);
1346
                bp += llen * sizeof(uint16_t);
1347
                break;
1348
            case PIXARLOGDATAFMT_8BIT:
1349
                horizontalDifference8((unsigned char *)bp, llen, sp->stride, up,
1350
                                      sp->From8);
1351
                bp += llen * sizeof(unsigned char);
1352
                break;
1353
            default:
1354
                TIFFErrorExtR(tif, module,
1355
                              "%" PRIu16 " bit input not supported in PixarLog",
1356
                              td->td_bitspersample);
1357
                return 0;
1358
        }
1359
    }
1360

1361
    sp->stream.next_in = (unsigned char *)sp->tbuf;
1362
    assert(sizeof(sp->stream.avail_in) == 4); /* if this assert gets raised,
1363
         we need to simplify this code to reflect a ZLib that is likely updated
1364
         to deal with 8byte memory sizes, though this code will respond
1365
         appropriately even before we simplify it */
1366
    sp->stream.avail_in = (uInt)(n * sizeof(uint16_t));
1367
    if ((sp->stream.avail_in / sizeof(uint16_t)) != (uInt)n)
1368
    {
1369
        TIFFErrorExtR(tif, module, "ZLib cannot deal with buffers this size");
1370
        return (0);
1371
    }
1372

1373
    do
1374
    {
1375
        if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK)
1376
        {
1377
            TIFFErrorExtR(tif, module, "Encoder error: %s",
1378
                          sp->stream.msg ? sp->stream.msg : "(null)");
1379
            return (0);
1380
        }
1381
        if (sp->stream.avail_out == 0)
1382
        {
1383
            tif->tif_rawcc = tif->tif_rawdatasize;
1384
            if (!TIFFFlushData1(tif))
1385
                return 0;
1386
            sp->stream.next_out = tif->tif_rawdata;
1387
            sp->stream.avail_out =
1388
                (uInt)tif
1389
                    ->tif_rawdatasize; /* this is a safe typecast, as check is
1390
                                          made already in PixarLogPreEncode */
1391
        }
1392
    } while (sp->stream.avail_in > 0);
1393
    return (1);
1394
}
1395

1396
/*
1397
 * Finish off an encoded strip by flushing the last
1398
 * string and tacking on an End Of Information code.
1399
 */
1400

1401
static int PixarLogPostEncode(TIFF *tif)
1402
{
1403
    static const char module[] = "PixarLogPostEncode";
1404
    PixarLogState *sp = EncoderState(tif);
1405
    int state;
1406

1407
    sp->stream.avail_in = 0;
1408

1409
    do
1410
    {
1411
        state = deflate(&sp->stream, Z_FINISH);
1412
        switch (state)
1413
        {
1414
            case Z_STREAM_END:
1415
            case Z_OK:
1416
                if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize)
1417
                {
1418
                    tif->tif_rawcc =
1419
                        tif->tif_rawdatasize - sp->stream.avail_out;
1420
                    if (!TIFFFlushData1(tif))
1421
                        return 0;
1422
                    sp->stream.next_out = tif->tif_rawdata;
1423
                    sp->stream.avail_out =
1424
                        (uInt)tif->tif_rawdatasize; /* this is a safe typecast,
1425
                                                       as check is made already
1426
                                                       in PixarLogPreEncode */
1427
                }
1428
                break;
1429
            default:
1430
                TIFFErrorExtR(tif, module, "ZLib error: %s",
1431
                              sp->stream.msg ? sp->stream.msg : "(null)");
1432
                return (0);
1433
        }
1434
    } while (state != Z_STREAM_END);
1435
    return (1);
1436
}
1437

1438
static void PixarLogClose(TIFF *tif)
1439
{
1440
    PixarLogState *sp = (PixarLogState *)tif->tif_data;
1441
    TIFFDirectory *td = &tif->tif_dir;
1442

1443
    assert(sp != 0);
1444
    /* In a really sneaky (and really incorrect, and untruthful, and
1445
     * troublesome, and error-prone) maneuver that completely goes against
1446
     * the spirit of TIFF, and breaks TIFF, on close, we covertly
1447
     * modify both bitspersample and sampleformat in the directory to
1448
     * indicate 8-bit linear.  This way, the decode "just works" even for
1449
     * readers that don't know about PixarLog, or how to set
1450
     * the PIXARLOGDATFMT pseudo-tag.
1451
     */
1452

1453
    if (sp->state & PLSTATE_INIT)
1454
    {
1455
        /* We test the state to avoid an issue such as in
1456
         * http://bugzilla.maptools.org/show_bug.cgi?id=2604
1457
         * What appends in that case is that the bitspersample is 1 and
1458
         * a TransferFunction is set. The size of the TransferFunction
1459
         * depends on 1<<bitspersample. So if we increase it, an access
1460
         * out of the buffer will happen at directory flushing.
1461
         * Another option would be to clear those targs.
1462
         */
1463
        td->td_bitspersample = 8;
1464
        td->td_sampleformat = SAMPLEFORMAT_UINT;
1465
    }
1466
}
1467

1468
static void PixarLogCleanup(TIFF *tif)
1469
{
1470
    PixarLogState *sp = (PixarLogState *)tif->tif_data;
1471

1472
    assert(sp != 0);
1473

1474
    (void)TIFFPredictorCleanup(tif);
1475

1476
    tif->tif_tagmethods.vgetfield = sp->vgetparent;
1477
    tif->tif_tagmethods.vsetfield = sp->vsetparent;
1478

1479
    if (sp->FromLT2)
1480
        _TIFFfreeExt(tif, sp->FromLT2);
1481
    if (sp->From14)
1482
        _TIFFfreeExt(tif, sp->From14);
1483
    if (sp->From8)
1484
        _TIFFfreeExt(tif, sp->From8);
1485
    if (sp->ToLinearF)
1486
        _TIFFfreeExt(tif, sp->ToLinearF);
1487
    if (sp->ToLinear16)
1488
        _TIFFfreeExt(tif, sp->ToLinear16);
1489
    if (sp->ToLinear8)
1490
        _TIFFfreeExt(tif, sp->ToLinear8);
1491
    if (sp->state & PLSTATE_INIT)
1492
    {
1493
        if (tif->tif_mode == O_RDONLY)
1494
            inflateEnd(&sp->stream);
1495
        else
1496
            deflateEnd(&sp->stream);
1497
    }
1498
    if (sp->tbuf)
1499
        _TIFFfreeExt(tif, sp->tbuf);
1500
    _TIFFfreeExt(tif, sp);
1501
    tif->tif_data = NULL;
1502

1503
    _TIFFSetDefaultCompressionState(tif);
1504
}
1505

1506
static int PixarLogVSetField(TIFF *tif, uint32_t tag, va_list ap)
1507
{
1508
    static const char module[] = "PixarLogVSetField";
1509
    PixarLogState *sp = (PixarLogState *)tif->tif_data;
1510
    int result;
1511

1512
    switch (tag)
1513
    {
1514
        case TIFFTAG_PIXARLOGQUALITY:
1515
            sp->quality = (int)va_arg(ap, int);
1516
            if (tif->tif_mode != O_RDONLY && (sp->state & PLSTATE_INIT))
1517
            {
1518
                if (deflateParams(&sp->stream, sp->quality,
1519
                                  Z_DEFAULT_STRATEGY) != Z_OK)
1520
                {
1521
                    TIFFErrorExtR(tif, module, "ZLib error: %s",
1522
                                  sp->stream.msg ? sp->stream.msg : "(null)");
1523
                    return (0);
1524
                }
1525
            }
1526
            return (1);
1527
        case TIFFTAG_PIXARLOGDATAFMT:
1528
            sp->user_datafmt = (int)va_arg(ap, int);
1529
            /* Tweak the TIFF header so that the rest of libtiff knows what
1530
             * size of data will be passed between app and library, and
1531
             * assume that the app knows what it is doing and is not
1532
             * confused by these header manipulations...
1533
             */
1534
            switch (sp->user_datafmt)
1535
            {
1536
                case PIXARLOGDATAFMT_8BIT:
1537
                case PIXARLOGDATAFMT_8BITABGR:
1538
                    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
1539
                    TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
1540
                    break;
1541
                case PIXARLOGDATAFMT_11BITLOG:
1542
                    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
1543
                    TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
1544
                    break;
1545
                case PIXARLOGDATAFMT_12BITPICIO:
1546
                    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
1547
                    TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT);
1548
                    break;
1549
                case PIXARLOGDATAFMT_16BIT:
1550
                    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
1551
                    TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
1552
                    break;
1553
                case PIXARLOGDATAFMT_FLOAT:
1554
                    TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32);
1555
                    TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT,
1556
                                 SAMPLEFORMAT_IEEEFP);
1557
                    break;
1558
            }
1559
            /*
1560
             * Must recalculate sizes should bits/sample change.
1561
             */
1562
            tif->tif_tilesize =
1563
                isTiled(tif) ? TIFFTileSize(tif) : (tmsize_t)(-1);
1564
            tif->tif_scanlinesize = TIFFScanlineSize(tif);
1565
            result = 1; /* NB: pseudo tag */
1566
            break;
1567
        default:
1568
            result = (*sp->vsetparent)(tif, tag, ap);
1569
    }
1570
    return (result);
1571
}
1572

1573
static int PixarLogVGetField(TIFF *tif, uint32_t tag, va_list ap)
1574
{
1575
    PixarLogState *sp = (PixarLogState *)tif->tif_data;
1576

1577
    switch (tag)
1578
    {
1579
        case TIFFTAG_PIXARLOGQUALITY:
1580
            *va_arg(ap, int *) = sp->quality;
1581
            break;
1582
        case TIFFTAG_PIXARLOGDATAFMT:
1583
            *va_arg(ap, int *) = sp->user_datafmt;
1584
            break;
1585
        default:
1586
            return (*sp->vgetparent)(tif, tag, ap);
1587
    }
1588
    return (1);
1589
}
1590

1591
static const TIFFField pixarlogFields[] = {
1592
    {TIFFTAG_PIXARLOGDATAFMT, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT,
1593
     TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, FALSE, FALSE, "", NULL},
1594
    {TIFFTAG_PIXARLOGQUALITY, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT,
1595
     TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, FALSE, FALSE, "", NULL}};
1596

1597
int TIFFInitPixarLog(TIFF *tif, int scheme)
1598
{
1599
    static const char module[] = "TIFFInitPixarLog";
1600

1601
    PixarLogState *sp;
1602

1603
    (void)scheme;
1604
    assert(scheme == COMPRESSION_PIXARLOG);
1605

1606
    /*
1607
     * Merge codec-specific tag information.
1608
     */
1609
    if (!_TIFFMergeFields(tif, pixarlogFields, TIFFArrayCount(pixarlogFields)))
1610
    {
1611
        TIFFErrorExtR(tif, module,
1612
                      "Merging PixarLog codec-specific tags failed");
1613
        return 0;
1614
    }
1615

1616
    /*
1617
     * Allocate state block so tag methods have storage to record values.
1618
     */
1619
    tif->tif_data = (uint8_t *)_TIFFmallocExt(tif, sizeof(PixarLogState));
1620
    if (tif->tif_data == NULL)
1621
        goto bad;
1622
    sp = (PixarLogState *)tif->tif_data;
1623
    _TIFFmemset(sp, 0, sizeof(*sp));
1624
    sp->stream.data_type = Z_BINARY;
1625
    sp->user_datafmt = PIXARLOGDATAFMT_UNKNOWN;
1626

1627
    /*
1628
     * Install codec methods.
1629
     */
1630
    tif->tif_fixuptags = PixarLogFixupTags;
1631
    tif->tif_setupdecode = PixarLogSetupDecode;
1632
    tif->tif_predecode = PixarLogPreDecode;
1633
    tif->tif_decoderow = PixarLogDecode;
1634
    tif->tif_decodestrip = PixarLogDecode;
1635
    tif->tif_decodetile = PixarLogDecode;
1636
    tif->tif_setupencode = PixarLogSetupEncode;
1637
    tif->tif_preencode = PixarLogPreEncode;
1638
    tif->tif_postencode = PixarLogPostEncode;
1639
    tif->tif_encoderow = PixarLogEncode;
1640
    tif->tif_encodestrip = PixarLogEncode;
1641
    tif->tif_encodetile = PixarLogEncode;
1642
    tif->tif_close = PixarLogClose;
1643
    tif->tif_cleanup = PixarLogCleanup;
1644

1645
    /* Override SetField so we can handle our private pseudo-tag */
1646
    sp->vgetparent = tif->tif_tagmethods.vgetfield;
1647
    tif->tif_tagmethods.vgetfield = PixarLogVGetField; /* hook for codec tags */
1648
    sp->vsetparent = tif->tif_tagmethods.vsetfield;
1649
    tif->tif_tagmethods.vsetfield = PixarLogVSetField; /* hook for codec tags */
1650

1651
    /* Default values for codec-specific fields */
1652
    sp->quality = Z_DEFAULT_COMPRESSION; /* default comp. level */
1653
    sp->state = 0;
1654

1655
    /* we don't wish to use the predictor,
1656
     * the default is none, which predictor value 1
1657
     */
1658
    (void)TIFFPredictorInit(tif);
1659

1660
    /*
1661
     * build the companding tables
1662
     */
1663
    PixarLogMakeTables(tif, sp);
1664

1665
    return (1);
1666
bad:
1667
    TIFFErrorExtR(tif, module, "No space for PixarLog state block");
1668
    return (0);
1669
}
1670
#endif /* PIXARLOG_SUPPORT */
1671

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.