1 /* $Id: tif_pixarlog.c,v 1.15.2.4 2010-06-08 18:50:42 bfriesen Exp $ */
4 * Copyright (c) 1996-1997 Sam Leffler
5 * Copyright (c) 1996 Pixar
7 * Permission to use, copy, modify, distribute, and sell this software and
8 * its documentation for any purpose is hereby granted without fee, provided
9 * that (i) the above copyright notices and this permission notice appear in
10 * all copies of the software and related documentation, and (ii) the names of
11 * Pixar, Sam Leffler and Silicon Graphics may not be used in any advertising or
12 * publicity relating to the software without the specific, prior written
13 * permission of Pixar, Sam Leffler and Silicon Graphics.
15 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
17 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
19 * IN NO EVENT SHALL PIXAR, SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
20 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
21 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
22 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
23 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
28 #ifdef PIXARLOG_SUPPORT
32 * PixarLog Compression Support
34 * Contributed by Dan McCoy.
36 * PixarLog film support uses the TIFF library to store companded
37 * 11 bit values into a tiff file, which are compressed using the
40 * The codec can take as input and produce as output 32-bit IEEE float values
41 * as well as 16-bit or 8-bit unsigned integer values.
43 * On writing any of the above are converted into the internal
44 * 11-bit log format. In the case of 8 and 16 bit values, the
45 * input is assumed to be unsigned linear color values that represent
46 * the range 0-1. In the case of IEEE values, the 0-1 range is assumed to
47 * be the normal linear color range, in addition over 1 values are
48 * accepted up to a value of about 25.0 to encode "hot" hightlights and such.
49 * The encoding is lossless for 8-bit values, slightly lossy for the
50 * other bit depths. The actual color precision should be better
51 * than the human eye can perceive with extra room to allow for
52 * error introduced by further image computation. As with any quantized
53 * color format, it is possible to perform image calculations which
54 * expose the quantization error. This format should certainly be less
55 * susceptable to such errors than standard 8-bit encodings, but more
56 * susceptable than straight 16-bit or 32-bit encodings.
58 * On reading the internal format is converted to the desired output format.
59 * The program can request which format it desires by setting the internal
60 * pseudo tag TIFFTAG_PIXARLOGDATAFMT to one of these possible values:
61 * PIXARLOGDATAFMT_FLOAT = provide IEEE float values.
62 * PIXARLOGDATAFMT_16BIT = provide unsigned 16-bit integer values
63 * PIXARLOGDATAFMT_8BIT = provide unsigned 8-bit integer values
65 * alternately PIXARLOGDATAFMT_8BITABGR provides unsigned 8-bit integer
66 * values with the difference that if there are exactly three or four channels
67 * (rgb or rgba) it swaps the channel order (bgr or abgr).
69 * PIXARLOGDATAFMT_11BITLOG provides the internal encoding directly
70 * packed in 16-bit values. However no tools are supplied for interpreting
73 * "hot" (over 1.0) areas written in floating point get clamped to
74 * 1.0 in the integer data types.
76 * When the file is closed after writing, the bit depth and sample format
77 * are set always to appear as if 8-bit data has been written into it.
78 * That way a naive program unaware of the particulars of the encoding
79 * gets the format it is most likely able to handle.
81 * The codec does it's own horizontal differencing step on the coded
82 * values so the libraries predictor stuff should be turned off.
83 * The codec also handle byte swapping the encoded values as necessary
84 * since the library does not have the information necessary
85 * to know the bit depth of the raw unencoded buffer.
89 #include "tif_predict.h"
96 /* Tables for converting to/from 11 bit coded values */
98 #define TSIZE 2048 /* decode table size (11-bit tokens) */
99 #define TSIZEP1 2049 /* Plus one for slop */
100 #define ONE 1250 /* token value of 1.0 exactly */
101 #define RATIO 1.004 /* nominal ratio for log part */
103 #define CODE_MASK 0x7ff /* 11 bits. */
105 static float Fltsize
;
106 static float LogK1
, LogK2
;
108 #define REPEAT(n, op) { int i; i=n; do { i--; op; } while (i>0); }
111 horizontalAccumulateF(uint16
*wp
, int n
, int stride
, float *op
,
114 register unsigned int cr
, cg
, cb
, ca
, mask
;
115 register float t0
, t1
, t2
, t3
;
120 t0
= ToLinearF
[cr
= wp
[0]];
121 t1
= ToLinearF
[cg
= wp
[1]];
122 t2
= ToLinearF
[cb
= wp
[2]];
131 t0
= ToLinearF
[(cr
+= wp
[0]) & mask
];
132 t1
= ToLinearF
[(cg
+= wp
[1]) & mask
];
133 t2
= ToLinearF
[(cb
+= wp
[2]) & mask
];
138 } else if (stride
== 4) {
139 t0
= ToLinearF
[cr
= wp
[0]];
140 t1
= ToLinearF
[cg
= wp
[1]];
141 t2
= ToLinearF
[cb
= wp
[2]];
142 t3
= ToLinearF
[ca
= wp
[3]];
152 t0
= ToLinearF
[(cr
+= wp
[0]) & mask
];
153 t1
= ToLinearF
[(cg
+= wp
[1]) & mask
];
154 t2
= ToLinearF
[(cb
+= wp
[2]) & mask
];
155 t3
= ToLinearF
[(ca
+= wp
[3]) & mask
];
162 REPEAT(stride
, *op
= ToLinearF
[*wp
&mask
]; wp
++; op
++)
166 wp
[stride
] += *wp
; *op
= ToLinearF
[*wp
&mask
]; wp
++; op
++)
174 horizontalAccumulate12(uint16
*wp
, int n
, int stride
, int16
*op
,
177 register unsigned int cr
, cg
, cb
, ca
, mask
;
178 register float t0
, t1
, t2
, t3
;
180 #define SCALE12 2048.0F
181 #define CLAMP12(t) (((t) < 3071) ? (uint16) (t) : 3071)
186 t0
= ToLinearF
[cr
= wp
[0]] * SCALE12
;
187 t1
= ToLinearF
[cg
= wp
[1]] * SCALE12
;
188 t2
= ToLinearF
[cb
= wp
[2]] * SCALE12
;
197 t0
= ToLinearF
[(cr
+= wp
[0]) & mask
] * SCALE12
;
198 t1
= ToLinearF
[(cg
+= wp
[1]) & mask
] * SCALE12
;
199 t2
= ToLinearF
[(cb
+= wp
[2]) & mask
] * SCALE12
;
204 } else if (stride
== 4) {
205 t0
= ToLinearF
[cr
= wp
[0]] * SCALE12
;
206 t1
= ToLinearF
[cg
= wp
[1]] * SCALE12
;
207 t2
= ToLinearF
[cb
= wp
[2]] * SCALE12
;
208 t3
= ToLinearF
[ca
= wp
[3]] * SCALE12
;
218 t0
= ToLinearF
[(cr
+= wp
[0]) & mask
] * SCALE12
;
219 t1
= ToLinearF
[(cg
+= wp
[1]) & mask
] * SCALE12
;
220 t2
= ToLinearF
[(cb
+= wp
[2]) & mask
] * SCALE12
;
221 t3
= ToLinearF
[(ca
+= wp
[3]) & mask
] * SCALE12
;
228 REPEAT(stride
, t0
= ToLinearF
[*wp
&mask
] * SCALE12
;
229 *op
= CLAMP12(t0
); wp
++; op
++)
233 wp
[stride
] += *wp
; t0
= ToLinearF
[wp
[stride
]&mask
]*SCALE12
;
234 *op
= CLAMP12(t0
); wp
++; op
++)
242 horizontalAccumulate16(uint16
*wp
, int n
, int stride
, uint16
*op
,
245 register unsigned int cr
, cg
, cb
, ca
, mask
;
250 op
[0] = ToLinear16
[cr
= wp
[0]];
251 op
[1] = ToLinear16
[cg
= wp
[1]];
252 op
[2] = ToLinear16
[cb
= wp
[2]];
258 op
[0] = ToLinear16
[(cr
+= wp
[0]) & mask
];
259 op
[1] = ToLinear16
[(cg
+= wp
[1]) & mask
];
260 op
[2] = ToLinear16
[(cb
+= wp
[2]) & mask
];
262 } else if (stride
== 4) {
263 op
[0] = ToLinear16
[cr
= wp
[0]];
264 op
[1] = ToLinear16
[cg
= wp
[1]];
265 op
[2] = ToLinear16
[cb
= wp
[2]];
266 op
[3] = ToLinear16
[ca
= wp
[3]];
272 op
[0] = ToLinear16
[(cr
+= wp
[0]) & mask
];
273 op
[1] = ToLinear16
[(cg
+= wp
[1]) & mask
];
274 op
[2] = ToLinear16
[(cb
+= wp
[2]) & mask
];
275 op
[3] = ToLinear16
[(ca
+= wp
[3]) & mask
];
278 REPEAT(stride
, *op
= ToLinear16
[*wp
&mask
]; wp
++; op
++)
282 wp
[stride
] += *wp
; *op
= ToLinear16
[*wp
&mask
]; wp
++; op
++)
290 * Returns the log encoded 11-bit values with the horizontal
291 * differencing undone.
294 horizontalAccumulate11(uint16
*wp
, int n
, int stride
, uint16
*op
)
296 register unsigned int cr
, cg
, cb
, ca
, mask
;
301 op
[0] = cr
= wp
[0]; op
[1] = cg
= wp
[1]; op
[2] = cb
= wp
[2];
307 op
[0] = (cr
+= wp
[0]) & mask
;
308 op
[1] = (cg
+= wp
[1]) & mask
;
309 op
[2] = (cb
+= wp
[2]) & mask
;
311 } else if (stride
== 4) {
312 op
[0] = cr
= wp
[0]; op
[1] = cg
= wp
[1];
313 op
[2] = cb
= wp
[2]; op
[3] = ca
= wp
[3];
319 op
[0] = (cr
+= wp
[0]) & mask
;
320 op
[1] = (cg
+= wp
[1]) & mask
;
321 op
[2] = (cb
+= wp
[2]) & mask
;
322 op
[3] = (ca
+= wp
[3]) & mask
;
325 REPEAT(stride
, *op
= *wp
&mask
; wp
++; op
++)
329 wp
[stride
] += *wp
; *op
= *wp
&mask
; wp
++; op
++)
337 horizontalAccumulate8(uint16
*wp
, int n
, int stride
, unsigned char *op
,
338 unsigned char *ToLinear8
)
340 register unsigned int cr
, cg
, cb
, ca
, mask
;
345 op
[0] = ToLinear8
[cr
= wp
[0]];
346 op
[1] = ToLinear8
[cg
= wp
[1]];
347 op
[2] = ToLinear8
[cb
= wp
[2]];
353 op
[0] = ToLinear8
[(cr
+= wp
[0]) & mask
];
354 op
[1] = ToLinear8
[(cg
+= wp
[1]) & mask
];
355 op
[2] = ToLinear8
[(cb
+= wp
[2]) & mask
];
357 } else if (stride
== 4) {
358 op
[0] = ToLinear8
[cr
= wp
[0]];
359 op
[1] = ToLinear8
[cg
= wp
[1]];
360 op
[2] = ToLinear8
[cb
= wp
[2]];
361 op
[3] = ToLinear8
[ca
= wp
[3]];
367 op
[0] = ToLinear8
[(cr
+= wp
[0]) & mask
];
368 op
[1] = ToLinear8
[(cg
+= wp
[1]) & mask
];
369 op
[2] = ToLinear8
[(cb
+= wp
[2]) & mask
];
370 op
[3] = ToLinear8
[(ca
+= wp
[3]) & mask
];
373 REPEAT(stride
, *op
= ToLinear8
[*wp
&mask
]; wp
++; op
++)
377 wp
[stride
] += *wp
; *op
= ToLinear8
[*wp
&mask
]; wp
++; op
++)
386 horizontalAccumulate8abgr(uint16
*wp
, int n
, int stride
, unsigned char *op
,
387 unsigned char *ToLinear8
)
389 register unsigned int cr
, cg
, cb
, ca
, mask
;
390 register unsigned char t0
, t1
, t2
, t3
;
396 t1
= ToLinear8
[cb
= wp
[2]];
397 t2
= ToLinear8
[cg
= wp
[1]];
398 t3
= ToLinear8
[cr
= wp
[0]];
408 t1
= ToLinear8
[(cb
+= wp
[2]) & mask
];
409 t2
= ToLinear8
[(cg
+= wp
[1]) & mask
];
410 t3
= ToLinear8
[(cr
+= wp
[0]) & mask
];
415 } else if (stride
== 4) {
416 t0
= ToLinear8
[ca
= wp
[3]];
417 t1
= ToLinear8
[cb
= wp
[2]];
418 t2
= ToLinear8
[cg
= wp
[1]];
419 t3
= ToLinear8
[cr
= wp
[0]];
429 t0
= ToLinear8
[(ca
+= wp
[3]) & mask
];
430 t1
= ToLinear8
[(cb
+= wp
[2]) & mask
];
431 t2
= ToLinear8
[(cg
+= wp
[1]) & mask
];
432 t3
= ToLinear8
[(cr
+= wp
[0]) & mask
];
439 REPEAT(stride
, *op
= ToLinear8
[*wp
&mask
]; wp
++; op
++)
443 wp
[stride
] += *wp
; *op
= ToLinear8
[*wp
&mask
]; wp
++; op
++)
451 * State block for each open TIFF
452 * file using PixarLog compression/decompression.
455 TIFFPredictorState predict
;
462 #define PLSTATE_INIT 1
464 TIFFVSetMethod vgetparent
; /* super-class method */
465 TIFFVSetMethod vsetparent
; /* super-class method */
469 unsigned char *ToLinear8
;
471 uint16
*From14
; /* Really for 16-bit data, but we shift down 2 */
477 PixarLogMakeTables(PixarLogState
*sp
)
481 * We make several tables here to convert between various external
482 * representations (float, 16-bit, and 8-bit) and the internal
483 * 11-bit companded representation. The 11-bit representation has two
484 * distinct regions. A linear bottom end up through .018316 in steps
485 * of about .000073, and a region of constant ratio up to about 25.
486 * These floating point numbers are stored in the main table ToLinearF.
487 * All other tables are derived from this one. The tables (and the
488 * ratios) are continuous at the internal seam.
493 double b
, c
, linstep
, v
;
496 unsigned char *ToLinear8
;
498 uint16
*From14
; /* Really for 16-bit data, but we shift down 2 */
502 nlin
= (int)(1./c
); /* nlin must be an integer */
504 b
= exp(-c
*ONE
); /* multiplicative scale factor [b*exp(c*ONE) = 1] */
505 linstep
= b
*c
*exp(1.);
507 LogK1
= (float)(1./c
); /* if (v >= 2) token = k1*log(v*k2) */
508 LogK2
= (float)(1./b
);
509 lt2size
= (int)(2./linstep
) + 1;
510 FromLT2
= (uint16
*)_TIFFmalloc(lt2size
*sizeof(uint16
));
511 From14
= (uint16
*)_TIFFmalloc(16384*sizeof(uint16
));
512 From8
= (uint16
*)_TIFFmalloc(256*sizeof(uint16
));
513 ToLinearF
= (float *)_TIFFmalloc(TSIZEP1
* sizeof(float));
514 ToLinear16
= (uint16
*)_TIFFmalloc(TSIZEP1
* sizeof(uint16
));
515 ToLinear8
= (unsigned char *)_TIFFmalloc(TSIZEP1
* sizeof(unsigned char));
516 if (FromLT2
== NULL
|| From14
== NULL
|| From8
== NULL
||
517 ToLinearF
== NULL
|| ToLinear16
== NULL
|| ToLinear8
== NULL
) {
518 if (FromLT2
) _TIFFfree(FromLT2
);
519 if (From14
) _TIFFfree(From14
);
520 if (From8
) _TIFFfree(From8
);
521 if (ToLinearF
) _TIFFfree(ToLinearF
);
522 if (ToLinear16
) _TIFFfree(ToLinear16
);
523 if (ToLinear8
) _TIFFfree(ToLinear8
);
527 sp
->ToLinearF
= NULL
;
528 sp
->ToLinear16
= NULL
;
529 sp
->ToLinear8
= NULL
;
535 for (i
= 0; i
< nlin
; i
++) {
537 ToLinearF
[j
++] = (float)v
;
540 for (i
= nlin
; i
< TSIZE
; i
++)
541 ToLinearF
[j
++] = (float)(b
*exp(c
*i
));
543 ToLinearF
[2048] = ToLinearF
[2047];
545 for (i
= 0; i
< TSIZEP1
; i
++) {
546 v
= ToLinearF
[i
]*65535.0 + 0.5;
547 ToLinear16
[i
] = (v
> 65535.0) ? 65535 : (uint16
)v
;
548 v
= ToLinearF
[i
]*255.0 + 0.5;
549 ToLinear8
[i
] = (v
> 255.0) ? 255 : (unsigned char)v
;
553 for (i
= 0; i
< lt2size
; i
++) {
554 if ((i
*linstep
)*(i
*linstep
) > ToLinearF
[j
]*ToLinearF
[j
+1])
560 * Since we lose info anyway on 16-bit data, we set up a 14-bit
561 * table and shift 16-bit values down two bits on input.
562 * saves a little table space.
565 for (i
= 0; i
< 16384; i
++) {
566 while ((i
/16383.)*(i
/16383.) > ToLinearF
[j
]*ToLinearF
[j
+1])
572 for (i
= 0; i
< 256; i
++) {
573 while ((i
/255.)*(i
/255.) > ToLinearF
[j
]*ToLinearF
[j
+1])
578 Fltsize
= (float)(lt2size
/2);
580 sp
->ToLinearF
= ToLinearF
;
581 sp
->ToLinear16
= ToLinear16
;
582 sp
->ToLinear8
= ToLinear8
;
583 sp
->FromLT2
= FromLT2
;
590 #define DecoderState(tif) ((PixarLogState*) (tif)->tif_data)
591 #define EncoderState(tif) ((PixarLogState*) (tif)->tif_data)
593 static int PixarLogEncode(TIFF
*, tidata_t
, tsize_t
, tsample_t
);
594 static int PixarLogDecode(TIFF
*, tidata_t
, tsize_t
, tsample_t
);
596 #define PIXARLOGDATAFMT_UNKNOWN -1
599 PixarLogGuessDataFmt(TIFFDirectory
*td
)
601 int guess
= PIXARLOGDATAFMT_UNKNOWN
;
602 int format
= td
->td_sampleformat
;
604 /* If the user didn't tell us his datafmt,
605 * take our best guess from the bitspersample.
607 switch (td
->td_bitspersample
) {
609 if (format
== SAMPLEFORMAT_IEEEFP
)
610 guess
= PIXARLOGDATAFMT_FLOAT
;
613 if (format
== SAMPLEFORMAT_VOID
|| format
== SAMPLEFORMAT_UINT
)
614 guess
= PIXARLOGDATAFMT_16BIT
;
617 if (format
== SAMPLEFORMAT_VOID
|| format
== SAMPLEFORMAT_INT
)
618 guess
= PIXARLOGDATAFMT_12BITPICIO
;
621 if (format
== SAMPLEFORMAT_VOID
|| format
== SAMPLEFORMAT_UINT
)
622 guess
= PIXARLOGDATAFMT_11BITLOG
;
625 if (format
== SAMPLEFORMAT_VOID
|| format
== SAMPLEFORMAT_UINT
)
626 guess
= PIXARLOGDATAFMT_8BIT
;
634 multiply(size_t m1
, size_t m2
)
636 uint32 bytes
= m1
* m2
;
638 if (m1
&& bytes
/ m1
!= m2
)
645 PixarLogSetupDecode(TIFF
* tif
)
647 TIFFDirectory
*td
= &tif
->tif_dir
;
648 PixarLogState
* sp
= DecoderState(tif
);
650 static const char module
[] = "PixarLogSetupDecode";
654 /* Make sure no byte swapping happens on the data
655 * after decompression. */
656 tif
->tif_postdecode
= _TIFFNoPostDecode
;
658 /* for some reason, we can't do this in TIFFInitPixarLog */
660 sp
->stride
= (td
->td_planarconfig
== PLANARCONFIG_CONTIG
?
661 td
->td_samplesperpixel
: 1);
662 tbuf_size
= multiply(multiply(multiply(sp
->stride
, td
->td_imagewidth
),
663 td
->td_rowsperstrip
), sizeof(uint16
));
666 sp
->tbuf
= (uint16
*) _TIFFmalloc(tbuf_size
);
667 if (sp
->tbuf
== NULL
)
669 if (sp
->user_datafmt
== PIXARLOGDATAFMT_UNKNOWN
)
670 sp
->user_datafmt
= PixarLogGuessDataFmt(td
);
671 if (sp
->user_datafmt
== PIXARLOGDATAFMT_UNKNOWN
) {
672 TIFFErrorExt(tif
->tif_clientdata
, module
,
673 "PixarLog compression can't handle bits depth/data format combination (depth: %d)",
674 td
->td_bitspersample
);
678 if (inflateInit(&sp
->stream
) != Z_OK
) {
679 TIFFErrorExt(tif
->tif_clientdata
, module
, "%s: %s", tif
->tif_name
, sp
->stream
.msg
);
682 sp
->state
|= PLSTATE_INIT
;
688 * Setup state for decoding a strip.
691 PixarLogPreDecode(TIFF
* tif
, tsample_t s
)
693 PixarLogState
* sp
= DecoderState(tif
);
697 sp
->stream
.next_in
= tif
->tif_rawdata
;
698 sp
->stream
.avail_in
= tif
->tif_rawcc
;
699 return (inflateReset(&sp
->stream
) == Z_OK
);
703 PixarLogDecode(TIFF
* tif
, tidata_t op
, tsize_t occ
, tsample_t s
)
705 TIFFDirectory
*td
= &tif
->tif_dir
;
706 PixarLogState
* sp
= DecoderState(tif
);
707 static const char module
[] = "PixarLogDecode";
708 int i
, nsamples
, llen
;
711 switch (sp
->user_datafmt
) {
712 case PIXARLOGDATAFMT_FLOAT
:
713 nsamples
= occ
/ sizeof(float); /* XXX float == 32 bits */
715 case PIXARLOGDATAFMT_16BIT
:
716 case PIXARLOGDATAFMT_12BITPICIO
:
717 case PIXARLOGDATAFMT_11BITLOG
:
718 nsamples
= occ
/ sizeof(uint16
); /* XXX uint16 == 16 bits */
720 case PIXARLOGDATAFMT_8BIT
:
721 case PIXARLOGDATAFMT_8BITABGR
:
725 TIFFErrorExt(tif
->tif_clientdata
, tif
->tif_name
,
726 "%d bit input not supported in PixarLog",
727 td
->td_bitspersample
);
731 llen
= sp
->stride
* td
->td_imagewidth
;
735 sp
->stream
.next_out
= (unsigned char *) sp
->tbuf
;
736 sp
->stream
.avail_out
= nsamples
* sizeof(uint16
);
738 int state
= inflate(&sp
->stream
, Z_PARTIAL_FLUSH
);
739 if (state
== Z_STREAM_END
) {
742 if (state
== Z_DATA_ERROR
) {
743 TIFFErrorExt(tif
->tif_clientdata
, module
,
744 "%s: Decoding error at scanline %d, %s",
745 tif
->tif_name
, tif
->tif_row
, sp
->stream
.msg
);
746 if (inflateSync(&sp
->stream
) != Z_OK
)
751 TIFFErrorExt(tif
->tif_clientdata
, module
, "%s: zlib error: %s",
752 tif
->tif_name
, sp
->stream
.msg
);
755 } while (sp
->stream
.avail_out
> 0);
757 /* hopefully, we got all the bytes we needed */
758 if (sp
->stream
.avail_out
!= 0) {
759 TIFFErrorExt(tif
->tif_clientdata
, module
,
760 "%s: Not enough data at scanline %d (short %d bytes)",
761 tif
->tif_name
, tif
->tif_row
, sp
->stream
.avail_out
);
766 /* Swap bytes in the data if from a different endian machine. */
767 if (tif
->tif_flags
& TIFF_SWAB
)
768 TIFFSwabArrayOfShort(up
, nsamples
);
771 * if llen is not an exact multiple of nsamples, the decode operation
772 * may overflow the output buffer, so truncate it enough to prevent
773 * that but still salvage as much data as possible.
775 if (nsamples
% llen
) {
776 TIFFWarningExt(tif
->tif_clientdata
, module
,
777 "%s: stride %d is not a multiple of sample count, "
778 "%d, data truncated.", tif
->tif_name
, llen
, nsamples
);
779 nsamples
-= nsamples
% llen
;
782 for (i
= 0; i
< nsamples
; i
+= llen
, up
+= llen
) {
783 switch (sp
->user_datafmt
) {
784 case PIXARLOGDATAFMT_FLOAT
:
785 horizontalAccumulateF(up
, llen
, sp
->stride
,
786 (float *)op
, sp
->ToLinearF
);
787 op
+= llen
* sizeof(float);
789 case PIXARLOGDATAFMT_16BIT
:
790 horizontalAccumulate16(up
, llen
, sp
->stride
,
791 (uint16
*)op
, sp
->ToLinear16
);
792 op
+= llen
* sizeof(uint16
);
794 case PIXARLOGDATAFMT_12BITPICIO
:
795 horizontalAccumulate12(up
, llen
, sp
->stride
,
796 (int16
*)op
, sp
->ToLinearF
);
797 op
+= llen
* sizeof(int16
);
799 case PIXARLOGDATAFMT_11BITLOG
:
800 horizontalAccumulate11(up
, llen
, sp
->stride
,
802 op
+= llen
* sizeof(uint16
);
804 case PIXARLOGDATAFMT_8BIT
:
805 horizontalAccumulate8(up
, llen
, sp
->stride
,
806 (unsigned char *)op
, sp
->ToLinear8
);
807 op
+= llen
* sizeof(unsigned char);
809 case PIXARLOGDATAFMT_8BITABGR
:
810 horizontalAccumulate8abgr(up
, llen
, sp
->stride
,
811 (unsigned char *)op
, sp
->ToLinear8
);
812 op
+= llen
* sizeof(unsigned char);
815 TIFFErrorExt(tif
->tif_clientdata
, tif
->tif_name
,
816 "PixarLogDecode: unsupported bits/sample: %d",
817 td
->td_bitspersample
);
826 PixarLogSetupEncode(TIFF
* tif
)
828 TIFFDirectory
*td
= &tif
->tif_dir
;
829 PixarLogState
* sp
= EncoderState(tif
);
831 static const char module
[] = "PixarLogSetupEncode";
835 /* for some reason, we can't do this in TIFFInitPixarLog */
837 sp
->stride
= (td
->td_planarconfig
== PLANARCONFIG_CONTIG
?
838 td
->td_samplesperpixel
: 1);
839 tbuf_size
= multiply(multiply(multiply(sp
->stride
, td
->td_imagewidth
),
840 td
->td_rowsperstrip
), sizeof(uint16
));
843 sp
->tbuf
= (uint16
*) _TIFFmalloc(tbuf_size
);
844 if (sp
->tbuf
== NULL
)
846 if (sp
->user_datafmt
== PIXARLOGDATAFMT_UNKNOWN
)
847 sp
->user_datafmt
= PixarLogGuessDataFmt(td
);
848 if (sp
->user_datafmt
== PIXARLOGDATAFMT_UNKNOWN
) {
849 TIFFErrorExt(tif
->tif_clientdata
, module
, "PixarLog compression can't handle %d bit linear encodings", td
->td_bitspersample
);
853 if (deflateInit(&sp
->stream
, sp
->quality
) != Z_OK
) {
854 TIFFErrorExt(tif
->tif_clientdata
, module
, "%s: %s", tif
->tif_name
, sp
->stream
.msg
);
857 sp
->state
|= PLSTATE_INIT
;
863 * Reset encoding state at the start of a strip.
866 PixarLogPreEncode(TIFF
* tif
, tsample_t s
)
868 PixarLogState
*sp
= EncoderState(tif
);
872 sp
->stream
.next_out
= tif
->tif_rawdata
;
873 sp
->stream
.avail_out
= tif
->tif_rawdatasize
;
874 return (deflateReset(&sp
->stream
) == Z_OK
);
878 horizontalDifferenceF(float *ip
, int n
, int stride
, uint16
*wp
, uint16
*FromLT2
)
881 int32 r1
, g1
, b1
, a1
, r2
, g2
, b2
, a2
, mask
;
882 float fltsize
= Fltsize
;
884 #define CLAMP(v) ( (v<(float)0.) ? 0 \
885 : (v<(float)2.) ? FromLT2[(int)(v*fltsize)] \
886 : (v>(float)24.2) ? 2047 \
887 : LogK1*log(v*LogK2) + 0.5 )
892 r2
= wp
[0] = (uint16
) CLAMP(ip
[0]);
893 g2
= wp
[1] = (uint16
) CLAMP(ip
[1]);
894 b2
= wp
[2] = (uint16
) CLAMP(ip
[2]);
900 r1
= (int32
) CLAMP(ip
[0]); wp
[0] = (r1
-r2
) & mask
; r2
= r1
;
901 g1
= (int32
) CLAMP(ip
[1]); wp
[1] = (g1
-g2
) & mask
; g2
= g1
;
902 b1
= (int32
) CLAMP(ip
[2]); wp
[2] = (b1
-b2
) & mask
; b2
= b1
;
904 } else if (stride
== 4) {
905 r2
= wp
[0] = (uint16
) CLAMP(ip
[0]);
906 g2
= wp
[1] = (uint16
) CLAMP(ip
[1]);
907 b2
= wp
[2] = (uint16
) CLAMP(ip
[2]);
908 a2
= wp
[3] = (uint16
) CLAMP(ip
[3]);
914 r1
= (int32
) CLAMP(ip
[0]); wp
[0] = (r1
-r2
) & mask
; r2
= r1
;
915 g1
= (int32
) CLAMP(ip
[1]); wp
[1] = (g1
-g2
) & mask
; g2
= g1
;
916 b1
= (int32
) CLAMP(ip
[2]); wp
[2] = (b1
-b2
) & mask
; b2
= b1
;
917 a1
= (int32
) CLAMP(ip
[3]); wp
[3] = (a1
-a2
) & mask
; a2
= a1
;
920 ip
+= n
- 1; /* point to last one */
921 wp
+= n
- 1; /* point to last one */
924 REPEAT(stride
, wp
[0] = (uint16
) CLAMP(ip
[0]);
930 REPEAT(stride
, wp
[0] = (uint16
) CLAMP(ip
[0]); wp
--; ip
--)
936 horizontalDifference16(unsigned short *ip
, int n
, int stride
,
937 unsigned short *wp
, uint16
*From14
)
939 register int r1
, g1
, b1
, a1
, r2
, g2
, b2
, a2
, mask
;
941 /* assumption is unsigned pixel values */
943 #define CLAMP(v) From14[(v) >> 2]
948 r2
= wp
[0] = CLAMP(ip
[0]); g2
= wp
[1] = CLAMP(ip
[1]);
949 b2
= wp
[2] = CLAMP(ip
[2]);
955 r1
= CLAMP(ip
[0]); wp
[0] = (r1
-r2
) & mask
; r2
= r1
;
956 g1
= CLAMP(ip
[1]); wp
[1] = (g1
-g2
) & mask
; g2
= g1
;
957 b1
= CLAMP(ip
[2]); wp
[2] = (b1
-b2
) & mask
; b2
= b1
;
959 } else if (stride
== 4) {
960 r2
= wp
[0] = CLAMP(ip
[0]); g2
= wp
[1] = CLAMP(ip
[1]);
961 b2
= wp
[2] = CLAMP(ip
[2]); a2
= wp
[3] = CLAMP(ip
[3]);
967 r1
= CLAMP(ip
[0]); wp
[0] = (r1
-r2
) & mask
; r2
= r1
;
968 g1
= CLAMP(ip
[1]); wp
[1] = (g1
-g2
) & mask
; g2
= g1
;
969 b1
= CLAMP(ip
[2]); wp
[2] = (b1
-b2
) & mask
; b2
= b1
;
970 a1
= CLAMP(ip
[3]); wp
[3] = (a1
-a2
) & mask
; a2
= a1
;
973 ip
+= n
- 1; /* point to last one */
974 wp
+= n
- 1; /* point to last one */
977 REPEAT(stride
, wp
[0] = CLAMP(ip
[0]);
983 REPEAT(stride
, wp
[0] = CLAMP(ip
[0]); wp
--; ip
--)
990 horizontalDifference8(unsigned char *ip
, int n
, int stride
,
991 unsigned short *wp
, uint16
*From8
)
993 register int r1
, g1
, b1
, a1
, r2
, g2
, b2
, a2
, mask
;
996 #define CLAMP(v) (From8[(v)])
1001 r2
= wp
[0] = CLAMP(ip
[0]); g2
= wp
[1] = CLAMP(ip
[1]);
1002 b2
= wp
[2] = CLAMP(ip
[2]);
1006 r1
= CLAMP(ip
[3]); wp
[3] = (r1
-r2
) & mask
; r2
= r1
;
1007 g1
= CLAMP(ip
[4]); wp
[4] = (g1
-g2
) & mask
; g2
= g1
;
1008 b1
= CLAMP(ip
[5]); wp
[5] = (b1
-b2
) & mask
; b2
= b1
;
1012 } else if (stride
== 4) {
1013 r2
= wp
[0] = CLAMP(ip
[0]); g2
= wp
[1] = CLAMP(ip
[1]);
1014 b2
= wp
[2] = CLAMP(ip
[2]); a2
= wp
[3] = CLAMP(ip
[3]);
1018 r1
= CLAMP(ip
[4]); wp
[4] = (r1
-r2
) & mask
; r2
= r1
;
1019 g1
= CLAMP(ip
[5]); wp
[5] = (g1
-g2
) & mask
; g2
= g1
;
1020 b1
= CLAMP(ip
[6]); wp
[6] = (b1
-b2
) & mask
; b2
= b1
;
1021 a1
= CLAMP(ip
[7]); wp
[7] = (a1
-a2
) & mask
; a2
= a1
;
1026 wp
+= n
+ stride
- 1; /* point to last one */
1027 ip
+= n
+ stride
- 1; /* point to last one */
1030 REPEAT(stride
, wp
[0] = CLAMP(ip
[0]);
1031 wp
[stride
] -= wp
[0];
1036 REPEAT(stride
, wp
[0] = CLAMP(ip
[0]); wp
--; ip
--)
1042 * Encode a chunk of pixels.
1045 PixarLogEncode(TIFF
* tif
, tidata_t bp
, tsize_t cc
, tsample_t s
)
1047 TIFFDirectory
*td
= &tif
->tif_dir
;
1048 PixarLogState
*sp
= EncoderState(tif
);
1049 static const char module
[] = "PixarLogEncode";
1051 unsigned short * up
;
1055 switch (sp
->user_datafmt
) {
1056 case PIXARLOGDATAFMT_FLOAT
:
1057 n
= cc
/ sizeof(float); /* XXX float == 32 bits */
1059 case PIXARLOGDATAFMT_16BIT
:
1060 case PIXARLOGDATAFMT_12BITPICIO
:
1061 case PIXARLOGDATAFMT_11BITLOG
:
1062 n
= cc
/ sizeof(uint16
); /* XXX uint16 == 16 bits */
1064 case PIXARLOGDATAFMT_8BIT
:
1065 case PIXARLOGDATAFMT_8BITABGR
:
1069 TIFFErrorExt(tif
->tif_clientdata
, tif
->tif_name
,
1070 "%d bit input not supported in PixarLog",
1071 td
->td_bitspersample
);
1075 llen
= sp
->stride
* td
->td_imagewidth
;
1077 for (i
= 0, up
= sp
->tbuf
; i
< n
; i
+= llen
, up
+= llen
) {
1078 switch (sp
->user_datafmt
) {
1079 case PIXARLOGDATAFMT_FLOAT
:
1080 horizontalDifferenceF((float *)bp
, llen
,
1081 sp
->stride
, up
, sp
->FromLT2
);
1082 bp
+= llen
* sizeof(float);
1084 case PIXARLOGDATAFMT_16BIT
:
1085 horizontalDifference16((uint16
*)bp
, llen
,
1086 sp
->stride
, up
, sp
->From14
);
1087 bp
+= llen
* sizeof(uint16
);
1089 case PIXARLOGDATAFMT_8BIT
:
1090 horizontalDifference8((unsigned char *)bp
, llen
,
1091 sp
->stride
, up
, sp
->From8
);
1092 bp
+= llen
* sizeof(unsigned char);
1095 TIFFErrorExt(tif
->tif_clientdata
, tif
->tif_name
,
1096 "%d bit input not supported in PixarLog",
1097 td
->td_bitspersample
);
1102 sp
->stream
.next_in
= (unsigned char *) sp
->tbuf
;
1103 sp
->stream
.avail_in
= n
* sizeof(uint16
);
1106 if (deflate(&sp
->stream
, Z_NO_FLUSH
) != Z_OK
) {
1107 TIFFErrorExt(tif
->tif_clientdata
, module
, "%s: Encoder error: %s",
1108 tif
->tif_name
, sp
->stream
.msg
);
1111 if (sp
->stream
.avail_out
== 0) {
1112 tif
->tif_rawcc
= tif
->tif_rawdatasize
;
1113 TIFFFlushData1(tif
);
1114 sp
->stream
.next_out
= tif
->tif_rawdata
;
1115 sp
->stream
.avail_out
= tif
->tif_rawdatasize
;
1117 } while (sp
->stream
.avail_in
> 0);
1122 * Finish off an encoded strip by flushing the last
1123 * string and tacking on an End Of Information code.
1127 PixarLogPostEncode(TIFF
* tif
)
1129 PixarLogState
*sp
= EncoderState(tif
);
1130 static const char module
[] = "PixarLogPostEncode";
1133 sp
->stream
.avail_in
= 0;
1136 state
= deflate(&sp
->stream
, Z_FINISH
);
1140 if (sp
->stream
.avail_out
!= (uint32
)tif
->tif_rawdatasize
) {
1142 tif
->tif_rawdatasize
- sp
->stream
.avail_out
;
1143 TIFFFlushData1(tif
);
1144 sp
->stream
.next_out
= tif
->tif_rawdata
;
1145 sp
->stream
.avail_out
= tif
->tif_rawdatasize
;
1149 TIFFErrorExt(tif
->tif_clientdata
, module
, "%s: zlib error: %s",
1150 tif
->tif_name
, sp
->stream
.msg
);
1153 } while (state
!= Z_STREAM_END
);
1158 PixarLogClose(TIFF
* tif
)
1160 TIFFDirectory
*td
= &tif
->tif_dir
;
1162 /* In a really sneaky maneuver, on close, we covertly modify both
1163 * bitspersample and sampleformat in the directory to indicate
1164 * 8-bit linear. This way, the decode "just works" even for
1165 * readers that don't know about PixarLog, or how to set
1166 * the PIXARLOGDATFMT pseudo-tag.
1168 td
->td_bitspersample
= 8;
1169 td
->td_sampleformat
= SAMPLEFORMAT_UINT
;
1173 PixarLogCleanup(TIFF
* tif
)
1175 PixarLogState
* sp
= (PixarLogState
*) tif
->tif_data
;
1179 (void)TIFFPredictorCleanup(tif
);
1181 tif
->tif_tagmethods
.vgetfield
= sp
->vgetparent
;
1182 tif
->tif_tagmethods
.vsetfield
= sp
->vsetparent
;
1184 if (sp
->FromLT2
) _TIFFfree(sp
->FromLT2
);
1185 if (sp
->From14
) _TIFFfree(sp
->From14
);
1186 if (sp
->From8
) _TIFFfree(sp
->From8
);
1187 if (sp
->ToLinearF
) _TIFFfree(sp
->ToLinearF
);
1188 if (sp
->ToLinear16
) _TIFFfree(sp
->ToLinear16
);
1189 if (sp
->ToLinear8
) _TIFFfree(sp
->ToLinear8
);
1190 if (sp
->state
&PLSTATE_INIT
) {
1191 if (tif
->tif_mode
== O_RDONLY
)
1192 inflateEnd(&sp
->stream
);
1194 deflateEnd(&sp
->stream
);
1197 _TIFFfree(sp
->tbuf
);
1199 tif
->tif_data
= NULL
;
1201 _TIFFSetDefaultCompressionState(tif
);
1205 PixarLogVSetField(TIFF
* tif
, ttag_t tag
, va_list ap
)
1207 PixarLogState
*sp
= (PixarLogState
*)tif
->tif_data
;
1209 static const char module
[] = "PixarLogVSetField";
1212 case TIFFTAG_PIXARLOGQUALITY
:
1213 sp
->quality
= va_arg(ap
, int);
1214 if (tif
->tif_mode
!= O_RDONLY
&& (sp
->state
&PLSTATE_INIT
)) {
1215 if (deflateParams(&sp
->stream
,
1216 sp
->quality
, Z_DEFAULT_STRATEGY
) != Z_OK
) {
1217 TIFFErrorExt(tif
->tif_clientdata
, module
, "%s: zlib error: %s",
1218 tif
->tif_name
, sp
->stream
.msg
);
1223 case TIFFTAG_PIXARLOGDATAFMT
:
1224 sp
->user_datafmt
= va_arg(ap
, int);
1225 /* Tweak the TIFF header so that the rest of libtiff knows what
1226 * size of data will be passed between app and library, and
1227 * assume that the app knows what it is doing and is not
1228 * confused by these header manipulations...
1230 switch (sp
->user_datafmt
) {
1231 case PIXARLOGDATAFMT_8BIT
:
1232 case PIXARLOGDATAFMT_8BITABGR
:
1233 TIFFSetField(tif
, TIFFTAG_BITSPERSAMPLE
, 8);
1234 TIFFSetField(tif
, TIFFTAG_SAMPLEFORMAT
, SAMPLEFORMAT_UINT
);
1236 case PIXARLOGDATAFMT_11BITLOG
:
1237 TIFFSetField(tif
, TIFFTAG_BITSPERSAMPLE
, 16);
1238 TIFFSetField(tif
, TIFFTAG_SAMPLEFORMAT
, SAMPLEFORMAT_UINT
);
1240 case PIXARLOGDATAFMT_12BITPICIO
:
1241 TIFFSetField(tif
, TIFFTAG_BITSPERSAMPLE
, 16);
1242 TIFFSetField(tif
, TIFFTAG_SAMPLEFORMAT
, SAMPLEFORMAT_INT
);
1244 case PIXARLOGDATAFMT_16BIT
:
1245 TIFFSetField(tif
, TIFFTAG_BITSPERSAMPLE
, 16);
1246 TIFFSetField(tif
, TIFFTAG_SAMPLEFORMAT
, SAMPLEFORMAT_UINT
);
1248 case PIXARLOGDATAFMT_FLOAT
:
1249 TIFFSetField(tif
, TIFFTAG_BITSPERSAMPLE
, 32);
1250 TIFFSetField(tif
, TIFFTAG_SAMPLEFORMAT
, SAMPLEFORMAT_IEEEFP
);
1254 * Must recalculate sizes should bits/sample change.
1256 tif
->tif_tilesize
= isTiled(tif
) ? TIFFTileSize(tif
) : (tsize_t
) -1;
1257 tif
->tif_scanlinesize
= TIFFScanlineSize(tif
);
1258 result
= 1; /* NB: pseudo tag */
1261 result
= (*sp
->vsetparent
)(tif
, tag
, ap
);
1267 PixarLogVGetField(TIFF
* tif
, ttag_t tag
, va_list ap
)
1269 PixarLogState
*sp
= (PixarLogState
*)tif
->tif_data
;
1272 case TIFFTAG_PIXARLOGQUALITY
:
1273 *va_arg(ap
, int*) = sp
->quality
;
1275 case TIFFTAG_PIXARLOGDATAFMT
:
1276 *va_arg(ap
, int*) = sp
->user_datafmt
;
1279 return (*sp
->vgetparent
)(tif
, tag
, ap
);
1284 static const TIFFFieldInfo pixarlogFieldInfo
[] = {
1285 {TIFFTAG_PIXARLOGDATAFMT
,0,0,TIFF_ANY
, FIELD_PSEUDO
,FALSE
,FALSE
,""},
1286 {TIFFTAG_PIXARLOGQUALITY
,0,0,TIFF_ANY
, FIELD_PSEUDO
,FALSE
,FALSE
,""}
1290 TIFFInitPixarLog(TIFF
* tif
, int scheme
)
1292 static const char module
[] = "TIFFInitPixarLog";
1296 assert(scheme
== COMPRESSION_PIXARLOG
);
1299 * Merge codec-specific tag information.
1301 if (!_TIFFMergeFieldInfo(tif
, pixarlogFieldInfo
,
1302 TIFFArrayCount(pixarlogFieldInfo
))) {
1303 TIFFErrorExt(tif
->tif_clientdata
, module
,
1304 "Merging PixarLog codec-specific tags failed");
1309 * Allocate state block so tag methods have storage to record values.
1311 tif
->tif_data
= (tidata_t
) _TIFFmalloc(sizeof (PixarLogState
));
1312 if (tif
->tif_data
== NULL
)
1314 sp
= (PixarLogState
*) tif
->tif_data
;
1315 _TIFFmemset(sp
, 0, sizeof (*sp
));
1316 sp
->stream
.data_type
= Z_BINARY
;
1317 sp
->user_datafmt
= PIXARLOGDATAFMT_UNKNOWN
;
1320 * Install codec methods.
1322 tif
->tif_setupdecode
= PixarLogSetupDecode
;
1323 tif
->tif_predecode
= PixarLogPreDecode
;
1324 tif
->tif_decoderow
= PixarLogDecode
;
1325 tif
->tif_decodestrip
= PixarLogDecode
;
1326 tif
->tif_decodetile
= PixarLogDecode
;
1327 tif
->tif_setupencode
= PixarLogSetupEncode
;
1328 tif
->tif_preencode
= PixarLogPreEncode
;
1329 tif
->tif_postencode
= PixarLogPostEncode
;
1330 tif
->tif_encoderow
= PixarLogEncode
;
1331 tif
->tif_encodestrip
= PixarLogEncode
;
1332 tif
->tif_encodetile
= PixarLogEncode
;
1333 tif
->tif_close
= PixarLogClose
;
1334 tif
->tif_cleanup
= PixarLogCleanup
;
1336 /* Override SetField so we can handle our private pseudo-tag */
1337 sp
->vgetparent
= tif
->tif_tagmethods
.vgetfield
;
1338 tif
->tif_tagmethods
.vgetfield
= PixarLogVGetField
; /* hook for codec tags */
1339 sp
->vsetparent
= tif
->tif_tagmethods
.vsetfield
;
1340 tif
->tif_tagmethods
.vsetfield
= PixarLogVSetField
; /* hook for codec tags */
1342 /* Default values for codec-specific fields */
1343 sp
->quality
= Z_DEFAULT_COMPRESSION
; /* default comp. level */
1346 /* we don't wish to use the predictor,
1347 * the default is none, which predictor value 1
1349 (void) TIFFPredictorInit(tif
);
1352 * build the companding tables
1354 PixarLogMakeTables(sp
);
1358 TIFFErrorExt(tif
->tif_clientdata
, module
,
1359 "No space for PixarLog state block");
1362 #endif /* PIXARLOG_SUPPORT */
1364 /* vim: set ts=8 sts=8 sw=8 noet: */