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