~ubuntu-branches/ubuntu/karmic/tiff/karmic-security

« back to all changes in this revision

Viewing changes to libtiff/tif_pixarlog.c

  • Committer: Bazaar Package Importer
  • Author(s): Fabio M. Di Nitto
  • Date: 2004-10-14 07:57:59 UTC
  • Revision ID: james.westby@ubuntu.com-20041014075759-a77e7zuaetya8cp0
Tags: upstream-3.6.1
ImportĀ upstreamĀ versionĀ 3.6.1

Show diffs side-by-side

added added

removed removed

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