2 * Copyright (c) 1996-1997 Sam Leffler
3 * Copyright (c) 1996 Pixar
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.
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.
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
26 #ifdef PIXARLOG_SUPPORT
30 * PixarLog Compression Support
32 * Contributed by Dan McCoy.
34 * PixarLog film support uses the TIFF library to store companded
35 * 11 bit values into a tiff file, which are compressed using the
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.
41 * On writing any of the above are converted into the internal
42 * 11-bit log format. In the case of 8 and 16 bit values, the
43 * input is assumed to be unsigned linear color values that represent
44 * the range 0-1. In the case of IEEE values, the 0-1 range is assumed to
45 * be the normal linear color range, in addition over 1 values are
46 * accepted up to a value of about 25.0 to encode "hot" hightlights and such.
47 * The encoding is lossless for 8-bit values, slightly lossy for the
48 * other bit depths. The actual color precision should be better
49 * than the human eye can perceive with extra room to allow for
50 * error introduced by further image computation. As with any quantized
51 * color format, it is possible to perform image calculations which
52 * expose the quantization error. This format should certainly be less
53 * susceptable to such errors than standard 8-bit encodings, but more
54 * susceptable than straight 16-bit or 32-bit encodings.
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
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).
67 * PIXARLOGDATAFMT_11BITLOG provides the internal encoding directly
68 * packed in 16-bit values. However no tools are supplied for interpreting
71 * "hot" (over 1.0) areas written in floating point get clamped to
72 * 1.0 in the integer data types.
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.
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.
87 /* Watcom C++ (or its make utility) doesn't like long filenames */
91 #include "tif_predict.h"
102 /* Tables for converting to/from 11 bit coded values */
104 #define TSIZE 2048 /* decode table size (11-bit tokens) */
105 #define TSIZEP1 2049 /* Plus one for slop */
106 #define ONE 1250 /* token value of 1.0 exactly */
107 #define RATIO 1.004 /* nominal ratio for log part */
109 #define CODE_MASK 0x7ff /* 11 bits. */
111 static float Fltsize
;
112 static float LogK1
, LogK2
;
114 #define REPEAT(n, op) { int i; i=n; do { i--; op; } while (i>0); }
117 horizontalAccumulateF(uint16
*wp
, int n
, int stride
, float *op
,
120 register unsigned int cr
, cg
, cb
, ca
, mask
;
121 register float t0
, t1
, t2
, t3
;
126 t0
= ToLinearF
[cr
= wp
[0]];
127 t1
= ToLinearF
[cg
= wp
[1]];
128 t2
= ToLinearF
[cb
= wp
[2]];
137 t0
= ToLinearF
[(cr
+= wp
[0]) & mask
];
138 t1
= ToLinearF
[(cg
+= wp
[1]) & mask
];
139 t2
= ToLinearF
[(cb
+= wp
[2]) & mask
];
144 } else if (stride
== 4) {
145 t0
= ToLinearF
[cr
= wp
[0]];
146 t1
= ToLinearF
[cg
= wp
[1]];
147 t2
= ToLinearF
[cb
= wp
[2]];
148 t3
= ToLinearF
[ca
= wp
[3]];
158 t0
= ToLinearF
[(cr
+= wp
[0]) & mask
];
159 t1
= ToLinearF
[(cg
+= wp
[1]) & mask
];
160 t2
= ToLinearF
[(cb
+= wp
[2]) & mask
];
161 t3
= ToLinearF
[(ca
+= wp
[3]) & mask
];
168 REPEAT(stride
, *op
= ToLinearF
[*wp
&mask
]; wp
++; op
++)
172 wp
[stride
] += *wp
; *op
= ToLinearF
[*wp
&mask
]; wp
++; op
++)
180 horizontalAccumulate12(uint16
*wp
, int n
, int stride
, int16
*op
,
183 register unsigned int cr
, cg
, cb
, ca
, mask
;
184 register float t0
, t1
, t2
, t3
;
186 #define SCALE12 2048.0
187 #define CLAMP12(t) (((t) < 3071) ? (uint16) (t) : 3071)
192 t0
= ToLinearF
[cr
= wp
[0]] * SCALE12
;
193 t1
= ToLinearF
[cg
= wp
[1]] * SCALE12
;
194 t2
= ToLinearF
[cb
= wp
[2]] * SCALE12
;
203 t0
= ToLinearF
[(cr
+= wp
[0]) & mask
] * SCALE12
;
204 t1
= ToLinearF
[(cg
+= wp
[1]) & mask
] * SCALE12
;
205 t2
= ToLinearF
[(cb
+= wp
[2]) & mask
] * SCALE12
;
210 } else if (stride
== 4) {
211 t0
= ToLinearF
[cr
= wp
[0]] * SCALE12
;
212 t1
= ToLinearF
[cg
= wp
[1]] * SCALE12
;
213 t2
= ToLinearF
[cb
= wp
[2]] * SCALE12
;
214 t3
= ToLinearF
[ca
= wp
[3]] * SCALE12
;
224 t0
= ToLinearF
[(cr
+= wp
[0]) & mask
] * SCALE12
;
225 t1
= ToLinearF
[(cg
+= wp
[1]) & mask
] * SCALE12
;
226 t2
= ToLinearF
[(cb
+= wp
[2]) & mask
] * SCALE12
;
227 t3
= ToLinearF
[(ca
+= wp
[3]) & mask
] * SCALE12
;
234 REPEAT(stride
, t0
= ToLinearF
[*wp
&mask
] * SCALE12
;
235 *op
= CLAMP12(t0
); wp
++; op
++)
239 wp
[stride
] += *wp
; t0
= ToLinearF
[wp
[stride
]&mask
]*SCALE12
;
240 *op
= CLAMP12(t0
); wp
++; op
++)
248 horizontalAccumulate16(uint16
*wp
, int n
, int stride
, uint16
*op
,
251 register unsigned int cr
, cg
, cb
, ca
, mask
;
256 op
[0] = ToLinear16
[cr
= wp
[0]];
257 op
[1] = ToLinear16
[cg
= wp
[1]];
258 op
[2] = ToLinear16
[cb
= wp
[2]];
264 op
[0] = ToLinear16
[(cr
+= wp
[0]) & mask
];
265 op
[1] = ToLinear16
[(cg
+= wp
[1]) & mask
];
266 op
[2] = ToLinear16
[(cb
+= wp
[2]) & mask
];
268 } else if (stride
== 4) {
269 op
[0] = ToLinear16
[cr
= wp
[0]];
270 op
[1] = ToLinear16
[cg
= wp
[1]];
271 op
[2] = ToLinear16
[cb
= wp
[2]];
272 op
[3] = ToLinear16
[ca
= wp
[3]];
278 op
[0] = ToLinear16
[(cr
+= wp
[0]) & mask
];
279 op
[1] = ToLinear16
[(cg
+= wp
[1]) & mask
];
280 op
[2] = ToLinear16
[(cb
+= wp
[2]) & mask
];
281 op
[3] = ToLinear16
[(ca
+= wp
[3]) & mask
];
284 REPEAT(stride
, *op
= ToLinear16
[*wp
&mask
]; wp
++; op
++)
288 wp
[stride
] += *wp
; *op
= ToLinear16
[*wp
&mask
]; wp
++; op
++)
296 * Returns the log encoded 11-bit values with the horizontal
297 * differencing undone.
300 horizontalAccumulate11(uint16
*wp
, int n
, int stride
, uint16
*op
)
302 register unsigned int cr
, cg
, cb
, ca
, mask
;
307 op
[0] = cr
= wp
[0]; op
[1] = cg
= wp
[1]; op
[2] = cb
= wp
[2];
313 op
[0] = (cr
+= wp
[0]) & mask
;
314 op
[1] = (cg
+= wp
[1]) & mask
;
315 op
[2] = (cb
+= wp
[2]) & mask
;
317 } else if (stride
== 4) {
318 op
[0] = cr
= wp
[0]; op
[1] = cg
= wp
[1];
319 op
[2] = cb
= wp
[2]; op
[3] = ca
= wp
[3];
325 op
[0] = (cr
+= wp
[0]) & mask
;
326 op
[1] = (cg
+= wp
[1]) & mask
;
327 op
[2] = (cb
+= wp
[2]) & mask
;
328 op
[3] = (ca
+= wp
[3]) & mask
;
331 REPEAT(stride
, *op
= *wp
&mask
; wp
++; op
++)
335 wp
[stride
] += *wp
; *op
= *wp
&mask
; wp
++; op
++)
343 horizontalAccumulate8(uint16
*wp
, int n
, int stride
, unsigned char *op
,
344 unsigned char *ToLinear8
)
346 register unsigned int cr
, cg
, cb
, ca
, mask
;
351 op
[0] = ToLinear8
[cr
= wp
[0]];
352 op
[1] = ToLinear8
[cg
= wp
[1]];
353 op
[2] = ToLinear8
[cb
= wp
[2]];
359 op
[0] = ToLinear8
[(cr
+= wp
[0]) & mask
];
360 op
[1] = ToLinear8
[(cg
+= wp
[1]) & mask
];
361 op
[2] = ToLinear8
[(cb
+= wp
[2]) & mask
];
363 } else if (stride
== 4) {
364 op
[0] = ToLinear8
[cr
= wp
[0]];
365 op
[1] = ToLinear8
[cg
= wp
[1]];
366 op
[2] = ToLinear8
[cb
= wp
[2]];
367 op
[3] = ToLinear8
[ca
= wp
[3]];
373 op
[0] = ToLinear8
[(cr
+= wp
[0]) & mask
];
374 op
[1] = ToLinear8
[(cg
+= wp
[1]) & mask
];
375 op
[2] = ToLinear8
[(cb
+= wp
[2]) & mask
];
376 op
[3] = ToLinear8
[(ca
+= wp
[3]) & mask
];
379 REPEAT(stride
, *op
= ToLinear8
[*wp
&mask
]; wp
++; op
++)
383 wp
[stride
] += *wp
; *op
= ToLinear8
[*wp
&mask
]; wp
++; op
++)
392 horizontalAccumulate8abgr(uint16
*wp
, int n
, int stride
, unsigned char *op
,
393 unsigned char *ToLinear8
)
395 register unsigned int cr
, cg
, cb
, ca
, mask
;
396 register unsigned char t0
, t1
, t2
, t3
;
402 t1
= ToLinear8
[cb
= wp
[2]];
403 t2
= ToLinear8
[cg
= wp
[1]];
404 t3
= ToLinear8
[cr
= wp
[0]];
414 t1
= ToLinear8
[(cb
+= wp
[2]) & mask
];
415 t2
= ToLinear8
[(cg
+= wp
[1]) & mask
];
416 t3
= ToLinear8
[(cr
+= wp
[0]) & mask
];
421 } else if (stride
== 4) {
422 t0
= ToLinear8
[ca
= wp
[3]];
423 t1
= ToLinear8
[cb
= wp
[2]];
424 t2
= ToLinear8
[cg
= wp
[1]];
425 t3
= ToLinear8
[cr
= wp
[0]];
435 t0
= ToLinear8
[(ca
+= wp
[3]) & mask
];
436 t1
= ToLinear8
[(cb
+= wp
[2]) & mask
];
437 t2
= ToLinear8
[(cg
+= wp
[1]) & mask
];
438 t3
= ToLinear8
[(cr
+= wp
[0]) & mask
];
445 REPEAT(stride
, *op
= ToLinear8
[*wp
&mask
]; wp
++; op
++)
449 wp
[stride
] += *wp
; *op
= ToLinear8
[*wp
&mask
]; wp
++; op
++)
457 * State block for each open TIFF
458 * file using PixarLog compression/decompression.
461 TIFFPredictorState predict
;
468 #define PLSTATE_INIT 1
470 TIFFVSetMethod vgetparent
; /* super-class method */
471 TIFFVSetMethod vsetparent
; /* super-class method */
475 unsigned char *ToLinear8
;
477 uint16
*From14
; /* Really for 16-bit data, but we shift down 2 */
483 PixarLogMakeTables(PixarLogState
*sp
)
487 * We make several tables here to convert between various external
488 * representations (float, 16-bit, and 8-bit) and the internal
489 * 11-bit companded representation. The 11-bit representation has two
490 * distinct regions. A linear bottom end up through .018316 in steps
491 * of about .000073, and a region of constant ratio up to about 25.
492 * These floating point numbers are stored in the main table ToLinearF.
493 * All other tables are derived from this one. The tables (and the
494 * ratios) are continuous at the internal seam.
499 double b
, c
, linstep
, max
;
500 double k
, v
, dv
, r
, lr2
, r2
;
503 unsigned char *ToLinear8
;
505 uint16
*From14
; /* Really for 16-bit data, but we shift down 2 */
509 nlin
= 1./c
; /* nlin must be an integer */
511 b
= exp(-c
*ONE
); /* multiplicative scale factor [b*exp(c*ONE) = 1] */
512 linstep
= b
*c
*exp(1.);
514 LogK1
= 1./c
; /* if (v >= 2) token = k1*log(v*k2) */
516 lt2size
= (2./linstep
)+1;
517 FromLT2
= (uint16
*)_TIFFmalloc(lt2size
*sizeof(uint16
));
518 From14
= (uint16
*)_TIFFmalloc(16384*sizeof(uint16
));
519 From8
= (uint16
*)_TIFFmalloc(256*sizeof(uint16
));
520 ToLinearF
= (float *)_TIFFmalloc(TSIZEP1
* sizeof(float));
521 ToLinear16
= (uint16
*)_TIFFmalloc(TSIZEP1
* sizeof(uint16
));
522 ToLinear8
= (unsigned char *)_TIFFmalloc(TSIZEP1
* sizeof(unsigned char));
523 if (FromLT2
== NULL
|| From14
== NULL
|| From8
== NULL
||
524 ToLinearF
== NULL
|| ToLinear16
== NULL
|| ToLinear8
== NULL
) {
525 if (FromLT2
) _TIFFfree(FromLT2
);
526 if (From14
) _TIFFfree(From14
);
527 if (From8
) _TIFFfree(From8
);
528 if (ToLinearF
) _TIFFfree(ToLinearF
);
529 if (ToLinear16
) _TIFFfree(ToLinear16
);
530 if (ToLinear8
) _TIFFfree(ToLinear8
);
534 sp
->ToLinearF
= NULL
;
535 sp
->ToLinear16
= NULL
;
536 sp
->ToLinear8
= NULL
;
542 for (i
= 0; i
< nlin
; i
++) {
547 for (i
= nlin
; i
< TSIZE
; i
++)
548 ToLinearF
[j
++] = b
*exp(c
*i
);
550 ToLinearF
[2048] = ToLinearF
[2047];
552 for (i
= 0; i
< TSIZEP1
; i
++) {
553 v
= ToLinearF
[i
]*65535.0 + 0.5;
554 ToLinear16
[i
] = (v
> 65535.0) ? 65535 : v
;
555 v
= ToLinearF
[i
]*255.0 + 0.5;
556 ToLinear8
[i
] = (v
> 255.0) ? 255 : v
;
560 for (i
= 0; i
< lt2size
; i
++) {
561 if ((i
*linstep
)*(i
*linstep
) > ToLinearF
[j
]*ToLinearF
[j
+1])
567 * Since we lose info anyway on 16-bit data, we set up a 14-bit
568 * table and shift 16-bit values down two bits on input.
569 * saves a little table space.
572 for (i
= 0; i
< 16384; i
++) {
573 while ((i
/16383.)*(i
/16383.) > ToLinearF
[j
]*ToLinearF
[j
+1])
579 for (i
= 0; i
< 256; i
++) {
580 while ((i
/255.)*(i
/255.) > ToLinearF
[j
]*ToLinearF
[j
+1])
587 sp
->ToLinearF
= ToLinearF
;
588 sp
->ToLinear16
= ToLinear16
;
589 sp
->ToLinear8
= ToLinear8
;
590 sp
->FromLT2
= FromLT2
;
597 #define DecoderState(tif) ((PixarLogState*) (tif)->tif_data)
598 #define EncoderState(tif) ((PixarLogState*) (tif)->tif_data)
600 static int PixarLogEncode(TIFF
*, tidata_t
, tsize_t
, tsample_t
);
601 static int PixarLogDecode(TIFF
*, tidata_t
, tsize_t
, tsample_t
);
603 #define N(a) (sizeof(a)/sizeof(a[0]))
604 #define PIXARLOGDATAFMT_UNKNOWN -1
607 PixarLogGuessDataFmt(TIFFDirectory
*td
)
609 int guess
= PIXARLOGDATAFMT_UNKNOWN
;
610 int format
= td
->td_sampleformat
;
612 /* If the user didn't tell us his datafmt,
613 * take our best guess from the bitspersample.
615 switch (td
->td_bitspersample
) {
617 if (format
== SAMPLEFORMAT_IEEEFP
)
618 guess
= PIXARLOGDATAFMT_FLOAT
;
621 if (format
== SAMPLEFORMAT_VOID
|| format
== SAMPLEFORMAT_UINT
)
622 guess
= PIXARLOGDATAFMT_16BIT
;
625 if (format
== SAMPLEFORMAT_VOID
|| format
== SAMPLEFORMAT_INT
)
626 guess
= PIXARLOGDATAFMT_12BITPICIO
;
629 if (format
== SAMPLEFORMAT_VOID
|| format
== SAMPLEFORMAT_UINT
)
630 guess
= PIXARLOGDATAFMT_11BITLOG
;
633 if (format
== SAMPLEFORMAT_VOID
|| format
== SAMPLEFORMAT_UINT
)
634 guess
= PIXARLOGDATAFMT_8BIT
;
642 PixarLogSetupDecode(TIFF
* tif
)
644 TIFFDirectory
*td
= &tif
->tif_dir
;
645 PixarLogState
* sp
= DecoderState(tif
);
646 static const char module[] = "PixarLogSetupDecode";
650 /* Make sure no byte swapping happens on the data
651 * after decompression. */
652 tif
->tif_postdecode
= _TIFFNoPostDecode
;
654 /* for some reason, we can't do this in TIFFInitPixarLog */
656 sp
->stride
= (td
->td_planarconfig
== PLANARCONFIG_CONTIG
?
657 td
->td_samplesperpixel
: 1);
658 sp
->tbuf
= (uint16
*) _TIFFmalloc(sp
->stride
*
659 td
->td_imagewidth
* td
->td_rowsperstrip
* sizeof(uint16
));
660 if (sp
->user_datafmt
== PIXARLOGDATAFMT_UNKNOWN
)
661 sp
->user_datafmt
= PixarLogGuessDataFmt(td
);
662 if (sp
->user_datafmt
== PIXARLOGDATAFMT_UNKNOWN
) {
664 "PixarLog compression can't handle bits depth/data format combination (depth: %d)",
665 td
->td_bitspersample
);
669 if (inflateInit(&sp
->stream
) != Z_OK
) {
670 TIFFError(module, "%s: %s", tif
->tif_name
, sp
->stream
.msg
);
673 sp
->state
|= PLSTATE_INIT
;
679 * Setup state for decoding a strip.
682 PixarLogPreDecode(TIFF
* tif
, tsample_t s
)
684 TIFFDirectory
*td
= &tif
->tif_dir
;
685 PixarLogState
* sp
= DecoderState(tif
);
689 sp
->stream
.next_in
= tif
->tif_rawdata
;
690 sp
->stream
.avail_in
= tif
->tif_rawcc
;
691 return (inflateReset(&sp
->stream
) == Z_OK
);
695 PixarLogDecode(TIFF
* tif
, tidata_t op
, tsize_t occ
, tsample_t s
)
697 TIFFDirectory
*td
= &tif
->tif_dir
;
698 PixarLogState
* sp
= DecoderState(tif
);
699 static const char module[] = "PixarLogDecode";
700 int i
, nsamples
, llen
;
703 switch (sp
->user_datafmt
) {
704 case PIXARLOGDATAFMT_FLOAT
:
705 nsamples
= occ
/ sizeof(float); /* XXX float == 32 bits */
707 case PIXARLOGDATAFMT_16BIT
:
708 case PIXARLOGDATAFMT_12BITPICIO
:
709 case PIXARLOGDATAFMT_11BITLOG
:
710 nsamples
= occ
/ sizeof(uint16
); /* XXX uint16 == 16 bits */
712 case PIXARLOGDATAFMT_8BIT
:
713 case PIXARLOGDATAFMT_8BITABGR
:
717 TIFFError(tif
->tif_name
,
718 "%d bit input not supported in PixarLog",
719 td
->td_bitspersample
);
723 llen
= sp
->stride
* td
->td_imagewidth
;
727 sp
->stream
.next_out
= (unsigned char *) sp
->tbuf
;
728 sp
->stream
.avail_out
= nsamples
* sizeof(uint16
);
730 int state
= inflate(&sp
->stream
, Z_PARTIAL_FLUSH
);
731 if (state
== Z_STREAM_END
) {
734 if (state
== Z_DATA_ERROR
) {
736 "%s: Decoding error at scanline %d, %s",
737 tif
->tif_name
, tif
->tif_row
, sp
->stream
.msg
);
738 if (inflateSync(&sp
->stream
) != Z_OK
)
743 TIFFError(module, "%s: zlib error: %s",
744 tif
->tif_name
, sp
->stream
.msg
);
747 } while (sp
->stream
.avail_out
> 0);
749 /* hopefully, we got all the bytes we needed */
750 if (sp
->stream
.avail_out
!= 0) {
752 "%s: Not enough data at scanline %d (short %d bytes)",
753 tif
->tif_name
, tif
->tif_row
, sp
->stream
.avail_out
);
758 /* Swap bytes in the data if from a different endian machine. */
759 if (tif
->tif_flags
& TIFF_SWAB
)
760 TIFFSwabArrayOfShort(up
, nsamples
);
762 for (i
= 0; i
< nsamples
; i
+= llen
, up
+= llen
) {
763 switch (sp
->user_datafmt
) {
764 case PIXARLOGDATAFMT_FLOAT
:
765 horizontalAccumulateF(up
, llen
, sp
->stride
,
766 (float *)op
, sp
->ToLinearF
);
767 op
+= llen
* sizeof(float);
769 case PIXARLOGDATAFMT_16BIT
:
770 horizontalAccumulate16(up
, llen
, sp
->stride
,
771 (uint16
*)op
, sp
->ToLinear16
);
772 op
+= llen
* sizeof(uint16
);
774 case PIXARLOGDATAFMT_12BITPICIO
:
775 horizontalAccumulate12(up
, llen
, sp
->stride
,
776 (int16
*)op
, sp
->ToLinearF
);
777 op
+= llen
* sizeof(int16
);
779 case PIXARLOGDATAFMT_11BITLOG
:
780 horizontalAccumulate11(up
, llen
, sp
->stride
,
782 op
+= llen
* sizeof(uint16
);
784 case PIXARLOGDATAFMT_8BIT
:
785 horizontalAccumulate8(up
, llen
, sp
->stride
,
786 (unsigned char *)op
, sp
->ToLinear8
);
787 op
+= llen
* sizeof(unsigned char);
789 case PIXARLOGDATAFMT_8BITABGR
:
790 horizontalAccumulate8abgr(up
, llen
, sp
->stride
,
791 (unsigned char *)op
, sp
->ToLinear8
);
792 op
+= llen
* sizeof(unsigned char);
795 TIFFError(tif
->tif_name
,
796 "PixarLogDecode: unsupported bits/sample: %d",
797 td
->td_bitspersample
);
806 PixarLogSetupEncode(TIFF
* tif
)
808 TIFFDirectory
*td
= &tif
->tif_dir
;
809 PixarLogState
* sp
= EncoderState(tif
);
810 static const char module[] = "PixarLogSetupEncode";
814 /* for some reason, we can't do this in TIFFInitPixarLog */
816 sp
->stride
= (td
->td_planarconfig
== PLANARCONFIG_CONTIG
?
817 td
->td_samplesperpixel
: 1);
818 sp
->tbuf
= (uint16
*) _TIFFmalloc(sp
->stride
*
819 td
->td_imagewidth
* td
->td_rowsperstrip
* sizeof(uint16
));
820 if (sp
->user_datafmt
== PIXARLOGDATAFMT_UNKNOWN
)
821 sp
->user_datafmt
= PixarLogGuessDataFmt(td
);
822 if (sp
->user_datafmt
== PIXARLOGDATAFMT_UNKNOWN
) {
823 TIFFError(module, "PixarLog compression can't handle %d bit linear encodings", td
->td_bitspersample
);
827 if (deflateInit(&sp
->stream
, sp
->quality
) != Z_OK
) {
828 TIFFError(module, "%s: %s", tif
->tif_name
, sp
->stream
.msg
);
831 sp
->state
|= PLSTATE_INIT
;
837 * Reset encoding state at the start of a strip.
840 PixarLogPreEncode(TIFF
* tif
, tsample_t s
)
842 TIFFDirectory
*td
= &tif
->tif_dir
;
843 PixarLogState
*sp
= EncoderState(tif
);
847 sp
->stream
.next_out
= tif
->tif_rawdata
;
848 sp
->stream
.avail_out
= tif
->tif_rawdatasize
;
849 return (deflateReset(&sp
->stream
) == Z_OK
);
853 horizontalDifferenceF(float *ip
, int n
, int stride
, uint16
*wp
, uint16
*FromLT2
)
856 register int r1
, g1
, b1
, a1
, r2
, g2
, b2
, a2
, mask
;
857 register float fltsize
= Fltsize
;
859 #define CLAMP(v) ( (v<(float)0.) ? 0 \
860 : (v<(float)2.) ? FromLT2[(int)(v*fltsize)] \
861 : (v>(float)24.2) ? 2047 \
862 : LogK1*log(v*LogK2) + 0.5 )
867 r2
= wp
[0] = CLAMP(ip
[0]); g2
= wp
[1] = CLAMP(ip
[1]);
868 b2
= wp
[2] = CLAMP(ip
[2]);
874 r1
= CLAMP(ip
[0]); wp
[0] = (r1
-r2
) & mask
; r2
= r1
;
875 g1
= CLAMP(ip
[1]); wp
[1] = (g1
-g2
) & mask
; g2
= g1
;
876 b1
= CLAMP(ip
[2]); wp
[2] = (b1
-b2
) & mask
; b2
= b1
;
878 } else if (stride
== 4) {
879 r2
= wp
[0] = CLAMP(ip
[0]); g2
= wp
[1] = CLAMP(ip
[1]);
880 b2
= wp
[2] = CLAMP(ip
[2]); a2
= wp
[3] = CLAMP(ip
[3]);
886 r1
= CLAMP(ip
[0]); wp
[0] = (r1
-r2
) & mask
; r2
= r1
;
887 g1
= CLAMP(ip
[1]); wp
[1] = (g1
-g2
) & mask
; g2
= g1
;
888 b1
= CLAMP(ip
[2]); wp
[2] = (b1
-b2
) & mask
; b2
= b1
;
889 a1
= CLAMP(ip
[3]); wp
[3] = (a1
-a2
) & mask
; a2
= a1
;
892 ip
+= n
- 1; /* point to last one */
893 wp
+= n
- 1; /* point to last one */
896 REPEAT(stride
, wp
[0] = CLAMP(ip
[0]);
902 REPEAT(stride
, wp
[0] = CLAMP(ip
[0]); wp
--; ip
--)
908 horizontalDifference16(unsigned short *ip
, int n
, int stride
,
909 unsigned short *wp
, uint16
*From14
)
911 register int r1
, g1
, b1
, a1
, r2
, g2
, b2
, a2
, mask
;
913 /* assumption is unsigned pixel values */
915 #define CLAMP(v) From14[(v) >> 2]
920 r2
= wp
[0] = CLAMP(ip
[0]); g2
= wp
[1] = CLAMP(ip
[1]);
921 b2
= wp
[2] = CLAMP(ip
[2]);
927 r1
= CLAMP(ip
[0]); wp
[0] = (r1
-r2
) & mask
; r2
= r1
;
928 g1
= CLAMP(ip
[1]); wp
[1] = (g1
-g2
) & mask
; g2
= g1
;
929 b1
= CLAMP(ip
[2]); wp
[2] = (b1
-b2
) & mask
; b2
= b1
;
931 } else if (stride
== 4) {
932 r2
= wp
[0] = CLAMP(ip
[0]); g2
= wp
[1] = CLAMP(ip
[1]);
933 b2
= wp
[2] = CLAMP(ip
[2]); a2
= wp
[3] = CLAMP(ip
[3]);
939 r1
= CLAMP(ip
[0]); wp
[0] = (r1
-r2
) & mask
; r2
= r1
;
940 g1
= CLAMP(ip
[1]); wp
[1] = (g1
-g2
) & mask
; g2
= g1
;
941 b1
= CLAMP(ip
[2]); wp
[2] = (b1
-b2
) & mask
; b2
= b1
;
942 a1
= CLAMP(ip
[3]); wp
[3] = (a1
-a2
) & mask
; a2
= a1
;
945 ip
+= n
- 1; /* point to last one */
946 wp
+= n
- 1; /* point to last one */
949 REPEAT(stride
, wp
[0] = CLAMP(ip
[0]);
955 REPEAT(stride
, wp
[0] = CLAMP(ip
[0]); wp
--; ip
--)
962 horizontalDifference8(unsigned char *ip
, int n
, int stride
,
963 unsigned short *wp
, uint16
*From8
)
965 register int r1
, g1
, b1
, a1
, r2
, g2
, b2
, a2
, mask
;
968 #define CLAMP(v) (From8[(v)])
973 r2
= wp
[0] = CLAMP(ip
[0]); g2
= wp
[1] = CLAMP(ip
[1]);
974 b2
= wp
[2] = CLAMP(ip
[2]);
978 r1
= CLAMP(ip
[3]); wp
[3] = (r1
-r2
) & mask
; r2
= r1
;
979 g1
= CLAMP(ip
[4]); wp
[4] = (g1
-g2
) & mask
; g2
= g1
;
980 b1
= CLAMP(ip
[5]); wp
[5] = (b1
-b2
) & mask
; b2
= b1
;
984 } else if (stride
== 4) {
985 r2
= wp
[0] = CLAMP(ip
[0]); g2
= wp
[1] = CLAMP(ip
[1]);
986 b2
= wp
[2] = CLAMP(ip
[2]); a2
= wp
[3] = CLAMP(ip
[3]);
990 r1
= CLAMP(ip
[4]); wp
[4] = (r1
-r2
) & mask
; r2
= r1
;
991 g1
= CLAMP(ip
[5]); wp
[5] = (g1
-g2
) & mask
; g2
= g1
;
992 b1
= CLAMP(ip
[6]); wp
[6] = (b1
-b2
) & mask
; b2
= b1
;
993 a1
= CLAMP(ip
[7]); wp
[7] = (a1
-a2
) & mask
; a2
= a1
;
998 wp
+= n
+ stride
- 1; /* point to last one */
999 ip
+= n
+ stride
- 1; /* point to last one */
1002 REPEAT(stride
, wp
[0] = CLAMP(ip
[0]);
1003 wp
[stride
] -= wp
[0];
1008 REPEAT(stride
, wp
[0] = CLAMP(ip
[0]); wp
--; ip
--)
1014 * Encode a chunk of pixels.
1017 PixarLogEncode(TIFF
* tif
, tidata_t bp
, tsize_t cc
, tsample_t s
)
1019 TIFFDirectory
*td
= &tif
->tif_dir
;
1020 PixarLogState
*sp
= EncoderState(tif
);
1021 static const char module[] = "PixarLogEncode";
1023 unsigned short * up
;
1027 switch (sp
->user_datafmt
) {
1028 case PIXARLOGDATAFMT_FLOAT
:
1029 n
= cc
/ sizeof(float); /* XXX float == 32 bits */
1031 case PIXARLOGDATAFMT_16BIT
:
1032 case PIXARLOGDATAFMT_12BITPICIO
:
1033 case PIXARLOGDATAFMT_11BITLOG
:
1034 n
= cc
/ sizeof(uint16
); /* XXX uint16 == 16 bits */
1036 case PIXARLOGDATAFMT_8BIT
:
1037 case PIXARLOGDATAFMT_8BITABGR
:
1041 TIFFError(tif
->tif_name
,
1042 "%d bit input not supported in PixarLog",
1043 td
->td_bitspersample
);
1047 llen
= sp
->stride
* td
->td_imagewidth
;
1049 for (i
= 0, up
= sp
->tbuf
; i
< n
; i
+= llen
, up
+= llen
) {
1050 switch (sp
->user_datafmt
) {
1051 case PIXARLOGDATAFMT_FLOAT
:
1052 horizontalDifferenceF((float *)bp
, llen
,
1053 sp
->stride
, up
, sp
->FromLT2
);
1054 bp
+= llen
* sizeof(float);
1056 case PIXARLOGDATAFMT_16BIT
:
1057 horizontalDifference16((uint16
*)bp
, llen
,
1058 sp
->stride
, up
, sp
->From14
);
1059 bp
+= llen
* sizeof(uint16
);
1061 case PIXARLOGDATAFMT_8BIT
:
1062 horizontalDifference8((unsigned char *)bp
, llen
,
1063 sp
->stride
, up
, sp
->From8
);
1064 bp
+= llen
* sizeof(unsigned char);
1067 TIFFError(tif
->tif_name
,
1068 "%d bit input not supported in PixarLog",
1069 td
->td_bitspersample
);
1074 sp
->stream
.next_in
= (unsigned char *) sp
->tbuf
;
1075 sp
->stream
.avail_in
= n
* sizeof(uint16
);
1078 if (deflate(&sp
->stream
, Z_NO_FLUSH
) != Z_OK
) {
1079 TIFFError(module, "%s: Encoder error: %s",
1080 tif
->tif_name
, sp
->stream
.msg
);
1083 if (sp
->stream
.avail_out
== 0) {
1084 tif
->tif_rawcc
= tif
->tif_rawdatasize
;
1085 TIFFFlushData1(tif
);
1086 sp
->stream
.next_out
= tif
->tif_rawdata
;
1087 sp
->stream
.avail_out
= tif
->tif_rawdatasize
;
1089 } while (sp
->stream
.avail_in
> 0);
1094 * Finish off an encoded strip by flushing the last
1095 * string and tacking on an End Of Information code.
1099 PixarLogPostEncode(TIFF
* tif
)
1101 PixarLogState
*sp
= EncoderState(tif
);
1102 static const char module[] = "PixarLogPostEncode";
1105 sp
->stream
.avail_in
= 0;
1108 state
= deflate(&sp
->stream
, Z_FINISH
);
1112 if (sp
->stream
.avail_out
!= tif
->tif_rawdatasize
) {
1114 tif
->tif_rawdatasize
- sp
->stream
.avail_out
;
1115 TIFFFlushData1(tif
);
1116 sp
->stream
.next_out
= tif
->tif_rawdata
;
1117 sp
->stream
.avail_out
= tif
->tif_rawdatasize
;
1121 TIFFError(module, "%s: zlib error: %s",
1122 tif
->tif_name
, sp
->stream
.msg
);
1125 } while (state
!= Z_STREAM_END
);
1130 PixarLogClose(TIFF
* tif
)
1132 TIFFDirectory
*td
= &tif
->tif_dir
;
1134 /* In a really sneaky maneuver, on close, we covertly modify both
1135 * bitspersample and sampleformat in the directory to indicate
1136 * 8-bit linear. This way, the decode "just works" even for
1137 * readers that don't know about PixarLog, or how to set
1138 * the PIXARLOGDATFMT pseudo-tag.
1140 td
->td_bitspersample
= 8;
1141 td
->td_sampleformat
= SAMPLEFORMAT_UINT
;
1145 PixarLogCleanup(TIFF
* tif
)
1147 PixarLogState
* sp
= (PixarLogState
*) tif
->tif_data
;
1150 if (sp
->FromLT2
) _TIFFfree(sp
->FromLT2
);
1151 if (sp
->From14
) _TIFFfree(sp
->From14
);
1152 if (sp
->From8
) _TIFFfree(sp
->From8
);
1153 if (sp
->ToLinearF
) _TIFFfree(sp
->ToLinearF
);
1154 if (sp
->ToLinear16
) _TIFFfree(sp
->ToLinear16
);
1155 if (sp
->ToLinear8
) _TIFFfree(sp
->ToLinear8
);
1156 if (sp
->state
&PLSTATE_INIT
) {
1157 if (tif
->tif_mode
== O_RDONLY
)
1158 inflateEnd(&sp
->stream
);
1160 deflateEnd(&sp
->stream
);
1163 _TIFFfree(sp
->tbuf
);
1165 tif
->tif_data
= NULL
;
1170 PixarLogVSetField(TIFF
* tif
, ttag_t tag
, va_list ap
)
1172 PixarLogState
*sp
= (PixarLogState
*)tif
->tif_data
;
1174 static const char module[] = "PixarLogVSetField";
1177 case TIFFTAG_PIXARLOGQUALITY
:
1178 sp
->quality
= va_arg(ap
, int);
1179 if (tif
->tif_mode
!= O_RDONLY
&& (sp
->state
&PLSTATE_INIT
)) {
1180 if (deflateParams(&sp
->stream
,
1181 sp
->quality
, Z_DEFAULT_STRATEGY
) != Z_OK
) {
1182 TIFFError(module, "%s: zlib error: %s",
1183 tif
->tif_name
, sp
->stream
.msg
);
1188 case TIFFTAG_PIXARLOGDATAFMT
:
1189 sp
->user_datafmt
= va_arg(ap
, int);
1190 /* Tweak the TIFF header so that the rest of libtiff knows what
1191 * size of data will be passed between app and library, and
1192 * assume that the app knows what it is doing and is not
1193 * confused by these header manipulations...
1195 switch (sp
->user_datafmt
) {
1196 case PIXARLOGDATAFMT_8BIT
:
1197 case PIXARLOGDATAFMT_8BITABGR
:
1198 TIFFSetField(tif
, TIFFTAG_BITSPERSAMPLE
, 8);
1199 TIFFSetField(tif
, TIFFTAG_SAMPLEFORMAT
, SAMPLEFORMAT_UINT
);
1201 case PIXARLOGDATAFMT_11BITLOG
:
1202 TIFFSetField(tif
, TIFFTAG_BITSPERSAMPLE
, 16);
1203 TIFFSetField(tif
, TIFFTAG_SAMPLEFORMAT
, SAMPLEFORMAT_UINT
);
1205 case PIXARLOGDATAFMT_12BITPICIO
:
1206 TIFFSetField(tif
, TIFFTAG_BITSPERSAMPLE
, 16);
1207 TIFFSetField(tif
, TIFFTAG_SAMPLEFORMAT
, SAMPLEFORMAT_INT
);
1209 case PIXARLOGDATAFMT_16BIT
:
1210 TIFFSetField(tif
, TIFFTAG_BITSPERSAMPLE
, 16);
1211 TIFFSetField(tif
, TIFFTAG_SAMPLEFORMAT
, SAMPLEFORMAT_UINT
);
1213 case PIXARLOGDATAFMT_FLOAT
:
1214 TIFFSetField(tif
, TIFFTAG_BITSPERSAMPLE
, 32);
1215 TIFFSetField(tif
, TIFFTAG_SAMPLEFORMAT
, SAMPLEFORMAT_IEEEFP
);
1219 * Must recalculate sizes should bits/sample change.
1221 tif
->tif_tilesize
= TIFFTileSize(tif
);
1222 tif
->tif_scanlinesize
= TIFFScanlineSize(tif
);
1223 result
= 1; /* NB: pseudo tag */
1226 result
= (*sp
->vsetparent
)(tif
, tag
, ap
);
1232 PixarLogVGetField(TIFF
* tif
, ttag_t tag
, va_list ap
)
1234 PixarLogState
*sp
= (PixarLogState
*)tif
->tif_data
;
1237 case TIFFTAG_PIXARLOGQUALITY
:
1238 *va_arg(ap
, int*) = sp
->quality
;
1240 case TIFFTAG_PIXARLOGDATAFMT
:
1241 *va_arg(ap
, int*) = sp
->user_datafmt
;
1244 return (*sp
->vgetparent
)(tif
, tag
, ap
);
1249 static const TIFFFieldInfo pixarlogFieldInfo
[] = {
1250 {TIFFTAG_PIXARLOGDATAFMT
,0,0,TIFF_ANY
, FIELD_PSEUDO
,FALSE
,FALSE
,""},
1251 {TIFFTAG_PIXARLOGQUALITY
,0,0,TIFF_ANY
, FIELD_PSEUDO
,FALSE
,FALSE
,""}
1255 TIFFInitPixarLog(TIFF
* tif
, int scheme
)
1259 assert(scheme
== COMPRESSION_PIXARLOG
);
1262 * Allocate state block so tag methods have storage to record values.
1264 tif
->tif_data
= (tidata_t
) _TIFFmalloc(sizeof (PixarLogState
));
1265 if (tif
->tif_data
== NULL
)
1267 sp
= (PixarLogState
*) tif
->tif_data
;
1268 memset(sp
, 0, sizeof (*sp
));
1269 sp
->stream
.data_type
= Z_BINARY
;
1270 sp
->user_datafmt
= PIXARLOGDATAFMT_UNKNOWN
;
1273 * Install codec methods.
1275 tif
->tif_setupdecode
= PixarLogSetupDecode
;
1276 tif
->tif_predecode
= PixarLogPreDecode
;
1277 tif
->tif_decoderow
= PixarLogDecode
;
1278 tif
->tif_decodestrip
= PixarLogDecode
;
1279 tif
->tif_decodetile
= PixarLogDecode
;
1280 tif
->tif_setupencode
= PixarLogSetupEncode
;
1281 tif
->tif_preencode
= PixarLogPreEncode
;
1282 tif
->tif_postencode
= PixarLogPostEncode
;
1283 tif
->tif_encoderow
= PixarLogEncode
;
1284 tif
->tif_encodestrip
= PixarLogEncode
;
1285 tif
->tif_encodetile
= PixarLogEncode
;
1286 tif
->tif_close
= PixarLogClose
;
1287 tif
->tif_cleanup
= PixarLogCleanup
;
1289 /* Override SetField so we can handle our private pseudo-tag */
1290 _TIFFMergeFieldInfo(tif
, pixarlogFieldInfo
, N(pixarlogFieldInfo
));
1291 sp
->vgetparent
= tif
->tif_vgetfield
;
1292 tif
->tif_vgetfield
= PixarLogVGetField
; /* hook for codec tags */
1293 sp
->vsetparent
= tif
->tif_vsetfield
;
1294 tif
->tif_vsetfield
= PixarLogVSetField
; /* hook for codec tags */
1296 /* Default values for codec-specific fields */
1297 sp
->quality
= Z_DEFAULT_COMPRESSION
; /* default comp. level */
1300 /* we don't wish to use the predictor,
1301 * the default is none, which predictor value 1
1303 (void) TIFFPredictorInit(tif
);
1306 * build the companding tables
1308 PixarLogMakeTables(sp
);
1312 TIFFError("TIFFInitPixarLog", "No space for PixarLog state block");
1315 #endif /* PIXARLOG_SUPPORT */