Coverage Report

Created: 2022-10-31 07:00

/src/ghostpdl/tiff/libtiff/tif_pixarlog.c
Line
Count
Source (jump to first uncovered line)
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 <stdio.h>
94
#include <stdlib.h>
95
#include <math.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
0
#define REPEAT(n, op)   { int i; i=n; do { i--; op; } while (i>0); }
110
111
static void
112
horizontalAccumulateF(uint16_t *wp, int n, int stride, float *op,
113
                      float *ToLinearF)
114
0
{
115
0
    register unsigned int  cr, cg, cb, ca, mask;
116
0
    register float  t0, t1, t2, t3;
117
118
0
    if (n >= stride) {
119
0
  mask = CODE_MASK;
120
0
  if (stride == 3) {
121
0
      t0 = ToLinearF[cr = (wp[0] & mask)];
122
0
      t1 = ToLinearF[cg = (wp[1] & mask)];
123
0
      t2 = ToLinearF[cb = (wp[2] & mask)];
124
0
      op[0] = t0;
125
0
      op[1] = t1;
126
0
      op[2] = t2;
127
0
      n -= 3;
128
0
      while (n > 0) {
129
0
    wp += 3;
130
0
    op += 3;
131
0
    n -= 3;
132
0
    t0 = ToLinearF[(cr += wp[0]) & mask];
133
0
    t1 = ToLinearF[(cg += wp[1]) & mask];
134
0
    t2 = ToLinearF[(cb += wp[2]) & mask];
135
0
    op[0] = t0;
136
0
    op[1] = t1;
137
0
    op[2] = t2;
138
0
      }
139
0
  } else if (stride == 4) {
140
0
      t0 = ToLinearF[cr = (wp[0] & mask)];
141
0
      t1 = ToLinearF[cg = (wp[1] & mask)];
142
0
      t2 = ToLinearF[cb = (wp[2] & mask)];
143
0
      t3 = ToLinearF[ca = (wp[3] & mask)];
144
0
      op[0] = t0;
145
0
      op[1] = t1;
146
0
      op[2] = t2;
147
0
      op[3] = t3;
148
0
      n -= 4;
149
0
      while (n > 0) {
150
0
    wp += 4;
151
0
    op += 4;
152
0
    n -= 4;
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
      }
162
0
  } else {
163
0
      REPEAT(stride, *op = ToLinearF[*wp&mask]; wp++; op++)
164
0
      n -= stride;
165
0
      while (n > 0) {
166
0
    REPEAT(stride,
167
0
        wp[stride] += *wp; *op = ToLinearF[*wp&mask]; wp++; op++)
168
0
    n -= stride;
169
0
      }
170
0
  }
171
0
    }
172
0
}
173
174
static void
175
horizontalAccumulate12(uint16_t *wp, int n, int stride, int16_t *op,
176
                       float *ToLinearF)
177
0
{
178
0
    register unsigned int  cr, cg, cb, ca, mask;
179
0
    register float  t0, t1, t2, t3;
180
181
0
#define SCALE12 2048.0F
182
0
#define CLAMP12(t) (((t) < 3071) ? (uint16_t) (t) : 3071)
183
184
0
    if (n >= stride) {
185
0
  mask = CODE_MASK;
186
0
  if (stride == 3) {
187
0
      t0 = ToLinearF[cr = (wp[0] & mask)] * SCALE12;
188
0
      t1 = ToLinearF[cg = (wp[1] & mask)] * SCALE12;
189
0
      t2 = ToLinearF[cb = (wp[2] & mask)] * SCALE12;
190
0
      op[0] = CLAMP12(t0);
191
0
      op[1] = CLAMP12(t1);
192
0
      op[2] = CLAMP12(t2);
193
0
      n -= 3;
194
0
      while (n > 0) {
195
0
    wp += 3;
196
0
    op += 3;
197
0
    n -= 3;
198
0
    t0 = ToLinearF[(cr += wp[0]) & mask] * SCALE12;
199
0
    t1 = ToLinearF[(cg += wp[1]) & mask] * SCALE12;
200
0
    t2 = ToLinearF[(cb += wp[2]) & mask] * SCALE12;
201
0
    op[0] = CLAMP12(t0);
202
0
    op[1] = CLAMP12(t1);
203
0
    op[2] = CLAMP12(t2);
204
0
      }
205
0
  } else if (stride == 4) {
206
0
      t0 = ToLinearF[cr = (wp[0] & mask)] * SCALE12;
207
0
      t1 = ToLinearF[cg = (wp[1] & mask)] * SCALE12;
208
0
      t2 = ToLinearF[cb = (wp[2] & mask)] * SCALE12;
209
0
      t3 = ToLinearF[ca = (wp[3] & mask)] * SCALE12;
210
0
      op[0] = CLAMP12(t0);
211
0
      op[1] = CLAMP12(t1);
212
0
      op[2] = CLAMP12(t2);
213
0
      op[3] = CLAMP12(t3);
214
0
      n -= 4;
215
0
      while (n > 0) {
216
0
    wp += 4;
217
0
    op += 4;
218
0
    n -= 4;
219
0
    t0 = ToLinearF[(cr += wp[0]) & mask] * SCALE12;
220
0
    t1 = ToLinearF[(cg += wp[1]) & mask] * SCALE12;
221
0
    t2 = ToLinearF[(cb += wp[2]) & mask] * SCALE12;
222
0
    t3 = ToLinearF[(ca += wp[3]) & mask] * SCALE12;
223
0
    op[0] = CLAMP12(t0);
224
0
    op[1] = CLAMP12(t1);
225
0
    op[2] = CLAMP12(t2);
226
0
    op[3] = CLAMP12(t3);
227
0
      }
228
0
  } else {
229
0
      REPEAT(stride, t0 = ToLinearF[*wp&mask] * SCALE12;
230
0
                           *op = CLAMP12(t0); wp++; op++)
231
0
      n -= stride;
232
0
      while (n > 0) {
233
0
    REPEAT(stride,
234
0
        wp[stride] += *wp; t0 = ToLinearF[wp[stride]&mask]*SCALE12;
235
0
        *op = CLAMP12(t0);  wp++; op++)
236
0
    n -= stride;
237
0
      }
238
0
  }
239
0
    }
240
0
}
241
242
static void
243
horizontalAccumulate16(uint16_t *wp, int n, int stride, uint16_t *op,
244
                       uint16_t *ToLinear16)
245
0
{
246
0
    register unsigned int  cr, cg, cb, ca, mask;
247
248
0
    if (n >= stride) {
249
0
  mask = CODE_MASK;
250
0
  if (stride == 3) {
251
0
      op[0] = ToLinear16[cr = (wp[0] & mask)];
252
0
      op[1] = ToLinear16[cg = (wp[1] & mask)];
253
0
      op[2] = ToLinear16[cb = (wp[2] & mask)];
254
0
      n -= 3;
255
0
      while (n > 0) {
256
0
    wp += 3;
257
0
    op += 3;
258
0
    n -= 3;
259
0
    op[0] = ToLinear16[(cr += wp[0]) & mask];
260
0
    op[1] = ToLinear16[(cg += wp[1]) & mask];
261
0
    op[2] = ToLinear16[(cb += wp[2]) & mask];
262
0
      }
263
0
  } else if (stride == 4) {
264
0
      op[0] = ToLinear16[cr = (wp[0] & mask)];
265
0
      op[1] = ToLinear16[cg = (wp[1] & mask)];
266
0
      op[2] = ToLinear16[cb = (wp[2] & mask)];
267
0
      op[3] = ToLinear16[ca = (wp[3] & mask)];
268
0
      n -= 4;
269
0
      while (n > 0) {
270
0
    wp += 4;
271
0
    op += 4;
272
0
    n -= 4;
273
0
    op[0] = ToLinear16[(cr += wp[0]) & mask];
274
0
    op[1] = ToLinear16[(cg += wp[1]) & mask];
275
0
    op[2] = ToLinear16[(cb += wp[2]) & mask];
276
0
    op[3] = ToLinear16[(ca += wp[3]) & mask];
277
0
      }
278
0
  } else {
279
0
      REPEAT(stride, *op = ToLinear16[*wp&mask]; wp++; op++)
280
0
      n -= stride;
281
0
      while (n > 0) {
282
0
    REPEAT(stride,
283
0
        wp[stride] += *wp; *op = ToLinear16[*wp&mask]; wp++; op++)
284
0
    n -= stride;
285
0
      }
286
0
  }
287
0
    }
288
0
}
289
290
/* 
291
 * Returns the log encoded 11-bit values with the horizontal
292
 * differencing undone.
293
 */
294
static void
295
horizontalAccumulate11(uint16_t *wp, int n, int stride, uint16_t *op)
296
0
{
297
0
    register unsigned int cr, cg, cb, ca, mask;
298
299
0
    if (n >= stride) {
300
0
  mask = CODE_MASK;
301
0
  if (stride == 3) {
302
0
      op[0] = wp[0];  op[1] = wp[1];  op[2] = wp[2];
303
0
            cr = wp[0];  cg = wp[1];  cb = wp[2];
304
0
      n -= 3;
305
0
      while (n > 0) {
306
0
    wp += 3;
307
0
    op += 3;
308
0
    n -= 3;
309
0
    op[0] = (uint16_t)((cr += wp[0]) & mask);
310
0
    op[1] = (uint16_t)((cg += wp[1]) & mask);
311
0
    op[2] = (uint16_t)((cb += wp[2]) & mask);
312
0
      }
313
0
  } else if (stride == 4) {
314
0
      op[0] = wp[0];  op[1] = wp[1];
315
0
      op[2] = wp[2];  op[3] = wp[3];
316
0
            cr = wp[0]; cg = wp[1]; cb = wp[2]; ca = wp[3];
317
0
      n -= 4;
318
0
      while (n > 0) {
319
0
    wp += 4;
320
0
    op += 4;
321
0
    n -= 4;
322
0
    op[0] = (uint16_t)((cr += wp[0]) & mask);
323
0
    op[1] = (uint16_t)((cg += wp[1]) & mask);
324
0
    op[2] = (uint16_t)((cb += wp[2]) & mask);
325
0
    op[3] = (uint16_t)((ca += wp[3]) & mask);
326
0
      } 
327
0
  } else {
328
0
      REPEAT(stride, *op = *wp&mask; wp++; op++)
329
0
      n -= stride;
330
0
      while (n > 0) {
331
0
    REPEAT(stride,
332
0
        wp[stride] += *wp; *op = *wp&mask; wp++; op++)
333
0
    n -= stride;
334
0
      }
335
0
  }
336
0
    }
337
0
}
338
339
static void
340
horizontalAccumulate8(uint16_t *wp, int n, int stride, unsigned char *op,
341
                      unsigned char *ToLinear8)
342
0
{
343
0
    register unsigned int  cr, cg, cb, ca, mask;
344
345
0
    if (n >= stride) {
346
0
  mask = CODE_MASK;
347
0
  if (stride == 3) {
348
0
      op[0] = ToLinear8[cr = (wp[0] & mask)];
349
0
      op[1] = ToLinear8[cg = (wp[1] & mask)];
350
0
      op[2] = ToLinear8[cb = (wp[2] & mask)];
351
0
      n -= 3;
352
0
      while (n > 0) {
353
0
    n -= 3;
354
0
    wp += 3;
355
0
    op += 3;
356
0
    op[0] = ToLinear8[(cr += wp[0]) & mask];
357
0
    op[1] = ToLinear8[(cg += wp[1]) & mask];
358
0
    op[2] = ToLinear8[(cb += wp[2]) & mask];
359
0
      }
360
0
  } else if (stride == 4) {
361
0
      op[0] = ToLinear8[cr = (wp[0] & mask)];
362
0
      op[1] = ToLinear8[cg = (wp[1] & mask)];
363
0
      op[2] = ToLinear8[cb = (wp[2] & mask)];
364
0
      op[3] = ToLinear8[ca = (wp[3] & mask)];
365
0
      n -= 4;
366
0
      while (n > 0) {
367
0
    n -= 4;
368
0
    wp += 4;
369
0
    op += 4;
370
0
    op[0] = ToLinear8[(cr += wp[0]) & mask];
371
0
    op[1] = ToLinear8[(cg += wp[1]) & mask];
372
0
    op[2] = ToLinear8[(cb += wp[2]) & mask];
373
0
    op[3] = ToLinear8[(ca += wp[3]) & mask];
374
0
      }
375
0
  } else {
376
0
      REPEAT(stride, *op = ToLinear8[*wp&mask]; wp++; op++)
377
0
      n -= stride;
378
0
      while (n > 0) {
379
0
    REPEAT(stride,
380
0
        wp[stride] += *wp; *op = ToLinear8[*wp&mask]; wp++; op++)
381
0
    n -= stride;
382
0
      }
383
0
  }
384
0
    }
385
0
}
386
387
388
static void
389
horizontalAccumulate8abgr(uint16_t *wp, int n, int stride, unsigned char *op,
390
                          unsigned char *ToLinear8)
391
0
{
392
0
    register unsigned int  cr, cg, cb, ca, mask;
393
0
    register unsigned char  t0, t1, t2, t3;
394
395
0
    if (n >= stride) {
396
0
  mask = CODE_MASK;
397
0
  if (stride == 3) {
398
0
      op[0] = 0;
399
0
      t1 = ToLinear8[cb = (wp[2] & mask)];
400
0
      t2 = ToLinear8[cg = (wp[1] & mask)];
401
0
      t3 = ToLinear8[cr = (wp[0] & mask)];
402
0
      op[1] = t1;
403
0
      op[2] = t2;
404
0
      op[3] = t3;
405
0
      n -= 3;
406
0
      while (n > 0) {
407
0
    n -= 3;
408
0
    wp += 3;
409
0
    op += 4;
410
0
    op[0] = 0;
411
0
    t1 = ToLinear8[(cb += wp[2]) & mask];
412
0
    t2 = ToLinear8[(cg += wp[1]) & mask];
413
0
    t3 = ToLinear8[(cr += wp[0]) & mask];
414
0
    op[1] = t1;
415
0
    op[2] = t2;
416
0
    op[3] = t3;
417
0
      }
418
0
  } else if (stride == 4) {
419
0
      t0 = ToLinear8[ca = (wp[3] & mask)];
420
0
      t1 = ToLinear8[cb = (wp[2] & mask)];
421
0
      t2 = ToLinear8[cg = (wp[1] & mask)];
422
0
      t3 = ToLinear8[cr = (wp[0] & mask)];
423
0
      op[0] = t0;
424
0
      op[1] = t1;
425
0
      op[2] = t2;
426
0
      op[3] = t3;
427
0
      n -= 4;
428
0
      while (n > 0) {
429
0
    n -= 4;
430
0
    wp += 4;
431
0
    op += 4;
432
0
    t0 = ToLinear8[(ca += wp[3]) & mask];
433
0
    t1 = ToLinear8[(cb += wp[2]) & mask];
434
0
    t2 = ToLinear8[(cg += wp[1]) & mask];
435
0
    t3 = ToLinear8[(cr += wp[0]) & mask];
436
0
    op[0] = t0;
437
0
    op[1] = t1;
438
0
    op[2] = t2;
439
0
    op[3] = t3;
440
0
      }
441
0
  } else {
442
0
      REPEAT(stride, *op = ToLinear8[*wp&mask]; wp++; op++)
443
0
      n -= stride;
444
0
      while (n > 0) {
445
0
    REPEAT(stride,
446
0
        wp[stride] += *wp; *op = ToLinear8[*wp&mask]; wp++; op++)
447
0
    n -= stride;
448
0
      }
449
0
  }
450
0
    }
451
0
}
452
453
/*
454
 * State block for each open TIFF
455
 * file using PixarLog compression/decompression.
456
 */
457
typedef struct {
458
  TIFFPredictorState  predict;
459
  z_stream    stream;
460
  tmsize_t    tbuf_size; /* only set/used on reading for now */
461
  uint16_t      *tbuf;
462
  uint16_t      stride;
463
  int     state;
464
  int     user_datafmt;
465
  int     quality;
466
0
#define PLSTATE_INIT 1
467
468
  TIFFVSetMethod    vgetparent; /* super-class method */
469
  TIFFVSetMethod    vsetparent; /* super-class method */
470
471
  float *ToLinearF;
472
  uint16_t *ToLinear16;
473
  unsigned char *ToLinear8;
474
  uint16_t  *FromLT2;
475
  uint16_t  *From14; /* Really for 16-bit data, but we shift down 2 */
476
  uint16_t  *From8;
477
  
478
} PixarLogState;
479
480
static int
481
PixarLogMakeTables(PixarLogState *sp)
482
0
{
483
484
/*
485
 *    We make several tables here to convert between various external
486
 *    representations (float, 16-bit, and 8-bit) and the internal
487
 *    11-bit companded representation.  The 11-bit representation has two
488
 *    distinct regions.  A linear bottom end up through .018316 in steps
489
 *    of about .000073, and a region of constant ratio up to about 25.
490
 *    These floating point numbers are stored in the main table ToLinearF. 
491
 *    All other tables are derived from this one.  The tables (and the
492
 *    ratios) are continuous at the internal seam.
493
 */
494
495
0
    int  nlin, lt2size;
496
0
    int  i, j;
497
0
    double  b, c, linstep, v;
498
0
    float *ToLinearF;
499
0
    uint16_t *ToLinear16;
500
0
    unsigned char *ToLinear8;
501
0
    uint16_t  *FromLT2;
502
0
    uint16_t  *From14; /* Really for 16-bit data, but we shift down 2 */
503
0
    uint16_t  *From8;
504
505
0
    c = log(RATIO);  
506
0
    nlin = (int)(1./c); /* nlin must be an integer */
507
0
    c = 1./nlin;
508
0
    b = exp(-c*ONE);  /* multiplicative scale factor [b*exp(c*ONE) = 1] */
509
0
    linstep = b*c*exp(1.);
510
511
0
    LogK1 = (float)(1./c);  /* if (v >= 2)  token = k1*log(v*k2) */
512
0
    LogK2 = (float)(1./b);
513
0
    lt2size = (int)(2./linstep) + 1;
514
0
    FromLT2 = (uint16_t *)_TIFFmalloc(lt2size * sizeof(uint16_t));
515
0
    From14 = (uint16_t *)_TIFFmalloc(16384 * sizeof(uint16_t));
516
0
    From8 = (uint16_t *)_TIFFmalloc(256 * sizeof(uint16_t));
517
0
    ToLinearF = (float *)_TIFFmalloc(TSIZEP1 * sizeof(float));
518
0
    ToLinear16 = (uint16_t *)_TIFFmalloc(TSIZEP1 * sizeof(uint16_t));
519
0
    ToLinear8 = (unsigned char *)_TIFFmalloc(TSIZEP1 * sizeof(unsigned char));
520
0
    if (FromLT2 == NULL || From14  == NULL || From8   == NULL ||
521
0
   ToLinearF == NULL || ToLinear16 == NULL || ToLinear8 == NULL) {
522
0
  if (FromLT2) _TIFFfree(FromLT2);
523
0
  if (From14) _TIFFfree(From14);
524
0
  if (From8) _TIFFfree(From8);
525
0
  if (ToLinearF) _TIFFfree(ToLinearF);
526
0
  if (ToLinear16) _TIFFfree(ToLinear16);
527
0
  if (ToLinear8) _TIFFfree(ToLinear8);
528
0
  sp->FromLT2 = NULL;
529
0
  sp->From14 = NULL;
530
0
  sp->From8 = NULL;
531
0
  sp->ToLinearF = NULL;
532
0
  sp->ToLinear16 = NULL;
533
0
  sp->ToLinear8 = NULL;
534
0
  return 0;
535
0
    }
536
537
0
    j = 0;
538
539
0
    for (i = 0; i < nlin; i++)  {
540
0
  v = i * linstep;
541
0
  ToLinearF[j++] = (float)v;
542
0
    }
543
544
0
    for (i = nlin; i < TSIZE; i++)
545
0
  ToLinearF[j++] = (float)(b*exp(c*i));
546
547
0
    ToLinearF[2048] = ToLinearF[2047];
548
549
0
    for (i = 0; i < TSIZEP1; i++)  {
550
0
  v = ToLinearF[i]*65535.0 + 0.5;
551
0
  ToLinear16[i] = (v > 65535.0) ? 65535 : (uint16_t)v;
552
0
  v = ToLinearF[i]*255.0  + 0.5;
553
0
  ToLinear8[i]  = (v > 255.0) ? 255 : (unsigned char)v;
554
0
    }
555
556
0
    j = 0;
557
0
    for (i = 0; i < lt2size; i++)  {
558
0
  if ((i*linstep)*(i*linstep) > ToLinearF[j]*ToLinearF[j+1])
559
0
      j++;
560
0
  FromLT2[i] = (uint16_t)j;
561
0
    }
562
563
    /*
564
     * Since we lose info anyway on 16-bit data, we set up a 14-bit
565
     * table and shift 16-bit values down two bits on input.
566
     * saves a little table space.
567
     */
568
0
    j = 0;
569
0
    for (i = 0; i < 16384; i++)  {
570
0
  while ((i/16383.)*(i/16383.) > ToLinearF[j]*ToLinearF[j+1])
571
0
      j++;
572
0
  From14[i] = (uint16_t)j;
573
0
    }
574
575
0
    j = 0;
576
0
    for (i = 0; i < 256; i++)  {
577
0
  while ((i/255.)*(i/255.) > ToLinearF[j]*ToLinearF[j+1])
578
0
      j++;
579
0
  From8[i] = (uint16_t)j;
580
0
    }
581
582
0
    Fltsize = (float)(lt2size/2);
583
584
0
    sp->ToLinearF = ToLinearF;
585
0
    sp->ToLinear16 = ToLinear16;
586
0
    sp->ToLinear8 = ToLinear8;
587
0
    sp->FromLT2 = FromLT2;
588
0
    sp->From14 = From14;
589
0
    sp->From8 = From8;
590
591
0
    return 1;
592
0
}
593
594
0
#define DecoderState(tif) ((PixarLogState*) (tif)->tif_data)
595
0
#define EncoderState(tif) ((PixarLogState*) (tif)->tif_data)
596
597
static int PixarLogEncode(TIFF* tif, uint8_t* bp, tmsize_t cc, uint16_t s);
598
static int PixarLogDecode(TIFF* tif, uint8_t* op, tmsize_t occ, uint16_t s);
599
600
0
#define PIXARLOGDATAFMT_UNKNOWN -1
601
602
static int
603
PixarLogGuessDataFmt(TIFFDirectory *td)
604
0
{
605
0
  int guess = PIXARLOGDATAFMT_UNKNOWN;
606
0
  int format = td->td_sampleformat;
607
608
  /* If the user didn't tell us his datafmt,
609
   * take our best guess from the bitspersample.
610
   */
611
0
  switch (td->td_bitspersample) {
612
0
   case 32:
613
0
    if (format == SAMPLEFORMAT_IEEEFP)
614
0
      guess = PIXARLOGDATAFMT_FLOAT;
615
0
    break;
616
0
   case 16:
617
0
    if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT)
618
0
      guess = PIXARLOGDATAFMT_16BIT;
619
0
    break;
620
0
   case 12:
621
0
    if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_INT)
622
0
      guess = PIXARLOGDATAFMT_12BITPICIO;
623
0
    break;
624
0
   case 11:
625
0
    if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT)
626
0
      guess = PIXARLOGDATAFMT_11BITLOG;
627
0
    break;
628
0
   case 8:
629
0
    if (format == SAMPLEFORMAT_VOID || format == SAMPLEFORMAT_UINT)
630
0
      guess = PIXARLOGDATAFMT_8BIT;
631
0
    break;
632
0
  }
633
634
0
  return guess;
635
0
}
636
637
static tmsize_t
638
multiply_ms(tmsize_t m1, tmsize_t m2)
639
0
{
640
0
        return _TIFFMultiplySSize(NULL, m1, m2, NULL);
641
0
}
642
643
static tmsize_t
644
add_ms(tmsize_t m1, tmsize_t m2)
645
0
{
646
0
        assert(m1 >= 0 && m2 >= 0);
647
  /* if either input is zero, assume overflow already occurred */
648
0
  if (m1 == 0 || m2 == 0)
649
0
    return 0;
650
0
  else if (m1 > TIFF_TMSIZE_T_MAX - m2)
651
0
    return 0;
652
653
0
  return m1 + m2;
654
0
}
655
656
static int
657
PixarLogFixupTags(TIFF* tif)
658
0
{
659
0
  (void) tif;
660
0
  return (1);
661
0
}
662
663
static int
664
PixarLogSetupDecode(TIFF* tif)
665
0
{
666
0
  static const char module[] = "PixarLogSetupDecode";
667
0
  TIFFDirectory *td = &tif->tif_dir;
668
0
  PixarLogState* sp = DecoderState(tif);
669
0
  tmsize_t tbuf_size;
670
0
        uint32_t strip_height;
671
672
0
  assert(sp != NULL);
673
674
  /* This function can possibly be called several times by */
675
  /* PredictorSetupDecode() if this function succeeds but */
676
  /* PredictorSetup() fails */
677
0
  if( (sp->state & PLSTATE_INIT) != 0 )
678
0
    return 1;
679
680
0
        strip_height = td->td_rowsperstrip;
681
0
        if( strip_height > td->td_imagelength )
682
0
            strip_height = td->td_imagelength;
683
684
  /* Make sure no byte swapping happens on the data
685
   * after decompression. */
686
0
  tif->tif_postdecode = _TIFFNoPostDecode;  
687
688
  /* for some reason, we can't do this in TIFFInitPixarLog */
689
690
0
  sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ?
691
0
      td->td_samplesperpixel : 1);
692
0
  tbuf_size = multiply_ms(multiply_ms(multiply_ms(sp->stride, td->td_imagewidth),
693
0
              strip_height), sizeof(uint16_t));
694
  /* add one more stride in case input ends mid-stride */
695
0
  tbuf_size = add_ms(tbuf_size, sizeof(uint16_t) * sp->stride);
696
0
  if (tbuf_size == 0)
697
0
    return (0);   /* TODO: this is an error return without error report through TIFFErrorExt */
698
0
  sp->tbuf = (uint16_t *) _TIFFmalloc(tbuf_size);
699
0
  if (sp->tbuf == NULL)
700
0
    return (0);
701
0
  sp->tbuf_size = tbuf_size;
702
0
  if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN)
703
0
    sp->user_datafmt = PixarLogGuessDataFmt(td);
704
0
  if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) {
705
0
                _TIFFfree(sp->tbuf);
706
0
                sp->tbuf = NULL;
707
0
                sp->tbuf_size = 0;
708
0
    TIFFErrorExt(tif->tif_clientdata, module,
709
0
      "PixarLog compression can't handle bits depth/data format combination (depth: %"PRIu16")",
710
0
      td->td_bitspersample);
711
0
    return (0);
712
0
  }
713
714
0
  if (inflateInit(&sp->stream) != Z_OK) {
715
0
                _TIFFfree(sp->tbuf);
716
0
                sp->tbuf = NULL;
717
0
                sp->tbuf_size = 0;
718
0
    TIFFErrorExt(tif->tif_clientdata, module, "%s", sp->stream.msg ? sp->stream.msg : "(null)");
719
0
    return (0);
720
0
  } else {
721
0
    sp->state |= PLSTATE_INIT;
722
0
    return (1);
723
0
  }
724
0
}
725
726
/*
727
 * Setup state for decoding a strip.
728
 */
729
static int
730
PixarLogPreDecode(TIFF* tif, uint16_t s)
731
0
{
732
0
  static const char module[] = "PixarLogPreDecode";
733
0
  PixarLogState* sp = DecoderState(tif);
734
735
0
  (void) s;
736
0
  assert(sp != NULL);
737
0
  sp->stream.next_in = tif->tif_rawdata;
738
0
  assert(sizeof(sp->stream.avail_in)==4);  /* if this assert gets raised,
739
      we need to simplify this code to reflect a ZLib that is likely updated
740
      to deal with 8byte memory sizes, though this code will respond
741
      appropriately even before we simplify it */
742
0
  sp->stream.avail_in = (uInt) tif->tif_rawcc;
743
0
  if ((tmsize_t)sp->stream.avail_in != tif->tif_rawcc)
744
0
  {
745
0
    TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size");
746
0
    return (0);
747
0
  }
748
0
  return (inflateReset(&sp->stream) == Z_OK);
749
0
}
750
751
static int
752
PixarLogDecode(TIFF* tif, uint8_t* op, tmsize_t occ, uint16_t s)
753
0
{
754
0
  static const char module[] = "PixarLogDecode";
755
0
  TIFFDirectory *td = &tif->tif_dir;
756
0
  PixarLogState* sp = DecoderState(tif);
757
0
  tmsize_t i;
758
0
  tmsize_t nsamples;
759
0
  int llen;
760
0
  uint16_t *up;
761
762
0
  switch (sp->user_datafmt) {
763
0
  case PIXARLOGDATAFMT_FLOAT:
764
0
    nsamples = occ / sizeof(float); /* XXX float == 32 bits */
765
0
    break;
766
0
  case PIXARLOGDATAFMT_16BIT:
767
0
  case PIXARLOGDATAFMT_12BITPICIO:
768
0
  case PIXARLOGDATAFMT_11BITLOG:
769
0
    nsamples = occ / sizeof(uint16_t); /* XXX uint16_t == 16 bits */
770
0
    break;
771
0
  case PIXARLOGDATAFMT_8BIT:
772
0
  case PIXARLOGDATAFMT_8BITABGR:
773
0
    nsamples = occ;
774
0
    break;
775
0
  default:
776
0
    TIFFErrorExt(tif->tif_clientdata, module,
777
0
      "%"PRIu16" bit input not supported in PixarLog",
778
0
      td->td_bitspersample);
779
0
    return 0;
780
0
  }
781
782
0
  llen = sp->stride * td->td_imagewidth;
783
784
0
  (void) s;
785
0
  assert(sp != NULL);
786
787
0
        sp->stream.next_in = tif->tif_rawcp;
788
0
  sp->stream.avail_in = (uInt) tif->tif_rawcc;
789
790
0
  sp->stream.next_out = (unsigned char *) sp->tbuf;
791
0
  assert(sizeof(sp->stream.avail_out)==4);  /* if this assert gets raised,
792
      we need to simplify this code to reflect a ZLib that is likely updated
793
      to deal with 8byte memory sizes, though this code will respond
794
      appropriately even before we simplify it */
795
0
  sp->stream.avail_out = (uInt) (nsamples * sizeof(uint16_t));
796
0
  if (sp->stream.avail_out != nsamples * sizeof(uint16_t))
797
0
  {
798
0
    TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size");
799
0
    return (0);
800
0
  }
801
  /* Check that we will not fill more than what was allocated */
802
0
  if ((tmsize_t)sp->stream.avail_out > sp->tbuf_size)
803
0
  {
804
0
    TIFFErrorExt(tif->tif_clientdata, module, "sp->stream.avail_out > sp->tbuf_size");
805
0
    return (0);
806
0
  }
807
0
  do {
808
0
    int state = inflate(&sp->stream, Z_PARTIAL_FLUSH);
809
0
    if (state == Z_STREAM_END) {
810
0
      break;      /* XXX */
811
0
    }
812
0
    if (state == Z_DATA_ERROR) {
813
0
      TIFFErrorExt(tif->tif_clientdata, module,
814
0
          "Decoding error at scanline %"PRIu32", %s",
815
0
          tif->tif_row, sp->stream.msg ? sp->stream.msg : "(null)");
816
0
      return (0);
817
0
    }
818
0
    if (state != Z_OK) {
819
0
      TIFFErrorExt(tif->tif_clientdata, module, "ZLib error: %s",
820
0
          sp->stream.msg ? sp->stream.msg : "(null)");
821
0
      return (0);
822
0
    }
823
0
  } while (sp->stream.avail_out > 0);
824
825
  /* hopefully, we got all the bytes we needed */
826
0
  if (sp->stream.avail_out != 0) {
827
0
    TIFFErrorExt(tif->tif_clientdata, module,
828
0
        "Not enough data at scanline %"PRIu32" (short %u bytes)",
829
0
        tif->tif_row, sp->stream.avail_out);
830
0
    return (0);
831
0
  }
832
833
0
        tif->tif_rawcp = sp->stream.next_in;
834
0
        tif->tif_rawcc = sp->stream.avail_in;
835
836
0
  up = sp->tbuf;
837
  /* Swap bytes in the data if from a different endian machine. */
838
0
  if (tif->tif_flags & TIFF_SWAB)
839
0
    TIFFSwabArrayOfShort(up, nsamples);
840
841
  /*
842
   * if llen is not an exact multiple of nsamples, the decode operation
843
   * may overflow the output buffer, so truncate it enough to prevent
844
   * that but still salvage as much data as possible.
845
   */
846
0
  if (nsamples % llen) { 
847
0
    TIFFWarningExt(tif->tif_clientdata, module,
848
0
      "stride %d is not a multiple of sample count, "
849
0
            "%"TIFF_SSIZE_FORMAT", data truncated.", llen, nsamples);
850
0
    nsamples -= nsamples % llen;
851
0
  }
852
853
0
  for (i = 0; i < nsamples; i += llen, up += llen) {
854
0
    switch (sp->user_datafmt)  {
855
0
    case PIXARLOGDATAFMT_FLOAT:
856
0
      horizontalAccumulateF(up, llen, sp->stride,
857
0
          (float *)op, sp->ToLinearF);
858
0
      op += llen * sizeof(float);
859
0
      break;
860
0
    case PIXARLOGDATAFMT_16BIT:
861
0
      horizontalAccumulate16(up, llen, sp->stride,
862
0
                                   (uint16_t *)op, sp->ToLinear16);
863
0
      op += llen * sizeof(uint16_t);
864
0
      break;
865
0
    case PIXARLOGDATAFMT_12BITPICIO:
866
0
      horizontalAccumulate12(up, llen, sp->stride,
867
0
                                   (int16_t *)op, sp->ToLinearF);
868
0
      op += llen * sizeof(int16_t);
869
0
      break;
870
0
    case PIXARLOGDATAFMT_11BITLOG:
871
0
      horizontalAccumulate11(up, llen, sp->stride,
872
0
          (uint16_t *)op);
873
0
      op += llen * sizeof(uint16_t);
874
0
      break;
875
0
    case PIXARLOGDATAFMT_8BIT:
876
0
      horizontalAccumulate8(up, llen, sp->stride,
877
0
          (unsigned char *)op, sp->ToLinear8);
878
0
      op += llen * sizeof(unsigned char);
879
0
      break;
880
0
    case PIXARLOGDATAFMT_8BITABGR:
881
0
      horizontalAccumulate8abgr(up, llen, sp->stride,
882
0
          (unsigned char *)op, sp->ToLinear8);
883
0
      op += llen * sizeof(unsigned char);
884
0
      break;
885
0
    default:
886
0
      TIFFErrorExt(tif->tif_clientdata, module,
887
0
          "Unsupported bits/sample: %"PRIu16,
888
0
          td->td_bitspersample);
889
0
      return (0);
890
0
    }
891
0
  }
892
893
0
  return (1);
894
0
}
895
896
static int
897
PixarLogSetupEncode(TIFF* tif)
898
0
{
899
0
  static const char module[] = "PixarLogSetupEncode";
900
0
  TIFFDirectory *td = &tif->tif_dir;
901
0
  PixarLogState* sp = EncoderState(tif);
902
0
  tmsize_t tbuf_size;
903
904
0
  assert(sp != NULL);
905
906
  /* for some reason, we can't do this in TIFFInitPixarLog */
907
908
0
  sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ?
909
0
      td->td_samplesperpixel : 1);
910
0
  tbuf_size = multiply_ms(multiply_ms(multiply_ms(sp->stride, td->td_imagewidth),
911
0
              td->td_rowsperstrip), sizeof(uint16_t));
912
0
  if (tbuf_size == 0)
913
0
    return (0);  /* TODO: this is an error return without error report through TIFFErrorExt */
914
0
  sp->tbuf = (uint16_t *) _TIFFmalloc(tbuf_size);
915
0
  if (sp->tbuf == NULL)
916
0
    return (0);
917
0
  if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN)
918
0
    sp->user_datafmt = PixarLogGuessDataFmt(td);
919
0
  if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN) {
920
0
    TIFFErrorExt(tif->tif_clientdata, module, "PixarLog compression can't handle %"PRIu16" bit linear encodings", td->td_bitspersample);
921
0
    return (0);
922
0
  }
923
924
0
  if (deflateInit(&sp->stream, sp->quality) != Z_OK) {
925
0
    TIFFErrorExt(tif->tif_clientdata, module, "%s", sp->stream.msg ? sp->stream.msg : "(null)");
926
0
    return (0);
927
0
  } else {
928
0
    sp->state |= PLSTATE_INIT;
929
0
    return (1);
930
0
  }
931
0
}
932
933
/*
934
 * Reset encoding state at the start of a strip.
935
 */
936
static int
937
PixarLogPreEncode(TIFF* tif, uint16_t s)
938
0
{
939
0
  static const char module[] = "PixarLogPreEncode";
940
0
  PixarLogState *sp = EncoderState(tif);
941
942
0
  (void) s;
943
0
  assert(sp != NULL);
944
0
  sp->stream.next_out = tif->tif_rawdata;
945
0
  assert(sizeof(sp->stream.avail_out)==4);  /* if this assert gets raised,
946
      we need to simplify this code to reflect a ZLib that is likely updated
947
      to deal with 8byte memory sizes, though this code will respond
948
      appropriately even before we simplify it */
949
0
  sp->stream.avail_out = (uInt)tif->tif_rawdatasize;
950
0
  if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize)
951
0
  {
952
0
    TIFFErrorExt(tif->tif_clientdata, module, "ZLib cannot deal with buffers this size");
953
0
    return (0);
954
0
  }
955
0
  return (deflateReset(&sp->stream) == Z_OK);
956
0
}
957
958
static void
959
horizontalDifferenceF(float *ip, int n, int stride, uint16_t *wp, uint16_t *FromLT2)
960
0
{
961
0
    int32_t r1, g1, b1, a1, r2, g2, b2, a2, mask;
962
0
    float fltsize = Fltsize;
963
964
0
#define  CLAMP(v) ( (v<(float)0.)   ? 0        \
965
0
      : (v<(float)2.)   ? FromLT2[(int)(v*fltsize)]  \
966
0
      : (v>(float)24.2) ? 2047      \
967
0
      : LogK1*log(v*LogK2) + 0.5 )
968
969
0
    mask = CODE_MASK;
970
0
    if (n >= stride) {
971
0
  if (stride == 3) {
972
0
      r2 = wp[0] = (uint16_t) CLAMP(ip[0]);
973
0
      g2 = wp[1] = (uint16_t) CLAMP(ip[1]);
974
0
      b2 = wp[2] = (uint16_t) CLAMP(ip[2]);
975
0
      n -= 3;
976
0
      while (n > 0) {
977
0
    n -= 3;
978
0
    wp += 3;
979
0
    ip += 3;
980
0
    r1 = (int32_t) CLAMP(ip[0]); wp[0] = (uint16_t)((r1 - r2) & mask); r2 = r1;
981
0
    g1 = (int32_t) CLAMP(ip[1]); wp[1] = (uint16_t)((g1 - g2) & mask); g2 = g1;
982
0
    b1 = (int32_t) CLAMP(ip[2]); wp[2] = (uint16_t)((b1 - b2) & mask); b2 = b1;
983
0
      }
984
0
  } else if (stride == 4) {
985
0
      r2 = wp[0] = (uint16_t) CLAMP(ip[0]);
986
0
      g2 = wp[1] = (uint16_t) CLAMP(ip[1]);
987
0
      b2 = wp[2] = (uint16_t) CLAMP(ip[2]);
988
0
      a2 = wp[3] = (uint16_t) CLAMP(ip[3]);
989
0
      n -= 4;
990
0
      while (n > 0) {
991
0
    n -= 4;
992
0
    wp += 4;
993
0
    ip += 4;
994
0
    r1 = (int32_t) CLAMP(ip[0]); wp[0] = (uint16_t)((r1 - r2) & mask); r2 = r1;
995
0
    g1 = (int32_t) CLAMP(ip[1]); wp[1] = (uint16_t)((g1 - g2) & mask); g2 = g1;
996
0
    b1 = (int32_t) CLAMP(ip[2]); wp[2] = (uint16_t)((b1 - b2) & mask); b2 = b1;
997
0
    a1 = (int32_t) CLAMP(ip[3]); wp[3] = (uint16_t)((a1 - a2) & mask); a2 = a1;
998
0
      }
999
0
  } else {
1000
0
        REPEAT(stride, wp[0] = (uint16_t) CLAMP(ip[0]); wp++; ip++)
1001
0
        n -= stride;
1002
0
        while (n > 0) {
1003
0
            REPEAT(stride,
1004
0
                wp[0] = (uint16_t)(((int32_t)CLAMP(ip[0]) - (int32_t)CLAMP(ip[-stride])) & mask);
1005
0
                wp++; ip++)
1006
0
            n -= stride;
1007
0
        }
1008
0
  }
1009
0
    }
1010
0
}
1011
1012
static void
1013
horizontalDifference16(unsigned short *ip, int n, int stride,
1014
                       unsigned short *wp, uint16_t *From14)
1015
0
{
1016
0
    register int  r1, g1, b1, a1, r2, g2, b2, a2, mask;
1017
1018
/* assumption is unsigned pixel values */
1019
0
#undef   CLAMP
1020
0
#define  CLAMP(v) From14[(v) >> 2]
1021
1022
0
    mask = CODE_MASK;
1023
0
    if (n >= stride) {
1024
0
  if (stride == 3) {
1025
0
      r2 = wp[0] = CLAMP(ip[0]);  g2 = wp[1] = CLAMP(ip[1]);
1026
0
      b2 = wp[2] = CLAMP(ip[2]);
1027
0
      n -= 3;
1028
0
      while (n > 0) {
1029
0
    n -= 3;
1030
0
    wp += 3;
1031
0
    ip += 3;
1032
0
    r1 = CLAMP(ip[0]); wp[0] = (uint16_t)((r1 - r2) & mask); r2 = r1;
1033
0
    g1 = CLAMP(ip[1]); wp[1] = (uint16_t)((g1 - g2) & mask); g2 = g1;
1034
0
    b1 = CLAMP(ip[2]); wp[2] = (uint16_t)((b1 - b2) & mask); b2 = b1;
1035
0
      }
1036
0
  } else if (stride == 4) {
1037
0
      r2 = wp[0] = CLAMP(ip[0]);  g2 = wp[1] = CLAMP(ip[1]);
1038
0
      b2 = wp[2] = CLAMP(ip[2]);  a2 = wp[3] = CLAMP(ip[3]);
1039
0
      n -= 4;
1040
0
      while (n > 0) {
1041
0
    n -= 4;
1042
0
    wp += 4;
1043
0
    ip += 4;
1044
0
    r1 = CLAMP(ip[0]); wp[0] = (uint16_t)((r1 - r2) & mask); r2 = r1;
1045
0
    g1 = CLAMP(ip[1]); wp[1] = (uint16_t)((g1 - g2) & mask); g2 = g1;
1046
0
    b1 = CLAMP(ip[2]); wp[2] = (uint16_t)((b1 - b2) & mask); b2 = b1;
1047
0
    a1 = CLAMP(ip[3]); wp[3] = (uint16_t)((a1 - a2) & mask); a2 = a1;
1048
0
      }
1049
0
  } else {
1050
0
        REPEAT(stride, wp[0] = CLAMP(ip[0]); wp++; ip++)
1051
0
      n -= stride;
1052
0
      while (n > 0) {
1053
0
            REPEAT(stride,
1054
0
                wp[0] = (uint16_t)((CLAMP(ip[0]) - CLAMP(ip[-stride])) & mask);
1055
0
                wp++; ip++)
1056
0
            n -= stride;
1057
0
        }
1058
0
  }
1059
0
    }
1060
0
}
1061
1062
1063
static void
1064
horizontalDifference8(unsigned char *ip, int n, int stride,
1065
                      unsigned short *wp, uint16_t *From8)
1066
0
{
1067
0
    register int  r1, g1, b1, a1, r2, g2, b2, a2, mask;
1068
1069
0
#undef   CLAMP
1070
0
#define  CLAMP(v) (From8[(v)])
1071
1072
0
    mask = CODE_MASK;
1073
0
    if (n >= stride) {
1074
0
  if (stride == 3) {
1075
0
      r2 = wp[0] = CLAMP(ip[0]);  g2 = wp[1] = CLAMP(ip[1]);
1076
0
      b2 = wp[2] = CLAMP(ip[2]);
1077
0
      n -= 3;
1078
0
      while (n > 0) {
1079
0
    n -= 3;
1080
0
    r1 = CLAMP(ip[3]); wp[3] = (uint16_t)((r1 - r2) & mask); r2 = r1;
1081
0
    g1 = CLAMP(ip[4]); wp[4] = (uint16_t)((g1 - g2) & mask); g2 = g1;
1082
0
    b1 = CLAMP(ip[5]); wp[5] = (uint16_t)((b1 - b2) & mask); b2 = b1;
1083
0
    wp += 3;
1084
0
    ip += 3;
1085
0
      }
1086
0
  } else if (stride == 4) {
1087
0
      r2 = wp[0] = CLAMP(ip[0]);  g2 = wp[1] = CLAMP(ip[1]);
1088
0
      b2 = wp[2] = CLAMP(ip[2]);  a2 = wp[3] = CLAMP(ip[3]);
1089
0
      n -= 4;
1090
0
      while (n > 0) {
1091
0
    n -= 4;
1092
0
    r1 = CLAMP(ip[4]); wp[4] = (uint16_t)((r1 - r2) & mask); r2 = r1;
1093
0
    g1 = CLAMP(ip[5]); wp[5] = (uint16_t)((g1 - g2) & mask); g2 = g1;
1094
0
    b1 = CLAMP(ip[6]); wp[6] = (uint16_t)((b1 - b2) & mask); b2 = b1;
1095
0
    a1 = CLAMP(ip[7]); wp[7] = (uint16_t)((a1 - a2) & mask); a2 = a1;
1096
0
    wp += 4;
1097
0
    ip += 4;
1098
0
      }
1099
0
  } else {
1100
0
        REPEAT(stride, wp[0] = CLAMP(ip[0]); wp++; ip++)
1101
0
        n -= stride;
1102
0
        while (n > 0) {
1103
0
            REPEAT(stride,
1104
0
                wp[0] = (uint16_t)((CLAMP(ip[0]) - CLAMP(ip[-stride])) & mask);
1105
0
                wp++; ip++)
1106
0
            n -= stride;
1107
0
        }
1108
0
    }
1109
0
    }
1110
0
}
1111
1112
/*
1113
 * Encode a chunk of pixels.
1114
 */
1115
static int
1116
PixarLogEncode(TIFF* tif, uint8_t* bp, tmsize_t cc, uint16_t s)
1117
0
{
1118
0
  static const char module[] = "PixarLogEncode";
1119
0
  TIFFDirectory *td = &tif->tif_dir;
1120
0
  PixarLogState *sp = EncoderState(tif);
1121
0
  tmsize_t i;
1122
0
  tmsize_t n;
1123
0
  int llen;
1124
0
  unsigned short * up;
1125
1126
0
  (void) s;
1127
1128
0
  switch (sp->user_datafmt) {
1129
0
  case PIXARLOGDATAFMT_FLOAT:
1130
0
    n = cc / sizeof(float);   /* XXX float == 32 bits */
1131
0
    break;
1132
0
  case PIXARLOGDATAFMT_16BIT:
1133
0
  case PIXARLOGDATAFMT_12BITPICIO:
1134
0
  case PIXARLOGDATAFMT_11BITLOG:
1135
0
    n = cc / sizeof(uint16_t);  /* XXX uint16_t == 16 bits */
1136
0
    break;
1137
0
  case PIXARLOGDATAFMT_8BIT:
1138
0
  case PIXARLOGDATAFMT_8BITABGR:
1139
0
    n = cc;
1140
0
    break;
1141
0
  default:
1142
0
    TIFFErrorExt(tif->tif_clientdata, module,
1143
0
      "%"PRIu16" bit input not supported in PixarLog",
1144
0
      td->td_bitspersample);
1145
0
    return 0;
1146
0
  }
1147
1148
0
  llen = sp->stride * td->td_imagewidth;
1149
    /* Check against the number of elements (of size uint16_t) of sp->tbuf */
1150
0
    if( n > ((tmsize_t)td->td_rowsperstrip * llen) )
1151
0
    {
1152
0
        TIFFErrorExt(tif->tif_clientdata, module,
1153
0
                     "Too many input bytes provided");
1154
0
        return 0;
1155
0
    }
1156
1157
0
  for (i = 0, up = sp->tbuf; i < n; i += llen, up += llen) {
1158
0
    switch (sp->user_datafmt)  {
1159
0
    case PIXARLOGDATAFMT_FLOAT:
1160
0
      horizontalDifferenceF((float *)bp, llen, 
1161
0
        sp->stride, up, sp->FromLT2);
1162
0
      bp += llen * sizeof(float);
1163
0
      break;
1164
0
    case PIXARLOGDATAFMT_16BIT:
1165
0
      horizontalDifference16((uint16_t *)bp, llen,
1166
0
                                   sp->stride, up, sp->From14);
1167
0
      bp += llen * sizeof(uint16_t);
1168
0
      break;
1169
0
    case PIXARLOGDATAFMT_8BIT:
1170
0
      horizontalDifference8((unsigned char *)bp, llen, 
1171
0
        sp->stride, up, sp->From8);
1172
0
      bp += llen * sizeof(unsigned char);
1173
0
      break;
1174
0
    default:
1175
0
      TIFFErrorExt(tif->tif_clientdata, module,
1176
0
        "%"PRIu16" bit input not supported in PixarLog",
1177
0
        td->td_bitspersample);
1178
0
      return 0;
1179
0
    }
1180
0
  }
1181
 
1182
0
  sp->stream.next_in = (unsigned char *) sp->tbuf;
1183
0
  assert(sizeof(sp->stream.avail_in)==4);  /* if this assert gets raised,
1184
      we need to simplify this code to reflect a ZLib that is likely updated
1185
      to deal with 8byte memory sizes, though this code will respond
1186
      appropriately even before we simplify it */
1187
0
  sp->stream.avail_in = (uInt) (n * sizeof(uint16_t));
1188
0
  if ((sp->stream.avail_in / sizeof(uint16_t)) != (uInt) n)
1189
0
  {
1190
0
    TIFFErrorExt(tif->tif_clientdata, module,
1191
0
           "ZLib cannot deal with buffers this size");
1192
0
    return (0);
1193
0
  }
1194
1195
0
  do {
1196
0
    if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) {
1197
0
      TIFFErrorExt(tif->tif_clientdata, module, "Encoder error: %s",
1198
0
          sp->stream.msg ? sp->stream.msg : "(null)");
1199
0
      return (0);
1200
0
    }
1201
0
    if (sp->stream.avail_out == 0) {
1202
0
      tif->tif_rawcc = tif->tif_rawdatasize;
1203
0
      if (!TIFFFlushData1(tif))
1204
0
        return 0;
1205
0
      sp->stream.next_out = tif->tif_rawdata;
1206
0
      sp->stream.avail_out = (uInt) tif->tif_rawdatasize;  /* this is a safe typecast, as check is made already in PixarLogPreEncode */
1207
0
    }
1208
0
  } while (sp->stream.avail_in > 0);
1209
0
  return (1);
1210
0
}
1211
1212
/*
1213
 * Finish off an encoded strip by flushing the last
1214
 * string and tacking on an End Of Information code.
1215
 */
1216
1217
static int
1218
PixarLogPostEncode(TIFF* tif)
1219
0
{
1220
0
  static const char module[] = "PixarLogPostEncode";
1221
0
  PixarLogState *sp = EncoderState(tif);
1222
0
  int state;
1223
1224
0
  sp->stream.avail_in = 0;
1225
1226
0
  do {
1227
0
    state = deflate(&sp->stream, Z_FINISH);
1228
0
    switch (state) {
1229
0
    case Z_STREAM_END:
1230
0
    case Z_OK:
1231
0
        if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize) {
1232
0
          tif->tif_rawcc =
1233
0
        tif->tif_rawdatasize - sp->stream.avail_out;
1234
0
          if (!TIFFFlushData1(tif))
1235
0
                                return 0;
1236
0
          sp->stream.next_out = tif->tif_rawdata;
1237
0
          sp->stream.avail_out = (uInt) tif->tif_rawdatasize;  /* this is a safe typecast, as check is made already in PixarLogPreEncode */
1238
0
        }
1239
0
        break;
1240
0
    default:
1241
0
      TIFFErrorExt(tif->tif_clientdata, module, "ZLib error: %s",
1242
0
      sp->stream.msg ? sp->stream.msg : "(null)");
1243
0
        return (0);
1244
0
    }
1245
0
  } while (state != Z_STREAM_END);
1246
0
  return (1);
1247
0
}
1248
1249
static void
1250
PixarLogClose(TIFF* tif)
1251
0
{
1252
0
        PixarLogState* sp = (PixarLogState*) tif->tif_data;
1253
0
  TIFFDirectory *td = &tif->tif_dir;
1254
1255
0
  assert(sp != 0);
1256
  /* In a really sneaky (and really incorrect, and untruthful, and
1257
   * troublesome, and error-prone) maneuver that completely goes against
1258
   * the spirit of TIFF, and breaks TIFF, on close, we covertly
1259
   * modify both bitspersample and sampleformat in the directory to
1260
   * indicate 8-bit linear.  This way, the decode "just works" even for
1261
   * readers that don't know about PixarLog, or how to set
1262
   * the PIXARLOGDATFMT pseudo-tag.
1263
   */
1264
1265
0
        if (sp->state&PLSTATE_INIT) {
1266
            /* We test the state to avoid an issue such as in
1267
             * http://bugzilla.maptools.org/show_bug.cgi?id=2604
1268
             * What appends in that case is that the bitspersample is 1 and
1269
             * a TransferFunction is set. The size of the TransferFunction
1270
             * depends on 1<<bitspersample. So if we increase it, an access
1271
             * out of the buffer will happen at directory flushing.
1272
             * Another option would be to clear those targs. 
1273
             */
1274
0
            td->td_bitspersample = 8;
1275
0
            td->td_sampleformat = SAMPLEFORMAT_UINT;
1276
0
        }
1277
0
}
1278
1279
static void
1280
PixarLogCleanup(TIFF* tif)
1281
0
{
1282
0
  PixarLogState* sp = (PixarLogState*) tif->tif_data;
1283
1284
0
  assert(sp != 0);
1285
1286
0
  (void)TIFFPredictorCleanup(tif);
1287
1288
0
  tif->tif_tagmethods.vgetfield = sp->vgetparent;
1289
0
  tif->tif_tagmethods.vsetfield = sp->vsetparent;
1290
1291
0
  if (sp->FromLT2) _TIFFfree(sp->FromLT2);
1292
0
  if (sp->From14) _TIFFfree(sp->From14);
1293
0
  if (sp->From8) _TIFFfree(sp->From8);
1294
0
  if (sp->ToLinearF) _TIFFfree(sp->ToLinearF);
1295
0
  if (sp->ToLinear16) _TIFFfree(sp->ToLinear16);
1296
0
  if (sp->ToLinear8) _TIFFfree(sp->ToLinear8);
1297
0
  if (sp->state&PLSTATE_INIT) {
1298
0
    if (tif->tif_mode == O_RDONLY)
1299
0
      inflateEnd(&sp->stream);
1300
0
    else
1301
0
      deflateEnd(&sp->stream);
1302
0
  }
1303
0
  if (sp->tbuf)
1304
0
    _TIFFfree(sp->tbuf);
1305
0
  _TIFFfree(sp);
1306
0
  tif->tif_data = NULL;
1307
1308
0
  _TIFFSetDefaultCompressionState(tif);
1309
0
}
1310
1311
static int
1312
PixarLogVSetField(TIFF* tif, uint32_t tag, va_list ap)
1313
0
{
1314
0
    static const char module[] = "PixarLogVSetField";
1315
0
    PixarLogState *sp = (PixarLogState *)tif->tif_data;
1316
0
    int result;
1317
1318
0
    switch (tag) {
1319
0
     case TIFFTAG_PIXARLOGQUALITY:
1320
0
    sp->quality = (int) va_arg(ap, int);
1321
0
    if (tif->tif_mode != O_RDONLY && (sp->state&PLSTATE_INIT)) {
1322
0
      if (deflateParams(&sp->stream,
1323
0
          sp->quality, Z_DEFAULT_STRATEGY) != Z_OK) {
1324
0
        TIFFErrorExt(tif->tif_clientdata, module, "ZLib error: %s",
1325
0
          sp->stream.msg ? sp->stream.msg : "(null)");
1326
0
        return (0);
1327
0
      }
1328
0
    }
1329
0
    return (1);
1330
0
     case TIFFTAG_PIXARLOGDATAFMT:
1331
0
  sp->user_datafmt = (int) va_arg(ap, int);
1332
  /* Tweak the TIFF header so that the rest of libtiff knows what
1333
   * size of data will be passed between app and library, and
1334
   * assume that the app knows what it is doing and is not
1335
   * confused by these header manipulations...
1336
   */
1337
0
  switch (sp->user_datafmt) {
1338
0
   case PIXARLOGDATAFMT_8BIT:
1339
0
   case PIXARLOGDATAFMT_8BITABGR:
1340
0
      TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
1341
0
      TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
1342
0
      break;
1343
0
   case PIXARLOGDATAFMT_11BITLOG:
1344
0
      TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
1345
0
      TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
1346
0
      break;
1347
0
   case PIXARLOGDATAFMT_12BITPICIO:
1348
0
      TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
1349
0
      TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT);
1350
0
      break;
1351
0
   case PIXARLOGDATAFMT_16BIT:
1352
0
      TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
1353
0
      TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
1354
0
      break;
1355
0
   case PIXARLOGDATAFMT_FLOAT:
1356
0
      TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32);
1357
0
      TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
1358
0
      break;
1359
0
  }
1360
  /*
1361
   * Must recalculate sizes should bits/sample change.
1362
   */
1363
0
  tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tmsize_t)(-1);
1364
0
  tif->tif_scanlinesize = TIFFScanlineSize(tif);
1365
0
  result = 1;   /* NB: pseudo tag */
1366
0
  break;
1367
0
     default:
1368
0
  result = (*sp->vsetparent)(tif, tag, ap);
1369
0
    }
1370
0
    return (result);
1371
0
}
1372
1373
static int
1374
PixarLogVGetField(TIFF* tif, uint32_t tag, va_list ap)
1375
0
{
1376
0
    PixarLogState *sp = (PixarLogState *)tif->tif_data;
1377
1378
0
    switch (tag) {
1379
0
     case TIFFTAG_PIXARLOGQUALITY:
1380
0
  *va_arg(ap, int*) = sp->quality;
1381
0
  break;
1382
0
     case TIFFTAG_PIXARLOGDATAFMT:
1383
0
  *va_arg(ap, int*) = sp->user_datafmt;
1384
0
  break;
1385
0
     default:
1386
0
  return (*sp->vgetparent)(tif, tag, ap);
1387
0
    }
1388
0
    return (1);
1389
0
}
1390
1391
static const TIFFField pixarlogFields[] = {
1392
    {TIFFTAG_PIXARLOGDATAFMT, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, FALSE, FALSE, "", NULL},
1393
    {TIFFTAG_PIXARLOGQUALITY, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT, TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, FALSE, FALSE, "", NULL}
1394
};
1395
1396
int
1397
TIFFInitPixarLog(TIFF* tif, int scheme)
1398
0
{
1399
0
  static const char module[] = "TIFFInitPixarLog";
1400
1401
0
  PixarLogState* sp;
1402
1403
0
        (void)scheme;
1404
0
  assert(scheme == COMPRESSION_PIXARLOG);
1405
1406
  /*
1407
   * Merge codec-specific tag information.
1408
   */
1409
0
  if (!_TIFFMergeFields(tif, pixarlogFields,
1410
0
            TIFFArrayCount(pixarlogFields))) {
1411
0
    TIFFErrorExt(tif->tif_clientdata, module,
1412
0
           "Merging PixarLog codec-specific tags failed");
1413
0
    return 0;
1414
0
  }
1415
1416
  /*
1417
   * Allocate state block so tag methods have storage to record values.
1418
   */
1419
0
  tif->tif_data = (uint8_t*) _TIFFmalloc(sizeof (PixarLogState));
1420
0
  if (tif->tif_data == NULL)
1421
0
    goto bad;
1422
0
  sp = (PixarLogState*) tif->tif_data;
1423
0
  _TIFFmemset(sp, 0, sizeof (*sp));
1424
0
  sp->stream.data_type = Z_BINARY;
1425
0
  sp->user_datafmt = PIXARLOGDATAFMT_UNKNOWN;
1426
1427
  /*
1428
   * Install codec methods.
1429
   */
1430
0
  tif->tif_fixuptags = PixarLogFixupTags; 
1431
0
  tif->tif_setupdecode = PixarLogSetupDecode;
1432
0
  tif->tif_predecode = PixarLogPreDecode;
1433
0
  tif->tif_decoderow = PixarLogDecode;
1434
0
  tif->tif_decodestrip = PixarLogDecode;  
1435
0
  tif->tif_decodetile = PixarLogDecode;
1436
0
  tif->tif_setupencode = PixarLogSetupEncode;
1437
0
  tif->tif_preencode = PixarLogPreEncode;
1438
0
  tif->tif_postencode = PixarLogPostEncode;
1439
0
  tif->tif_encoderow = PixarLogEncode;  
1440
0
  tif->tif_encodestrip = PixarLogEncode;
1441
0
  tif->tif_encodetile = PixarLogEncode;  
1442
0
  tif->tif_close = PixarLogClose;
1443
0
  tif->tif_cleanup = PixarLogCleanup;
1444
1445
  /* Override SetField so we can handle our private pseudo-tag */
1446
0
  sp->vgetparent = tif->tif_tagmethods.vgetfield;
1447
0
  tif->tif_tagmethods.vgetfield = PixarLogVGetField;   /* hook for codec tags */
1448
0
  sp->vsetparent = tif->tif_tagmethods.vsetfield;
1449
0
  tif->tif_tagmethods.vsetfield = PixarLogVSetField;   /* hook for codec tags */
1450
1451
  /* Default values for codec-specific fields */
1452
0
  sp->quality = Z_DEFAULT_COMPRESSION; /* default comp. level */
1453
0
  sp->state = 0;
1454
1455
  /* we don't wish to use the predictor, 
1456
   * the default is none, which predictor value 1
1457
   */
1458
0
  (void) TIFFPredictorInit(tif);
1459
1460
  /*
1461
   * build the companding tables 
1462
   */
1463
0
  PixarLogMakeTables(sp);
1464
1465
0
  return (1);
1466
0
bad:
1467
0
  TIFFErrorExt(tif->tif_clientdata, module,
1468
0
         "No space for PixarLog state block");
1469
0
  return (0);
1470
0
}
1471
#endif /* PIXARLOG_SUPPORT */
1472
1473
/* vim: set ts=8 sts=8 sw=8 noet: */
1474
/*
1475
 * Local Variables:
1476
 * mode: c
1477
 * c-basic-offset: 8
1478
 * fill-column: 78
1479
 * End:
1480
 */