xref: /aosp_15_r20/external/pdfium/third_party/libtiff/tif_pixarlog.c (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
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 
horizontalAccumulateF(uint16_t * wp,int n,int stride,float * op,float * ToLinearF)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 
horizontalAccumulate12(uint16_t * wp,int n,int stride,int16_t * op,float * ToLinearF)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 
horizontalAccumulate16(uint16_t * wp,int n,int stride,uint16_t * op,uint16_t * ToLinear16)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  */
horizontalAccumulate11(uint16_t * wp,int n,int stride,uint16_t * op)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 
horizontalAccumulate8(uint16_t * wp,int n,int stride,unsigned char * op,unsigned char * ToLinear8)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 
horizontalAccumulate8abgr(uint16_t * wp,int n,int stride,unsigned char * op,unsigned char * ToLinear8)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 
PixarLogMakeTables(TIFF * tif,PixarLogState * sp)547 static int PixarLogMakeTables(TIFF *tif, PixarLogState *sp)
548 {
549 
550     /*
551      *    We make several tables here to convert between various external
552      *    representations (float, 16-bit, and 8-bit) and the internal
553      *    11-bit companded representation.  The 11-bit representation has two
554      *    distinct regions.  A linear bottom end up through .018316 in steps
555      *    of about .000073, and a region of constant ratio up to about 25.
556      *    These floating point numbers are stored in the main table ToLinearF.
557      *    All other tables are derived from this one.  The tables (and the
558      *    ratios) are continuous at the internal seam.
559      */
560 
561     int nlin, lt2size;
562     int i, j;
563     double b, c, linstep, v;
564     float *ToLinearF;
565     uint16_t *ToLinear16;
566     unsigned char *ToLinear8;
567     uint16_t *FromLT2;
568     uint16_t *From14; /* Really for 16-bit data, but we shift down 2 */
569     uint16_t *From8;
570 
571     c = log(RATIO);
572     nlin = (int)(1. / c); /* nlin must be an integer */
573     c = 1. / nlin;
574     b = exp(-c * ONE); /* multiplicative scale factor [b*exp(c*ONE) = 1] */
575     linstep = b * c * exp(1.);
576 
577     LogK1 = (float)(1. / c); /* if (v >= 2)  token = k1*log(v*k2) */
578     LogK2 = (float)(1. / b);
579     lt2size = (int)(2. / linstep) + 1;
580     FromLT2 = (uint16_t *)_TIFFmallocExt(tif, lt2size * sizeof(uint16_t));
581     From14 = (uint16_t *)_TIFFmallocExt(tif, 16384 * sizeof(uint16_t));
582     From8 = (uint16_t *)_TIFFmallocExt(tif, 256 * sizeof(uint16_t));
583     ToLinearF = (float *)_TIFFmallocExt(tif, TSIZEP1 * sizeof(float));
584     ToLinear16 = (uint16_t *)_TIFFmallocExt(tif, TSIZEP1 * sizeof(uint16_t));
585     ToLinear8 =
586         (unsigned char *)_TIFFmallocExt(tif, TSIZEP1 * sizeof(unsigned char));
587     if (FromLT2 == NULL || From14 == NULL || From8 == NULL ||
588         ToLinearF == NULL || ToLinear16 == NULL || ToLinear8 == NULL)
589     {
590         if (FromLT2)
591             _TIFFfreeExt(tif, FromLT2);
592         if (From14)
593             _TIFFfreeExt(tif, From14);
594         if (From8)
595             _TIFFfreeExt(tif, From8);
596         if (ToLinearF)
597             _TIFFfreeExt(tif, ToLinearF);
598         if (ToLinear16)
599             _TIFFfreeExt(tif, ToLinear16);
600         if (ToLinear8)
601             _TIFFfreeExt(tif, ToLinear8);
602         sp->FromLT2 = NULL;
603         sp->From14 = NULL;
604         sp->From8 = NULL;
605         sp->ToLinearF = NULL;
606         sp->ToLinear16 = NULL;
607         sp->ToLinear8 = NULL;
608         return 0;
609     }
610 
611     j = 0;
612 
613     for (i = 0; i < nlin; i++)
614     {
615         v = i * linstep;
616         ToLinearF[j++] = (float)v;
617     }
618 
619     for (i = nlin; i < TSIZE; i++)
620         ToLinearF[j++] = (float)(b * exp(c * i));
621 
622     ToLinearF[2048] = ToLinearF[2047];
623 
624     for (i = 0; i < TSIZEP1; i++)
625     {
626         v = ToLinearF[i] * 65535.0 + 0.5;
627         ToLinear16[i] = (v > 65535.0) ? 65535 : (uint16_t)v;
628         v = ToLinearF[i] * 255.0 + 0.5;
629         ToLinear8[i] = (v > 255.0) ? 255 : (unsigned char)v;
630     }
631 
632     j = 0;
633     for (i = 0; i < lt2size; i++)
634     {
635         if ((i * linstep) * (i * linstep) > ToLinearF[j] * ToLinearF[j + 1])
636             j++;
637         FromLT2[i] = (uint16_t)j;
638     }
639 
640     /*
641      * Since we lose info anyway on 16-bit data, we set up a 14-bit
642      * table and shift 16-bit values down two bits on input.
643      * saves a little table space.
644      */
645     j = 0;
646     for (i = 0; i < 16384; i++)
647     {
648         while ((i / 16383.) * (i / 16383.) > ToLinearF[j] * ToLinearF[j + 1])
649             j++;
650         From14[i] = (uint16_t)j;
651     }
652 
653     j = 0;
654     for (i = 0; i < 256; i++)
655     {
656         while ((i / 255.) * (i / 255.) > ToLinearF[j] * ToLinearF[j + 1])
657             j++;
658         From8[i] = (uint16_t)j;
659     }
660 
661     Fltsize = (float)(lt2size / 2);
662 
663     sp->ToLinearF = ToLinearF;
664     sp->ToLinear16 = ToLinear16;
665     sp->ToLinear8 = ToLinear8;
666     sp->FromLT2 = FromLT2;
667     sp->From14 = From14;
668     sp->From8 = From8;
669 
670     return 1;
671 }
672 
673 #define DecoderState(tif) ((PixarLogState *)(tif)->tif_data)
674 #define EncoderState(tif) ((PixarLogState *)(tif)->tif_data)
675 
676 static int PixarLogEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s);
677 static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s);
678 
679 #define PIXARLOGDATAFMT_UNKNOWN -1
680 
PixarLogGuessDataFmt(TIFFDirectory * td)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 
multiply_ms(tmsize_t m1,tmsize_t m2)716 static tmsize_t multiply_ms(tmsize_t m1, tmsize_t m2)
717 {
718     return _TIFFMultiplySSize(NULL, m1, m2, NULL);
719 }
720 
add_ms(tmsize_t m1,tmsize_t m2)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 
PixarLogFixupTags(TIFF * tif)733 static int PixarLogFixupTags(TIFF *tif)
734 {
735     (void)tif;
736     return (1);
737 }
738 
PixarLogSetupDecode(TIFF * tif)739 static int PixarLogSetupDecode(TIFF *tif)
740 {
741     static const char module[] = "PixarLogSetupDecode";
742     TIFFDirectory *td = &tif->tif_dir;
743     PixarLogState *sp = DecoderState(tif);
744     tmsize_t tbuf_size;
745     uint32_t strip_height;
746 
747     assert(sp != NULL);
748 
749     /* This function can possibly be called several times by */
750     /* PredictorSetupDecode() if this function succeeds but */
751     /* PredictorSetup() fails */
752     if ((sp->state & PLSTATE_INIT) != 0)
753         return 1;
754 
755     strip_height = td->td_rowsperstrip;
756     if (strip_height > td->td_imagelength)
757         strip_height = td->td_imagelength;
758 
759     /* Make sure no byte swapping happens on the data
760      * after decompression. */
761     tif->tif_postdecode = _TIFFNoPostDecode;
762 
763     /* for some reason, we can't do this in TIFFInitPixarLog */
764 
765     sp->stride =
766         (td->td_planarconfig == PLANARCONFIG_CONTIG ? td->td_samplesperpixel
767                                                     : 1);
768     tbuf_size = multiply_ms(
769         multiply_ms(multiply_ms(sp->stride, td->td_imagewidth), strip_height),
770         sizeof(uint16_t));
771     /* add one more stride in case input ends mid-stride */
772     tbuf_size = add_ms(tbuf_size, sizeof(uint16_t) * sp->stride);
773     if (tbuf_size == 0)
774         return (0); /* TODO: this is an error return without error report
775                        through TIFFErrorExt */
776     sp->tbuf = (uint16_t *)_TIFFmallocExt(tif, tbuf_size);
777     if (sp->tbuf == NULL)
778         return (0);
779     sp->tbuf_size = tbuf_size;
780     if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN)
781         sp->user_datafmt = PixarLogGuessDataFmt(td);
782     if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN)
783     {
784         _TIFFfreeExt(tif, sp->tbuf);
785         sp->tbuf = NULL;
786         sp->tbuf_size = 0;
787         TIFFErrorExtR(tif, module,
788                       "PixarLog compression can't handle bits depth/data "
789                       "format combination (depth: %" PRIu16 ")",
790                       td->td_bitspersample);
791         return (0);
792     }
793 
794     if (inflateInit(&sp->stream) != Z_OK)
795     {
796         _TIFFfreeExt(tif, sp->tbuf);
797         sp->tbuf = NULL;
798         sp->tbuf_size = 0;
799         TIFFErrorExtR(tif, module, "%s",
800                       sp->stream.msg ? sp->stream.msg : "(null)");
801         return (0);
802     }
803     else
804     {
805         sp->state |= PLSTATE_INIT;
806         return (1);
807     }
808 }
809 
810 /*
811  * Setup state for decoding a strip.
812  */
PixarLogPreDecode(TIFF * tif,uint16_t s)813 static int PixarLogPreDecode(TIFF *tif, uint16_t s)
814 {
815     static const char module[] = "PixarLogPreDecode";
816     PixarLogState *sp = DecoderState(tif);
817 
818     (void)s;
819     assert(sp != NULL);
820     sp->stream.next_in = tif->tif_rawdata;
821     assert(sizeof(sp->stream.avail_in) == 4); /* if this assert gets raised,
822          we need to simplify this code to reflect a ZLib that is likely updated
823          to deal with 8byte memory sizes, though this code will respond
824          appropriately even before we simplify it */
825     sp->stream.avail_in = (uInt)tif->tif_rawcc;
826     if ((tmsize_t)sp->stream.avail_in != tif->tif_rawcc)
827     {
828         TIFFErrorExtR(tif, module, "ZLib cannot deal with buffers this size");
829         return (0);
830     }
831     return (inflateReset(&sp->stream) == Z_OK);
832 }
833 
PixarLogDecode(TIFF * tif,uint8_t * op,tmsize_t occ,uint16_t s)834 static int PixarLogDecode(TIFF *tif, uint8_t *op, tmsize_t occ, uint16_t s)
835 {
836     static const char module[] = "PixarLogDecode";
837     TIFFDirectory *td = &tif->tif_dir;
838     PixarLogState *sp = DecoderState(tif);
839     tmsize_t i;
840     tmsize_t nsamples;
841     int llen;
842     uint16_t *up;
843 
844     switch (sp->user_datafmt)
845     {
846         case PIXARLOGDATAFMT_FLOAT:
847             nsamples = occ / sizeof(float); /* XXX float == 32 bits */
848             break;
849         case PIXARLOGDATAFMT_16BIT:
850         case PIXARLOGDATAFMT_12BITPICIO:
851         case PIXARLOGDATAFMT_11BITLOG:
852             nsamples = occ / sizeof(uint16_t); /* XXX uint16_t == 16 bits */
853             break;
854         case PIXARLOGDATAFMT_8BIT:
855         case PIXARLOGDATAFMT_8BITABGR:
856             nsamples = occ;
857             break;
858         default:
859             TIFFErrorExtR(tif, module,
860                           "%" PRIu16 " bit input not supported in PixarLog",
861                           td->td_bitspersample);
862             return 0;
863     }
864 
865     llen = sp->stride * td->td_imagewidth;
866 
867     (void)s;
868     assert(sp != NULL);
869 
870     sp->stream.next_in = tif->tif_rawcp;
871     sp->stream.avail_in = (uInt)tif->tif_rawcc;
872 
873     sp->stream.next_out = (unsigned char *)sp->tbuf;
874     assert(sizeof(sp->stream.avail_out) == 4); /* if this assert gets raised,
875          we need to simplify this code to reflect a ZLib that is likely updated
876          to deal with 8byte memory sizes, though this code will respond
877          appropriately even before we simplify it */
878     sp->stream.avail_out = (uInt)(nsamples * sizeof(uint16_t));
879     if (sp->stream.avail_out != nsamples * sizeof(uint16_t))
880     {
881         TIFFErrorExtR(tif, module, "ZLib cannot deal with buffers this size");
882         return (0);
883     }
884     /* Check that we will not fill more than what was allocated */
885     if (sp->tbuf_size < 0 || sp->stream.avail_out > (uInt) sp->tbuf_size)
886     {
887         TIFFErrorExtR(tif, module, "sp->stream.avail_out > sp->tbuf_size");
888         return (0);
889     }
890     do
891     {
892         int state = inflate(&sp->stream, Z_PARTIAL_FLUSH);
893         if (state == Z_STREAM_END)
894         {
895             break; /* XXX */
896         }
897         if (state == Z_DATA_ERROR)
898         {
899             TIFFErrorExtR(
900                 tif, module, "Decoding error at scanline %" PRIu32 ", %s",
901                 tif->tif_row, sp->stream.msg ? sp->stream.msg : "(null)");
902             return (0);
903         }
904         if (state != Z_OK)
905         {
906             TIFFErrorExtR(tif, module, "ZLib error: %s",
907                           sp->stream.msg ? sp->stream.msg : "(null)");
908             return (0);
909         }
910     } while (sp->stream.avail_out > 0);
911 
912     /* hopefully, we got all the bytes we needed */
913     if (sp->stream.avail_out != 0)
914     {
915         TIFFErrorExtR(tif, module,
916                       "Not enough data at scanline %" PRIu32
917                       " (short %u bytes)",
918                       tif->tif_row, sp->stream.avail_out);
919         return (0);
920     }
921 
922     tif->tif_rawcp = sp->stream.next_in;
923     tif->tif_rawcc = sp->stream.avail_in;
924 
925     up = sp->tbuf;
926     /* Swap bytes in the data if from a different endian machine. */
927     if (tif->tif_flags & TIFF_SWAB)
928         TIFFSwabArrayOfShort(up, nsamples);
929 
930     /*
931      * if llen is not an exact multiple of nsamples, the decode operation
932      * may overflow the output buffer, so truncate it enough to prevent
933      * that but still salvage as much data as possible.
934      */
935     if (nsamples % llen)
936     {
937         TIFFWarningExtR(tif, module,
938                         "stride %d is not a multiple of sample count, "
939                         "%" TIFF_SSIZE_FORMAT ", data truncated.",
940                         llen, nsamples);
941         nsamples -= nsamples % llen;
942     }
943 
944     for (i = 0; i < nsamples; i += llen, up += llen)
945     {
946         switch (sp->user_datafmt)
947         {
948             case PIXARLOGDATAFMT_FLOAT:
949                 horizontalAccumulateF(up, llen, sp->stride, (float *)op,
950                                       sp->ToLinearF);
951                 op += llen * sizeof(float);
952                 break;
953             case PIXARLOGDATAFMT_16BIT:
954                 horizontalAccumulate16(up, llen, sp->stride, (uint16_t *)op,
955                                        sp->ToLinear16);
956                 op += llen * sizeof(uint16_t);
957                 break;
958             case PIXARLOGDATAFMT_12BITPICIO:
959                 horizontalAccumulate12(up, llen, sp->stride, (int16_t *)op,
960                                        sp->ToLinearF);
961                 op += llen * sizeof(int16_t);
962                 break;
963             case PIXARLOGDATAFMT_11BITLOG:
964                 horizontalAccumulate11(up, llen, sp->stride, (uint16_t *)op);
965                 op += llen * sizeof(uint16_t);
966                 break;
967             case PIXARLOGDATAFMT_8BIT:
968                 horizontalAccumulate8(up, llen, sp->stride, (unsigned char *)op,
969                                       sp->ToLinear8);
970                 op += llen * sizeof(unsigned char);
971                 break;
972             case PIXARLOGDATAFMT_8BITABGR:
973                 horizontalAccumulate8abgr(up, llen, sp->stride,
974                                           (unsigned char *)op, sp->ToLinear8);
975                 op += llen * sizeof(unsigned char);
976                 break;
977             default:
978                 TIFFErrorExtR(tif, module, "Unsupported bits/sample: %" PRIu16,
979                               td->td_bitspersample);
980                 return (0);
981         }
982     }
983 
984     return (1);
985 }
986 
PixarLogSetupEncode(TIFF * tif)987 static int PixarLogSetupEncode(TIFF *tif)
988 {
989     static const char module[] = "PixarLogSetupEncode";
990     TIFFDirectory *td = &tif->tif_dir;
991     PixarLogState *sp = EncoderState(tif);
992     tmsize_t tbuf_size;
993 
994     assert(sp != NULL);
995 
996     /* for some reason, we can't do this in TIFFInitPixarLog */
997 
998     sp->stride =
999         (td->td_planarconfig == PLANARCONFIG_CONTIG ? td->td_samplesperpixel
1000                                                     : 1);
1001     tbuf_size =
1002         multiply_ms(multiply_ms(multiply_ms(sp->stride, td->td_imagewidth),
1003                                 td->td_rowsperstrip),
1004                     sizeof(uint16_t));
1005     if (tbuf_size == 0)
1006         return (0); /* TODO: this is an error return without error report
1007                        through TIFFErrorExt */
1008     sp->tbuf = (uint16_t *)_TIFFmallocExt(tif, tbuf_size);
1009     if (sp->tbuf == NULL)
1010         return (0);
1011     if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN)
1012         sp->user_datafmt = PixarLogGuessDataFmt(td);
1013     if (sp->user_datafmt == PIXARLOGDATAFMT_UNKNOWN)
1014     {
1015         TIFFErrorExtR(tif, module,
1016                       "PixarLog compression can't handle %" PRIu16
1017                       " bit linear encodings",
1018                       td->td_bitspersample);
1019         return (0);
1020     }
1021 
1022     if (deflateInit(&sp->stream, sp->quality) != Z_OK)
1023     {
1024         TIFFErrorExtR(tif, module, "%s",
1025                       sp->stream.msg ? sp->stream.msg : "(null)");
1026         return (0);
1027     }
1028     else
1029     {
1030         sp->state |= PLSTATE_INIT;
1031         return (1);
1032     }
1033 }
1034 
1035 /*
1036  * Reset encoding state at the start of a strip.
1037  */
PixarLogPreEncode(TIFF * tif,uint16_t s)1038 static int PixarLogPreEncode(TIFF *tif, uint16_t s)
1039 {
1040     static const char module[] = "PixarLogPreEncode";
1041     PixarLogState *sp = EncoderState(tif);
1042 
1043     (void)s;
1044     assert(sp != NULL);
1045     sp->stream.next_out = tif->tif_rawdata;
1046     assert(sizeof(sp->stream.avail_out) == 4); /* if this assert gets raised,
1047          we need to simplify this code to reflect a ZLib that is likely updated
1048          to deal with 8byte memory sizes, though this code will respond
1049          appropriately even before we simplify it */
1050     sp->stream.avail_out = (uInt)tif->tif_rawdatasize;
1051     if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize)
1052     {
1053         TIFFErrorExtR(tif, module, "ZLib cannot deal with buffers this size");
1054         return (0);
1055     }
1056     return (deflateReset(&sp->stream) == Z_OK);
1057 }
1058 
horizontalDifferenceF(float * ip,int n,int stride,uint16_t * wp,uint16_t * FromLT2)1059 static void horizontalDifferenceF(float *ip, int n, int stride, uint16_t *wp,
1060                                   uint16_t *FromLT2)
1061 {
1062     int32_t r1, g1, b1, a1, r2, g2, b2, a2, mask;
1063     float fltsize = Fltsize;
1064 
1065 #define CLAMP(v)                                                               \
1066     ((v < (float)0.)     ? 0                                                   \
1067      : (v < (float)2.)   ? FromLT2[(int)(v * fltsize)]                         \
1068      : (v > (float)24.2) ? 2047                                                \
1069                          : LogK1 * log(v * LogK2) + 0.5)
1070 
1071     mask = CODE_MASK;
1072     if (n >= stride)
1073     {
1074         if (stride == 3)
1075         {
1076             r2 = wp[0] = (uint16_t)CLAMP(ip[0]);
1077             g2 = wp[1] = (uint16_t)CLAMP(ip[1]);
1078             b2 = wp[2] = (uint16_t)CLAMP(ip[2]);
1079             n -= 3;
1080             while (n > 0)
1081             {
1082                 n -= 3;
1083                 wp += 3;
1084                 ip += 3;
1085                 r1 = (int32_t)CLAMP(ip[0]);
1086                 wp[0] = (uint16_t)((r1 - r2) & mask);
1087                 r2 = r1;
1088                 g1 = (int32_t)CLAMP(ip[1]);
1089                 wp[1] = (uint16_t)((g1 - g2) & mask);
1090                 g2 = g1;
1091                 b1 = (int32_t)CLAMP(ip[2]);
1092                 wp[2] = (uint16_t)((b1 - b2) & mask);
1093                 b2 = b1;
1094             }
1095         }
1096         else if (stride == 4)
1097         {
1098             r2 = wp[0] = (uint16_t)CLAMP(ip[0]);
1099             g2 = wp[1] = (uint16_t)CLAMP(ip[1]);
1100             b2 = wp[2] = (uint16_t)CLAMP(ip[2]);
1101             a2 = wp[3] = (uint16_t)CLAMP(ip[3]);
1102             n -= 4;
1103             while (n > 0)
1104             {
1105                 n -= 4;
1106                 wp += 4;
1107                 ip += 4;
1108                 r1 = (int32_t)CLAMP(ip[0]);
1109                 wp[0] = (uint16_t)((r1 - r2) & mask);
1110                 r2 = r1;
1111                 g1 = (int32_t)CLAMP(ip[1]);
1112                 wp[1] = (uint16_t)((g1 - g2) & mask);
1113                 g2 = g1;
1114                 b1 = (int32_t)CLAMP(ip[2]);
1115                 wp[2] = (uint16_t)((b1 - b2) & mask);
1116                 b2 = b1;
1117                 a1 = (int32_t)CLAMP(ip[3]);
1118                 wp[3] = (uint16_t)((a1 - a2) & mask);
1119                 a2 = a1;
1120             }
1121         }
1122         else
1123         {
1124             REPEAT(stride, wp[0] = (uint16_t)CLAMP(ip[0]); wp++; ip++)
1125             n -= stride;
1126             while (n > 0)
1127             {
1128                 REPEAT(stride,
1129                        wp[0] = (uint16_t)(((int32_t)CLAMP(ip[0]) -
1130                                            (int32_t)CLAMP(ip[-stride])) &
1131                                           mask);
1132                        wp++; ip++)
1133                 n -= stride;
1134             }
1135         }
1136     }
1137 }
1138 
horizontalDifference16(unsigned short * ip,int n,int stride,unsigned short * wp,uint16_t * From14)1139 static void horizontalDifference16(unsigned short *ip, int n, int stride,
1140                                    unsigned short *wp, uint16_t *From14)
1141 {
1142     register int r1, g1, b1, a1, r2, g2, b2, a2, mask;
1143 
1144 /* assumption is unsigned pixel values */
1145 #undef CLAMP
1146 #define CLAMP(v) From14[(v) >> 2]
1147 
1148     mask = CODE_MASK;
1149     if (n >= stride)
1150     {
1151         if (stride == 3)
1152         {
1153             r2 = wp[0] = CLAMP(ip[0]);
1154             g2 = wp[1] = CLAMP(ip[1]);
1155             b2 = wp[2] = CLAMP(ip[2]);
1156             n -= 3;
1157             while (n > 0)
1158             {
1159                 n -= 3;
1160                 wp += 3;
1161                 ip += 3;
1162                 r1 = CLAMP(ip[0]);
1163                 wp[0] = (uint16_t)((r1 - r2) & mask);
1164                 r2 = r1;
1165                 g1 = CLAMP(ip[1]);
1166                 wp[1] = (uint16_t)((g1 - g2) & mask);
1167                 g2 = g1;
1168                 b1 = CLAMP(ip[2]);
1169                 wp[2] = (uint16_t)((b1 - b2) & mask);
1170                 b2 = b1;
1171             }
1172         }
1173         else if (stride == 4)
1174         {
1175             r2 = wp[0] = CLAMP(ip[0]);
1176             g2 = wp[1] = CLAMP(ip[1]);
1177             b2 = wp[2] = CLAMP(ip[2]);
1178             a2 = wp[3] = CLAMP(ip[3]);
1179             n -= 4;
1180             while (n > 0)
1181             {
1182                 n -= 4;
1183                 wp += 4;
1184                 ip += 4;
1185                 r1 = CLAMP(ip[0]);
1186                 wp[0] = (uint16_t)((r1 - r2) & mask);
1187                 r2 = r1;
1188                 g1 = CLAMP(ip[1]);
1189                 wp[1] = (uint16_t)((g1 - g2) & mask);
1190                 g2 = g1;
1191                 b1 = CLAMP(ip[2]);
1192                 wp[2] = (uint16_t)((b1 - b2) & mask);
1193                 b2 = b1;
1194                 a1 = CLAMP(ip[3]);
1195                 wp[3] = (uint16_t)((a1 - a2) & mask);
1196                 a2 = a1;
1197             }
1198         }
1199         else
1200         {
1201             REPEAT(stride, wp[0] = CLAMP(ip[0]); wp++; ip++)
1202             n -= stride;
1203             while (n > 0)
1204             {
1205                 REPEAT(stride,
1206                        wp[0] = (uint16_t)((CLAMP(ip[0]) - CLAMP(ip[-stride])) &
1207                                           mask);
1208                        wp++; ip++)
1209                 n -= stride;
1210             }
1211         }
1212     }
1213 }
1214 
horizontalDifference8(unsigned char * ip,int n,int stride,unsigned short * wp,uint16_t * From8)1215 static void horizontalDifference8(unsigned char *ip, int n, int stride,
1216                                   unsigned short *wp, uint16_t *From8)
1217 {
1218     register int r1, g1, b1, a1, r2, g2, b2, a2, mask;
1219 
1220 #undef CLAMP
1221 #define CLAMP(v) (From8[(v)])
1222 
1223     mask = CODE_MASK;
1224     if (n >= stride)
1225     {
1226         if (stride == 3)
1227         {
1228             r2 = wp[0] = CLAMP(ip[0]);
1229             g2 = wp[1] = CLAMP(ip[1]);
1230             b2 = wp[2] = CLAMP(ip[2]);
1231             n -= 3;
1232             while (n > 0)
1233             {
1234                 n -= 3;
1235                 r1 = CLAMP(ip[3]);
1236                 wp[3] = (uint16_t)((r1 - r2) & mask);
1237                 r2 = r1;
1238                 g1 = CLAMP(ip[4]);
1239                 wp[4] = (uint16_t)((g1 - g2) & mask);
1240                 g2 = g1;
1241                 b1 = CLAMP(ip[5]);
1242                 wp[5] = (uint16_t)((b1 - b2) & mask);
1243                 b2 = b1;
1244                 wp += 3;
1245                 ip += 3;
1246             }
1247         }
1248         else if (stride == 4)
1249         {
1250             r2 = wp[0] = CLAMP(ip[0]);
1251             g2 = wp[1] = CLAMP(ip[1]);
1252             b2 = wp[2] = CLAMP(ip[2]);
1253             a2 = wp[3] = CLAMP(ip[3]);
1254             n -= 4;
1255             while (n > 0)
1256             {
1257                 n -= 4;
1258                 r1 = CLAMP(ip[4]);
1259                 wp[4] = (uint16_t)((r1 - r2) & mask);
1260                 r2 = r1;
1261                 g1 = CLAMP(ip[5]);
1262                 wp[5] = (uint16_t)((g1 - g2) & mask);
1263                 g2 = g1;
1264                 b1 = CLAMP(ip[6]);
1265                 wp[6] = (uint16_t)((b1 - b2) & mask);
1266                 b2 = b1;
1267                 a1 = CLAMP(ip[7]);
1268                 wp[7] = (uint16_t)((a1 - a2) & mask);
1269                 a2 = a1;
1270                 wp += 4;
1271                 ip += 4;
1272             }
1273         }
1274         else
1275         {
1276             REPEAT(stride, wp[0] = CLAMP(ip[0]); wp++; ip++)
1277             n -= stride;
1278             while (n > 0)
1279             {
1280                 REPEAT(stride,
1281                        wp[0] = (uint16_t)((CLAMP(ip[0]) - CLAMP(ip[-stride])) &
1282                                           mask);
1283                        wp++; ip++)
1284                 n -= stride;
1285             }
1286         }
1287     }
1288 }
1289 
1290 /*
1291  * Encode a chunk of pixels.
1292  */
PixarLogEncode(TIFF * tif,uint8_t * bp,tmsize_t cc,uint16_t s)1293 static int PixarLogEncode(TIFF *tif, uint8_t *bp, tmsize_t cc, uint16_t s)
1294 {
1295     static const char module[] = "PixarLogEncode";
1296     TIFFDirectory *td = &tif->tif_dir;
1297     PixarLogState *sp = EncoderState(tif);
1298     tmsize_t i;
1299     tmsize_t n;
1300     int llen;
1301     unsigned short *up;
1302 
1303     (void)s;
1304 
1305     switch (sp->user_datafmt)
1306     {
1307         case PIXARLOGDATAFMT_FLOAT:
1308             n = cc / sizeof(float); /* XXX float == 32 bits */
1309             break;
1310         case PIXARLOGDATAFMT_16BIT:
1311         case PIXARLOGDATAFMT_12BITPICIO:
1312         case PIXARLOGDATAFMT_11BITLOG:
1313             n = cc / sizeof(uint16_t); /* XXX uint16_t == 16 bits */
1314             break;
1315         case PIXARLOGDATAFMT_8BIT:
1316         case PIXARLOGDATAFMT_8BITABGR:
1317             n = cc;
1318             break;
1319         default:
1320             TIFFErrorExtR(tif, module,
1321                           "%" PRIu16 " bit input not supported in PixarLog",
1322                           td->td_bitspersample);
1323             return 0;
1324     }
1325 
1326     llen = sp->stride * td->td_imagewidth;
1327     /* Check against the number of elements (of size uint16_t) of sp->tbuf */
1328     if (n > ((tmsize_t)td->td_rowsperstrip * llen))
1329     {
1330         TIFFErrorExtR(tif, module, "Too many input bytes provided");
1331         return 0;
1332     }
1333 
1334     for (i = 0, up = sp->tbuf; i < n; i += llen, up += llen)
1335     {
1336         switch (sp->user_datafmt)
1337         {
1338             case PIXARLOGDATAFMT_FLOAT:
1339                 horizontalDifferenceF((float *)bp, llen, sp->stride, up,
1340                                       sp->FromLT2);
1341                 bp += llen * sizeof(float);
1342                 break;
1343             case PIXARLOGDATAFMT_16BIT:
1344                 horizontalDifference16((uint16_t *)bp, llen, sp->stride, up,
1345                                        sp->From14);
1346                 bp += llen * sizeof(uint16_t);
1347                 break;
1348             case PIXARLOGDATAFMT_8BIT:
1349                 horizontalDifference8((unsigned char *)bp, llen, sp->stride, up,
1350                                       sp->From8);
1351                 bp += llen * sizeof(unsigned char);
1352                 break;
1353             default:
1354                 TIFFErrorExtR(tif, module,
1355                               "%" PRIu16 " bit input not supported in PixarLog",
1356                               td->td_bitspersample);
1357                 return 0;
1358         }
1359     }
1360 
1361     sp->stream.next_in = (unsigned char *)sp->tbuf;
1362     assert(sizeof(sp->stream.avail_in) == 4); /* if this assert gets raised,
1363          we need to simplify this code to reflect a ZLib that is likely updated
1364          to deal with 8byte memory sizes, though this code will respond
1365          appropriately even before we simplify it */
1366     sp->stream.avail_in = (uInt)(n * sizeof(uint16_t));
1367     if ((sp->stream.avail_in / sizeof(uint16_t)) != (uInt)n)
1368     {
1369         TIFFErrorExtR(tif, module, "ZLib cannot deal with buffers this size");
1370         return (0);
1371     }
1372 
1373     do
1374     {
1375         if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK)
1376         {
1377             TIFFErrorExtR(tif, module, "Encoder error: %s",
1378                           sp->stream.msg ? sp->stream.msg : "(null)");
1379             return (0);
1380         }
1381         if (sp->stream.avail_out == 0)
1382         {
1383             tif->tif_rawcc = tif->tif_rawdatasize;
1384             if (!TIFFFlushData1(tif))
1385                 return 0;
1386             sp->stream.next_out = tif->tif_rawdata;
1387             sp->stream.avail_out =
1388                 (uInt)tif
1389                     ->tif_rawdatasize; /* this is a safe typecast, as check is
1390                                           made already in PixarLogPreEncode */
1391         }
1392     } while (sp->stream.avail_in > 0);
1393     return (1);
1394 }
1395 
1396 /*
1397  * Finish off an encoded strip by flushing the last
1398  * string and tacking on an End Of Information code.
1399  */
1400 
PixarLogPostEncode(TIFF * tif)1401 static int PixarLogPostEncode(TIFF *tif)
1402 {
1403     static const char module[] = "PixarLogPostEncode";
1404     PixarLogState *sp = EncoderState(tif);
1405     int state;
1406 
1407     sp->stream.avail_in = 0;
1408 
1409     do
1410     {
1411         state = deflate(&sp->stream, Z_FINISH);
1412         switch (state)
1413         {
1414             case Z_STREAM_END:
1415             case Z_OK:
1416                 if ((tmsize_t)sp->stream.avail_out != tif->tif_rawdatasize)
1417                 {
1418                     tif->tif_rawcc =
1419                         tif->tif_rawdatasize - sp->stream.avail_out;
1420                     if (!TIFFFlushData1(tif))
1421                         return 0;
1422                     sp->stream.next_out = tif->tif_rawdata;
1423                     sp->stream.avail_out =
1424                         (uInt)tif->tif_rawdatasize; /* this is a safe typecast,
1425                                                        as check is made already
1426                                                        in PixarLogPreEncode */
1427                 }
1428                 break;
1429             default:
1430                 TIFFErrorExtR(tif, module, "ZLib error: %s",
1431                               sp->stream.msg ? sp->stream.msg : "(null)");
1432                 return (0);
1433         }
1434     } while (state != Z_STREAM_END);
1435     return (1);
1436 }
1437 
PixarLogClose(TIFF * tif)1438 static void PixarLogClose(TIFF *tif)
1439 {
1440     PixarLogState *sp = (PixarLogState *)tif->tif_data;
1441     TIFFDirectory *td = &tif->tif_dir;
1442 
1443     assert(sp != 0);
1444     /* In a really sneaky (and really incorrect, and untruthful, and
1445      * troublesome, and error-prone) maneuver that completely goes against
1446      * the spirit of TIFF, and breaks TIFF, on close, we covertly
1447      * modify both bitspersample and sampleformat in the directory to
1448      * indicate 8-bit linear.  This way, the decode "just works" even for
1449      * readers that don't know about PixarLog, or how to set
1450      * the PIXARLOGDATFMT pseudo-tag.
1451      */
1452 
1453     if (sp->state & PLSTATE_INIT)
1454     {
1455         /* We test the state to avoid an issue such as in
1456          * http://bugzilla.maptools.org/show_bug.cgi?id=2604
1457          * What appends in that case is that the bitspersample is 1 and
1458          * a TransferFunction is set. The size of the TransferFunction
1459          * depends on 1<<bitspersample. So if we increase it, an access
1460          * out of the buffer will happen at directory flushing.
1461          * Another option would be to clear those targs.
1462          */
1463         td->td_bitspersample = 8;
1464         td->td_sampleformat = SAMPLEFORMAT_UINT;
1465     }
1466 }
1467 
PixarLogCleanup(TIFF * tif)1468 static void PixarLogCleanup(TIFF *tif)
1469 {
1470     PixarLogState *sp = (PixarLogState *)tif->tif_data;
1471 
1472     assert(sp != 0);
1473 
1474     (void)TIFFPredictorCleanup(tif);
1475 
1476     tif->tif_tagmethods.vgetfield = sp->vgetparent;
1477     tif->tif_tagmethods.vsetfield = sp->vsetparent;
1478 
1479     if (sp->FromLT2)
1480         _TIFFfreeExt(tif, sp->FromLT2);
1481     if (sp->From14)
1482         _TIFFfreeExt(tif, sp->From14);
1483     if (sp->From8)
1484         _TIFFfreeExt(tif, sp->From8);
1485     if (sp->ToLinearF)
1486         _TIFFfreeExt(tif, sp->ToLinearF);
1487     if (sp->ToLinear16)
1488         _TIFFfreeExt(tif, sp->ToLinear16);
1489     if (sp->ToLinear8)
1490         _TIFFfreeExt(tif, sp->ToLinear8);
1491     if (sp->state & PLSTATE_INIT)
1492     {
1493         if (tif->tif_mode == O_RDONLY)
1494             inflateEnd(&sp->stream);
1495         else
1496             deflateEnd(&sp->stream);
1497     }
1498     if (sp->tbuf)
1499         _TIFFfreeExt(tif, sp->tbuf);
1500     _TIFFfreeExt(tif, sp);
1501     tif->tif_data = NULL;
1502 
1503     _TIFFSetDefaultCompressionState(tif);
1504 }
1505 
PixarLogVSetField(TIFF * tif,uint32_t tag,va_list ap)1506 static int PixarLogVSetField(TIFF *tif, uint32_t tag, va_list ap)
1507 {
1508     static const char module[] = "PixarLogVSetField";
1509     PixarLogState *sp = (PixarLogState *)tif->tif_data;
1510     int result;
1511 
1512     switch (tag)
1513     {
1514         case TIFFTAG_PIXARLOGQUALITY:
1515             sp->quality = (int)va_arg(ap, int);
1516             if (tif->tif_mode != O_RDONLY && (sp->state & PLSTATE_INIT))
1517             {
1518                 if (deflateParams(&sp->stream, sp->quality,
1519                                   Z_DEFAULT_STRATEGY) != Z_OK)
1520                 {
1521                     TIFFErrorExtR(tif, module, "ZLib error: %s",
1522                                   sp->stream.msg ? sp->stream.msg : "(null)");
1523                     return (0);
1524                 }
1525             }
1526             return (1);
1527         case TIFFTAG_PIXARLOGDATAFMT:
1528             sp->user_datafmt = (int)va_arg(ap, int);
1529             /* Tweak the TIFF header so that the rest of libtiff knows what
1530              * size of data will be passed between app and library, and
1531              * assume that the app knows what it is doing and is not
1532              * confused by these header manipulations...
1533              */
1534             switch (sp->user_datafmt)
1535             {
1536                 case PIXARLOGDATAFMT_8BIT:
1537                 case PIXARLOGDATAFMT_8BITABGR:
1538                     TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
1539                     TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
1540                     break;
1541                 case PIXARLOGDATAFMT_11BITLOG:
1542                     TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
1543                     TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
1544                     break;
1545                 case PIXARLOGDATAFMT_12BITPICIO:
1546                     TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
1547                     TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT);
1548                     break;
1549                 case PIXARLOGDATAFMT_16BIT:
1550                     TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
1551                     TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
1552                     break;
1553                 case PIXARLOGDATAFMT_FLOAT:
1554                     TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32);
1555                     TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT,
1556                                  SAMPLEFORMAT_IEEEFP);
1557                     break;
1558             }
1559             /*
1560              * Must recalculate sizes should bits/sample change.
1561              */
1562             tif->tif_tilesize =
1563                 isTiled(tif) ? TIFFTileSize(tif) : (tmsize_t)(-1);
1564             tif->tif_scanlinesize = TIFFScanlineSize(tif);
1565             result = 1; /* NB: pseudo tag */
1566             break;
1567         default:
1568             result = (*sp->vsetparent)(tif, tag, ap);
1569     }
1570     return (result);
1571 }
1572 
PixarLogVGetField(TIFF * tif,uint32_t tag,va_list ap)1573 static int PixarLogVGetField(TIFF *tif, uint32_t tag, va_list ap)
1574 {
1575     PixarLogState *sp = (PixarLogState *)tif->tif_data;
1576 
1577     switch (tag)
1578     {
1579         case TIFFTAG_PIXARLOGQUALITY:
1580             *va_arg(ap, int *) = sp->quality;
1581             break;
1582         case TIFFTAG_PIXARLOGDATAFMT:
1583             *va_arg(ap, int *) = sp->user_datafmt;
1584             break;
1585         default:
1586             return (*sp->vgetparent)(tif, tag, ap);
1587     }
1588     return (1);
1589 }
1590 
1591 static const TIFFField pixarlogFields[] = {
1592     {TIFFTAG_PIXARLOGDATAFMT, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT,
1593      TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, FALSE, FALSE, "", NULL},
1594     {TIFFTAG_PIXARLOGQUALITY, 0, 0, TIFF_ANY, 0, TIFF_SETGET_INT,
1595      TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, FALSE, FALSE, "", NULL}};
1596 
TIFFInitPixarLog(TIFF * tif,int scheme)1597 int TIFFInitPixarLog(TIFF *tif, int scheme)
1598 {
1599     static const char module[] = "TIFFInitPixarLog";
1600 
1601     PixarLogState *sp;
1602 
1603     (void)scheme;
1604     assert(scheme == COMPRESSION_PIXARLOG);
1605 
1606     /*
1607      * Merge codec-specific tag information.
1608      */
1609     if (!_TIFFMergeFields(tif, pixarlogFields, TIFFArrayCount(pixarlogFields)))
1610     {
1611         TIFFErrorExtR(tif, module,
1612                       "Merging PixarLog codec-specific tags failed");
1613         return 0;
1614     }
1615 
1616     /*
1617      * Allocate state block so tag methods have storage to record values.
1618      */
1619     tif->tif_data = (uint8_t *)_TIFFmallocExt(tif, sizeof(PixarLogState));
1620     if (tif->tif_data == NULL)
1621         goto bad;
1622     sp = (PixarLogState *)tif->tif_data;
1623     _TIFFmemset(sp, 0, sizeof(*sp));
1624     sp->stream.data_type = Z_BINARY;
1625     sp->user_datafmt = PIXARLOGDATAFMT_UNKNOWN;
1626 
1627     /*
1628      * Install codec methods.
1629      */
1630     tif->tif_fixuptags = PixarLogFixupTags;
1631     tif->tif_setupdecode = PixarLogSetupDecode;
1632     tif->tif_predecode = PixarLogPreDecode;
1633     tif->tif_decoderow = PixarLogDecode;
1634     tif->tif_decodestrip = PixarLogDecode;
1635     tif->tif_decodetile = PixarLogDecode;
1636     tif->tif_setupencode = PixarLogSetupEncode;
1637     tif->tif_preencode = PixarLogPreEncode;
1638     tif->tif_postencode = PixarLogPostEncode;
1639     tif->tif_encoderow = PixarLogEncode;
1640     tif->tif_encodestrip = PixarLogEncode;
1641     tif->tif_encodetile = PixarLogEncode;
1642     tif->tif_close = PixarLogClose;
1643     tif->tif_cleanup = PixarLogCleanup;
1644 
1645     /* Override SetField so we can handle our private pseudo-tag */
1646     sp->vgetparent = tif->tif_tagmethods.vgetfield;
1647     tif->tif_tagmethods.vgetfield = PixarLogVGetField; /* hook for codec tags */
1648     sp->vsetparent = tif->tif_tagmethods.vsetfield;
1649     tif->tif_tagmethods.vsetfield = PixarLogVSetField; /* hook for codec tags */
1650 
1651     /* Default values for codec-specific fields */
1652     sp->quality = Z_DEFAULT_COMPRESSION; /* default comp. level */
1653     sp->state = 0;
1654 
1655     /* we don't wish to use the predictor,
1656      * the default is none, which predictor value 1
1657      */
1658     (void)TIFFPredictorInit(tif);
1659 
1660     /*
1661      * build the companding tables
1662      */
1663     PixarLogMakeTables(tif, sp);
1664 
1665     return (1);
1666 bad:
1667     TIFFErrorExtR(tif, module, "No space for PixarLog state block");
1668     return (0);
1669 }
1670 #endif /* PIXARLOG_SUPPORT */
1671