2 * Copyright (c) 1997 Greg Ward Larson
3 * Copyright (c) 1997 Silicon Graphics, Inc.
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 * Sam Leffler, Greg Larson and Silicon Graphics may not be used in any
10 * advertising or publicity relating to the software without the specific,
11 * prior written permission of Sam Leffler, Greg Larson 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 SAM LEFFLER, GREG LARSON OR SILICON GRAPHICS BE LIABLE
18 * FOR 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
30 * LogLuv compression support for high dynamic range images.
32 * Contributed by Greg Larson.
34 * LogLuv image support uses the TIFF library to store 16 or 10-bit
35 * log luminance values with 8 bits each of u and v or a 14-bit index.
37 * The codec can take as input and produce as output 32-bit IEEE float values
38 * as well as 16-bit integer values. A 16-bit luminance is interpreted
39 * as a sign bit followed by a 15-bit integer that is converted
40 * to and from a linear magnitude using the transformation:
42 * L = 2^( (Le+.5)/256 - 64 ) # real from 15-bit
44 * Le = floor( 256*(log2(L) + 64) ) # 15-bit from real
46 * The actual conversion to world luminance units in candelas per sq. meter
47 * requires an additional multiplier, which is stored in the TIFFTAG_STONITS.
48 * This value is usually set such that a reasonable exposure comes from
49 * clamping decoded luminances above 1 to 1 in the displayed image.
51 * The 16-bit values for u and v may be converted to real values by dividing
52 * each by 32768. (This allows for negative values, which aren't useful as
53 * far as we know, but are left in case of future improvements in human
56 * Conversion from (u,v), which is actually the CIE (u',v') system for
57 * you color scientists, is accomplished by the following transformation:
59 * u = 4*x / (-2*x + 12*y + 3)
60 * v = 9*y / (-2*x + 12*y + 3)
62 * x = 9*u / (6*u - 16*v + 12)
63 * y = 4*v / (6*u - 16*v + 12)
65 * This process is greatly simplified by passing 32-bit IEEE floats
66 * for each of three CIE XYZ coordinates. The codec then takes care
67 * of conversion to and from LogLuv, though the application is still
68 * responsible for interpreting the TIFFTAG_STONITS calibration factor.
70 * The information is compressed into one of two basic encodings, depending on
71 * the setting of the compression tag, which is one of COMPRESSION_SGILOG
72 * or COMPRESSION_SGILOG24. For COMPRESSION_SGILOG, greyscale data is
78 * COMPRESSION_SGILOG color data is stored as:
81 * |-+---------------|--------+--------|
84 * For the 24-bit COMPRESSION_SGILOG24 color format, the data is stored as:
87 * |----------|--------------|
90 * There is no sign bit in the 24-bit case, and the (u,v) chromaticity is
91 * encoded as an index for optimal color resolution. The 10 log bits are
92 * defined by the following conversions:
94 * L = 2^((Le'+.5)/64 - 12) # real from 10-bit
96 * Le' = floor( 64*(log2(L) + 12) ) # 10-bit from real
98 * The 10 bits of the smaller format may be converted into the 15 bits of
99 * the larger format by multiplying by 4 and adding 13314. Obviously,
100 * a smaller range of magnitudes is covered (about 5 orders of magnitude
101 * instead of 38), and the lack of a sign bit means that negative luminances
102 * are not allowed. (Well, they aren't allowed in the real world, either,
103 * but they are useful for certain types of image processing.)
105 * The desired user format is controlled by the setting the internal
106 * pseudo tag TIFFTAG_SGILOGDATAFMT to one of:
107 * SGILOGDATAFMT_FLOAT = IEEE 32-bit float XYZ values
108 * SGILOGDATAFMT_16BIT = 16-bit integer encodings of logL, u and v
109 * Raw data i/o is also possible using:
110 * SGILOGDATAFMT_RAW = 32-bit unsigned integer with encoded pixel
111 * In addition, the following decoding is provided for ease of display:
112 * SGILOGDATAFMT_8BIT = 8-bit default RGB gamma-corrected values
114 * For grayscale images, we provide the following data formats:
115 * SGILOGDATAFMT_FLOAT = IEEE 32-bit float Y values
116 * SGILOGDATAFMT_16BIT = 16-bit integer w/ encoded luminance
117 * SGILOGDATAFMT_8BIT = 8-bit gray monitor values
119 * Note that the COMPRESSION_SGILOG applies a simple run-length encoding
120 * scheme by separating the logL, u and v bytes for each row and applying
121 * a PackBits type of compression. Since the 24-bit encoding is not
122 * adaptive, the 32-bit color format takes less space in many cases.
131 * State block for each open TIFF
132 * file using LogLuv compression/decompression.
134 typedef struct logLuvState LogLuvState
;
137 int user_datafmt
; /* user data format */
138 int pixel_size
; /* bytes per pixel */
140 tidata_t
* tbuf
; /* translation buffer */
141 short tbuflen
; /* buffer length */
142 void (*tfunc
)(LogLuvState
*, tidata_t
, int);
144 TIFFVSetMethod vgetparent
; /* super-class method */
145 TIFFVSetMethod vsetparent
; /* super-class method */
148 #define DecoderState(tif) ((LogLuvState*) (tif)->tif_data)
149 #define EncoderState(tif) ((LogLuvState*) (tif)->tif_data)
151 #define N(a) (sizeof(a)/sizeof(a[0]))
152 #define SGILOGDATAFMT_UNKNOWN -1
154 #define MINRUN 4 /* minimum run length */
157 * Decode a string of 16-bit gray pixels.
160 LogL16Decode(TIFF
* tif
, tidata_t op
, tsize_t occ
, tsample_t s
)
162 LogLuvState
* sp
= DecoderState(tif
);
163 int shft
, i
, npixels
;
172 npixels
= occ
/ sp
->pixel_size
;
174 if (sp
->user_datafmt
== SGILOGDATAFMT_16BIT
)
177 assert(sp
->tbuflen
>= npixels
);
178 tp
= (int16
*) sp
->tbuf
;
180 _TIFFmemset((tdata_t
) tp
, 0, npixels
*sizeof (tp
[0]));
182 bp
= (u_char
*) tif
->tif_rawcp
;
184 /* get each byte string */
185 for (shft
= 2*8; (shft
-= 8) >= 0; ) {
186 for (i
= 0; i
< npixels
&& cc
> 0; )
187 if (*bp
>= 128) { /* run */
188 rc
= *bp
++ + (2-128);
189 b
= (int16
)*bp
++ << shft
;
193 } else { /* non-run */
194 rc
= *bp
++; /* nul is noop */
196 tp
[i
++] |= (int16
)*bp
++ << shft
;
199 TIFFError(tif
->tif_name
,
200 "LogL16Decode: Not enough data at row %d (short %d pixels)",
201 tif
->tif_row
, npixels
- i
);
202 tif
->tif_rawcp
= (tidata_t
) bp
;
207 (*sp
->tfunc
)(sp
, op
, npixels
);
208 tif
->tif_rawcp
= (tidata_t
) bp
;
214 * Decode a string of 24-bit pixels.
217 LogLuvDecode24(TIFF
* tif
, tidata_t op
, tsize_t occ
, tsample_t s
)
219 LogLuvState
* sp
= DecoderState(tif
);
227 npixels
= occ
/ sp
->pixel_size
;
229 if (sp
->user_datafmt
== SGILOGDATAFMT_RAW
)
232 assert(sp
->tbuflen
>= npixels
);
233 tp
= (uint32
*) sp
->tbuf
;
235 _TIFFmemset((tdata_t
) tp
, 0, npixels
*sizeof (tp
[0]));
236 /* copy to array of uint32 */
237 bp
= (u_char
*) tif
->tif_rawcp
;
239 for (i
= 0; i
< npixels
&& cc
> 0; i
++) {
240 tp
[i
] = bp
[0] << 16 | bp
[1] << 8 | bp
[2];
244 tif
->tif_rawcp
= (tidata_t
) bp
;
247 TIFFError(tif
->tif_name
,
248 "LogLuvDecode24: Not enough data at row %d (short %d pixels)",
249 tif
->tif_row
, npixels
- i
);
252 (*sp
->tfunc
)(sp
, op
, npixels
);
257 * Decode a string of 32-bit pixels.
260 LogLuvDecode32(TIFF
* tif
, tidata_t op
, tsize_t occ
, tsample_t s
)
263 int shft
, i
, npixels
;
270 sp
= DecoderState(tif
);
273 npixels
= occ
/ sp
->pixel_size
;
275 if (sp
->user_datafmt
== SGILOGDATAFMT_RAW
)
278 assert(sp
->tbuflen
>= npixels
);
279 tp
= (uint32
*) sp
->tbuf
;
281 _TIFFmemset((tdata_t
) tp
, 0, npixels
*sizeof (tp
[0]));
283 bp
= (u_char
*) tif
->tif_rawcp
;
285 /* get each byte string */
286 for (shft
= 4*8; (shft
-= 8) >= 0; ) {
287 for (i
= 0; i
< npixels
&& cc
> 0; )
288 if (*bp
>= 128) { /* run */
289 rc
= *bp
++ + (2-128);
290 b
= (uint32
)*bp
++ << shft
;
294 } else { /* non-run */
295 rc
= *bp
++; /* nul is noop */
297 tp
[i
++] |= (uint32
)*bp
++ << shft
;
300 TIFFError(tif
->tif_name
,
301 "LogLuvDecode32: Not enough data at row %d (short %d pixels)",
302 tif
->tif_row
, npixels
- i
);
303 tif
->tif_rawcp
= (tidata_t
) bp
;
308 (*sp
->tfunc
)(sp
, op
, npixels
);
309 tif
->tif_rawcp
= (tidata_t
) bp
;
315 * Decode a strip of pixels. We break it into rows to
316 * maintain synchrony with the encode algorithm, which
320 LogLuvDecodeStrip(TIFF
* tif
, tidata_t bp
, tsize_t cc
, tsample_t s
)
322 tsize_t rowlen
= TIFFScanlineSize(tif
);
324 assert(cc%rowlen
== 0);
325 while (cc
&& (*tif
->tif_decoderow
)(tif
, bp
, rowlen
, s
))
326 bp
+= rowlen
, cc
-= rowlen
;
331 * Decode a tile of pixels. We break it into rows to
332 * maintain synchrony with the encode algorithm, which
336 LogLuvDecodeTile(TIFF
* tif
, tidata_t bp
, tsize_t cc
, tsample_t s
)
338 tsize_t rowlen
= TIFFTileRowSize(tif
);
340 assert(cc%rowlen
== 0);
341 while (cc
&& (*tif
->tif_decoderow
)(tif
, bp
, rowlen
, s
))
342 bp
+= rowlen
, cc
-= rowlen
;
347 * Encode a row of 16-bit pixels.
350 LogL16Encode(TIFF
* tif
, tidata_t bp
, tsize_t cc
, tsample_t s
)
352 LogLuvState
* sp
= EncoderState(tif
);
353 int shft
, i
, j
, npixels
;
357 int occ
, rc
=0, mask
, beg
;
361 npixels
= cc
/ sp
->pixel_size
;
363 if (sp
->user_datafmt
== SGILOGDATAFMT_16BIT
)
366 tp
= (int16
*) sp
->tbuf
;
367 assert(sp
->tbuflen
>= npixels
);
368 (*sp
->tfunc
)(sp
, bp
, npixels
);
370 /* compress each byte string */
372 occ
= tif
->tif_rawdatasize
- tif
->tif_rawcc
;
373 for (shft
= 2*8; (shft
-= 8) >= 0; )
374 for (i
= 0; i
< npixels
; i
+= rc
) {
377 tif
->tif_rawcc
= tif
->tif_rawdatasize
- occ
;
378 if (!TIFFFlushData1(tif
))
381 occ
= tif
->tif_rawdatasize
- tif
->tif_rawcc
;
383 mask
= 0xff << shft
; /* find next run */
384 for (beg
= i
; beg
< npixels
; beg
+= rc
) {
387 while (rc
< 127+2 && beg
+rc
< npixels
&&
388 (tp
[beg
+rc
] & mask
) == b
)
391 break; /* long enough */
393 if (beg
-i
> 1 && beg
-i
< MINRUN
) {
394 b
= tp
[i
] & mask
; /* check short run */
396 while ((tp
[j
++] & mask
) == b
)
405 while (i
< beg
) { /* write out non-run */
406 if ((j
= beg
-i
) > 127) j
= 127;
409 tif
->tif_rawcc
= tif
->tif_rawdatasize
- occ
;
410 if (!TIFFFlushData1(tif
))
413 occ
= tif
->tif_rawdatasize
- tif
->tif_rawcc
;
417 *op
++ = tp
[i
++] >> shft
& 0xff;
421 if (rc
>= MINRUN
) { /* write out run */
423 *op
++ = tp
[beg
] >> shft
& 0xff;
429 tif
->tif_rawcc
= tif
->tif_rawdatasize
- occ
;
435 * Encode a row of 24-bit pixels.
438 LogLuvEncode24(TIFF
* tif
, tidata_t bp
, tsize_t cc
, tsample_t s
)
440 LogLuvState
* sp
= EncoderState(tif
);
447 npixels
= cc
/ sp
->pixel_size
;
449 if (sp
->user_datafmt
== SGILOGDATAFMT_RAW
)
452 tp
= (uint32
*) sp
->tbuf
;
453 assert(sp
->tbuflen
>= npixels
);
454 (*sp
->tfunc
)(sp
, bp
, npixels
);
456 /* write out encoded pixels */
458 occ
= tif
->tif_rawdatasize
- tif
->tif_rawcc
;
459 for (i
= npixels
; i
--; ) {
462 tif
->tif_rawcc
= tif
->tif_rawdatasize
- occ
;
463 if (!TIFFFlushData1(tif
))
466 occ
= tif
->tif_rawdatasize
- tif
->tif_rawcc
;
469 *op
++ = *tp
>> 8 & 0xff;
470 *op
++ = *tp
++ & 0xff;
474 tif
->tif_rawcc
= tif
->tif_rawdatasize
- occ
;
480 * Encode a row of 32-bit pixels.
483 LogLuvEncode32(TIFF
* tif
, tidata_t bp
, tsize_t cc
, tsample_t s
)
485 LogLuvState
* sp
= EncoderState(tif
);
486 int shft
, i
, j
, npixels
;
490 int occ
, rc
=0, mask
, beg
;
495 npixels
= cc
/ sp
->pixel_size
;
497 if (sp
->user_datafmt
== SGILOGDATAFMT_RAW
)
500 tp
= (uint32
*) sp
->tbuf
;
501 assert(sp
->tbuflen
>= npixels
);
502 (*sp
->tfunc
)(sp
, bp
, npixels
);
504 /* compress each byte string */
506 occ
= tif
->tif_rawdatasize
- tif
->tif_rawcc
;
507 for (shft
= 4*8; (shft
-= 8) >= 0; )
508 for (i
= 0; i
< npixels
; i
+= rc
) {
511 tif
->tif_rawcc
= tif
->tif_rawdatasize
- occ
;
512 if (!TIFFFlushData1(tif
))
515 occ
= tif
->tif_rawdatasize
- tif
->tif_rawcc
;
517 mask
= 0xff << shft
; /* find next run */
518 for (beg
= i
; beg
< npixels
; beg
+= rc
) {
521 while (rc
< 127+2 && beg
+rc
< npixels
&&
522 (tp
[beg
+rc
] & mask
) == b
)
525 break; /* long enough */
527 if (beg
-i
> 1 && beg
-i
< MINRUN
) {
528 b
= tp
[i
] & mask
; /* check short run */
530 while ((tp
[j
++] & mask
) == b
)
539 while (i
< beg
) { /* write out non-run */
540 if ((j
= beg
-i
) > 127) j
= 127;
543 tif
->tif_rawcc
= tif
->tif_rawdatasize
- occ
;
544 if (!TIFFFlushData1(tif
))
547 occ
= tif
->tif_rawdatasize
- tif
->tif_rawcc
;
551 *op
++ = tp
[i
++] >> shft
& 0xff;
555 if (rc
>= MINRUN
) { /* write out run */
557 *op
++ = tp
[beg
] >> shft
& 0xff;
563 tif
->tif_rawcc
= tif
->tif_rawdatasize
- occ
;
569 * Encode a strip of pixels. We break it into rows to
570 * avoid encoding runs across row boundaries.
573 LogLuvEncodeStrip(TIFF
* tif
, tidata_t bp
, tsize_t cc
, tsample_t s
)
575 tsize_t rowlen
= TIFFScanlineSize(tif
);
577 assert(cc%rowlen
== 0);
578 while (cc
&& (*tif
->tif_encoderow
)(tif
, bp
, rowlen
, s
) == 0)
579 bp
+= rowlen
, cc
-= rowlen
;
584 * Encode a tile of pixels. We break it into rows to
585 * avoid encoding runs across row boundaries.
588 LogLuvEncodeTile(TIFF
* tif
, tidata_t bp
, tsize_t cc
, tsample_t s
)
590 tsize_t rowlen
= TIFFTileRowSize(tif
);
592 assert(cc%rowlen
== 0);
593 while (cc
&& (*tif
->tif_encoderow
)(tif
, bp
, rowlen
, s
) == 0)
594 bp
+= rowlen
, cc
-= rowlen
;
599 * Encode/Decode functions for converting to and from user formats.
603 #define U_NEU 0.210526316
604 #define V_NEU 0.473684211
609 #define LOGOF2 0.69314718055994530942
611 #define log2(x) ((1./LOGOF2)*log(x))
612 #define exp2(x) exp(LOGOF2*(x))
619 int Le
= p16
& 0x7fff;
624 Y
= exp(LOGOF2
/256.*(Le
+.5) - LOGOF2
*64.);
635 if (Y
<= -1.84467e19
)
638 return (int)(256.*(log2(Y
) + 64.));
639 if (Y
< -5.43571e-20)
640 return (~0x7fff | (int)(256.*(log2(-Y
) + 64.)));
645 L16toY(LogLuvState
* sp
, tidata_t op
, int n
)
647 int16
* l16
= (int16
*) sp
->tbuf
;
648 float* yp
= (float*) op
;
651 *yp
++ = pix16toY(*l16
++);
655 L16toGry(LogLuvState
* sp
, tidata_t op
, int n
)
657 int16
* l16
= (int16
*) sp
->tbuf
;
658 uint8
* gp
= (uint8
*) op
;
661 double Y
= pix16toY(*l16
++);
662 *gp
++ = (Y
<= 0.) ? 0 : (Y
>= 1.) ? 255 : (int)(256.*sqrt(Y
));
667 L16fromY(LogLuvState
* sp
, tidata_t op
, int n
)
669 int16
* l16
= (int16
*) sp
->tbuf
;
670 float* yp
= (float*) op
;
673 *l16
++ = pix16fromY(*yp
++);
677 XYZtoRGB24(float xyz
[3], uint8 rgb
[3])
680 /* assume CCIR-709 primaries */
681 r
= 2.690*xyz
[0] + -1.276*xyz
[1] + -0.414*xyz
[2];
682 g
= -1.022*xyz
[0] + 1.978*xyz
[1] + 0.044*xyz
[2];
683 b
= 0.061*xyz
[0] + -0.224*xyz
[1] + 1.163*xyz
[2];
684 /* assume 2.0 gamma for speed */
685 /* could use integer sqrt approx., but this is probably faster */
686 rgb
[0] = (r
<= 0.) ? 0 : (r
>= 1.) ? 255 : (int)(256.*sqrt(r
));
687 rgb
[1] = (g
<= 0.) ? 0 : (g
>= 1.) ? 255 : (int)(256.*sqrt(g
));
688 rgb
[2] = (b
<= 0.) ? 0 : (b
>= 1.) ? 255 : (int)(256.*sqrt(b
));
692 uv_encode(double u
, double v
) /* encode (u',v') coordinates */
698 vi
= (v
- UV_VSTART
)*(1./UV_SQSIZ
);
701 if (u
< uv_row
[vi
].ustart
)
703 ui
= (u
- uv_row
[vi
].ustart
)*(1./UV_SQSIZ
);
704 if (ui
>= uv_row
[vi
].nus
)
706 return(uv_row
[vi
].ncum
+ ui
);
710 uv_decode(double *up
, double *vp
, int c
) /* decode (u',v') index */
715 if (c
< 0 || c
>= UV_NDIVS
)
717 lower
= 0; /* binary search */
720 vi
= (lower
+ upper
) >> 1;
721 ui
= c
- uv_row
[vi
].ncum
;
728 } while (upper
- lower
> 1);
730 ui
= c
- uv_row
[vi
].ncum
;
731 *up
= uv_row
[vi
].ustart
+ (ui
+.5)*UV_SQSIZ
;
732 *vp
= UV_VSTART
+ (vi
+.5)*UV_SQSIZ
;
737 pix24toXYZ(uint32 p
, float XYZ
[3])
740 double L
, u
, v
, s
, x
, y
;
741 /* decode luminance */
742 Le
= p
>> 14 & 0x3ff;
744 XYZ
[0] = XYZ
[1] = XYZ
[2] = 0.;
747 L
= exp(LOGOF2
/64.*(Le
+.5) - LOGOF2
*12.);
750 if (uv_decode(&u
, &v
, Ce
) < 0) {
751 u
= U_NEU
; v
= V_NEU
;
753 s
= 1./(6.*u
- 16.*v
+ 12.);
759 XYZ
[2] = (1.-x
-y
)/y
* L
;
763 pix24fromXYZ(float XYZ
[3])
767 /* encode luminance */
771 else if (L
<= 1./4096.)
774 Le
= 64.*(log2(L
) + 12.);
776 s
= XYZ
[0] + 15.*XYZ
[1] + 3.*XYZ
[2];
784 Ce
= uv_encode(u
, v
);
786 Ce
= uv_encode(U_NEU
, V_NEU
);
787 /* combine encodings */
788 return (Le
<< 14 | Ce
);
792 Luv24toXYZ(LogLuvState
* sp
, tidata_t op
, int n
)
794 uint32
* luv
= (uint32
*) sp
->tbuf
;
795 float* xyz
= (float*) op
;
798 pix24toXYZ(*luv
, xyz
);
805 Luv24toLuv48(LogLuvState
* sp
, tidata_t op
, int n
)
807 uint32
* luv
= (uint32
*) sp
->tbuf
;
808 int16
* luv3
= (int16
*) op
;
813 *luv3
++ = (*luv
>> 12 & 0xffd) + 13314;
814 if (uv_decode(&u
, &v
, *luv
&0x3fff) < 0) {
818 *luv3
++ = u
* (1L<<15);
819 *luv3
++ = v
* (1L<<15);
825 Luv24toRGB(LogLuvState
* sp
, tidata_t op
, int n
)
827 uint32
* luv
= (uint32
*) sp
->tbuf
;
828 uint8
* rgb
= (uint8
*) op
;
833 pix24toXYZ(*luv
++, xyz
);
834 XYZtoRGB24(xyz
, rgb
);
840 Luv24fromXYZ(LogLuvState
* sp
, tidata_t op
, int n
)
842 uint32
* luv
= (uint32
*) sp
->tbuf
;
843 float* xyz
= (float*) op
;
846 *luv
++ = pix24fromXYZ(xyz
);
852 Luv24fromLuv48(LogLuvState
* sp
, tidata_t op
, int n
)
854 uint32
* luv
= (uint32
*) sp
->tbuf
;
855 int16
* luv3
= (int16
*) op
;
862 else if (luv3
[0] >= (1<<12)+3314)
865 Le
= (luv3
[0]-3314) >> 2;
866 Ce
= uv_encode((luv
[1]+.5)/(1<<15), (luv
[2]+.5)/(1<<15));
868 Ce
= uv_encode(U_NEU
, V_NEU
);
869 *luv
++ = (uint32
)Le
<< 14 | Ce
;
875 pix32toXYZ(uint32 p
, float XYZ
[3])
877 double L
, u
, v
, s
, x
, y
;
878 /* decode luminance */
879 L
= pix16toY((int)p
>> 16);
881 XYZ
[0] = XYZ
[1] = XYZ
[2] = 0.;
885 u
= 1./UVSCALE
* ((p
>>8 & 0xff) + .5);
886 v
= 1./UVSCALE
* ((p
& 0xff) + .5);
887 s
= 1./(6.*u
- 16.*v
+ 12.);
893 XYZ
[2] = (1.-x
-y
)/y
* L
;
897 pix32fromXYZ(float XYZ
[3])
899 unsigned int Le
, ue
, ve
;
901 /* encode luminance */
902 Le
= (unsigned int)pix16fromY(XYZ
[1]);
904 s
= XYZ
[0] + 15.*XYZ
[1] + 3.*XYZ
[2];
913 else ue
= UVSCALE
* u
;
914 if (ue
> 255) ue
= 255;
916 else ve
= UVSCALE
* v
;
917 if (ve
> 255) ve
= 255;
918 /* combine encodings */
919 return (Le
<< 16 | ue
<< 8 | ve
);
923 Luv32toXYZ(LogLuvState
* sp
, tidata_t op
, int n
)
925 uint32
* luv
= (uint32
*) sp
->tbuf
;
926 float* xyz
= (float*) op
;
929 pix32toXYZ(*luv
++, xyz
);
935 Luv32toLuv48(LogLuvState
* sp
, tidata_t op
, int n
)
937 uint32
* luv
= (uint32
*) sp
->tbuf
;
938 int16
* luv3
= (int16
*) op
;
943 *luv3
++ = *luv
>> 16;
944 u
= 1./UVSCALE
* ((*luv
>>8 & 0xff) + .5);
945 v
= 1./UVSCALE
* ((*luv
& 0xff) + .5);
946 *luv3
++ = u
* (1L<<15);
947 *luv3
++ = v
* (1L<<15);
953 Luv32toRGB(LogLuvState
* sp
, tidata_t op
, int n
)
955 uint32
* luv
= (uint32
*) sp
->tbuf
;
956 uint8
* rgb
= (uint8
*) op
;
961 pix32toXYZ(*luv
++, xyz
);
962 XYZtoRGB24(xyz
, rgb
);
968 Luv32fromXYZ(LogLuvState
* sp
, tidata_t op
, int n
)
970 uint32
* luv
= (uint32
*) sp
->tbuf
;
971 float* xyz
= (float*) op
;
974 *luv
++ = pix32fromXYZ(xyz
);
980 Luv32fromLuv48(LogLuvState
* sp
, tidata_t op
, int n
)
982 uint32
* luv
= (uint32
*) sp
->tbuf
;
983 int16
* luv3
= (int16
*) op
;
986 *luv
++ = (uint32
)luv3
[0] << 16 |
987 (luv3
[1]*(uint32
)(UVSCALE
+.5) >> 7 & 0xff00) |
988 (luv3
[2]*(uint32
)(UVSCALE
+.5) >> 15 & 0xff);
994 _logLuvNop(LogLuvState
* sp
, tidata_t op
, int n
)
996 (void) sp
; (void) op
; (void) n
;
1000 LogL16GuessDataFmt(TIFFDirectory
*td
)
1002 #define PACK(s,b,f) (((b)<<6)|((s)<<3)|(f))
1003 switch (PACK(td
->td_samplesperpixel
, td
->td_bitspersample
, td
->td_sampleformat
)) {
1004 case PACK(1, 32, SAMPLEFORMAT_IEEEFP
):
1005 return (SGILOGDATAFMT_FLOAT
);
1006 case PACK(1, 16, SAMPLEFORMAT_VOID
):
1007 case PACK(1, 16, SAMPLEFORMAT_INT
):
1008 case PACK(1, 16, SAMPLEFORMAT_UINT
):
1009 return (SGILOGDATAFMT_16BIT
);
1010 case PACK(1, 8, SAMPLEFORMAT_VOID
):
1011 case PACK(1, 8, SAMPLEFORMAT_UINT
):
1012 return (SGILOGDATAFMT_8BIT
);
1015 return (SGILOGDATAFMT_UNKNOWN
);
1019 LogL16InitState(TIFF
* tif
)
1021 TIFFDirectory
*td
= &tif
->tif_dir
;
1022 LogLuvState
* sp
= DecoderState(tif
);
1023 static const char module[] = "LogL16InitState";
1026 assert(td
->td_photometric
== PHOTOMETRIC_LOGL
);
1028 /* for some reason, we can't do this in TIFFInitLogL16 */
1029 if (sp
->user_datafmt
== SGILOGDATAFMT_UNKNOWN
)
1030 sp
->user_datafmt
= LogL16GuessDataFmt(td
);
1031 switch (sp
->user_datafmt
) {
1032 case SGILOGDATAFMT_FLOAT
:
1033 sp
->pixel_size
= sizeof (float);
1035 case SGILOGDATAFMT_16BIT
:
1036 sp
->pixel_size
= sizeof (int16
);
1038 case SGILOGDATAFMT_8BIT
:
1039 sp
->pixel_size
= sizeof (uint8
);
1042 TIFFError(tif
->tif_name
,
1043 "No support for converting user data format to LogL");
1046 sp
->tbuflen
= td
->td_imagewidth
* td
->td_rowsperstrip
;
1047 sp
->tbuf
= (tidata_t
*) _TIFFmalloc(sp
->tbuflen
* sizeof (int16
));
1048 if (sp
->tbuf
== NULL
) {
1049 TIFFError(module, "%s: No space for SGILog translation buffer",
1057 LogLuvGuessDataFmt(TIFFDirectory
*td
)
1062 * If the user didn't tell us their datafmt,
1063 * take our best guess from the bitspersample.
1065 #define PACK(a,b) (((a)<<3)|(b))
1066 switch (PACK(td
->td_bitspersample
, td
->td_sampleformat
)) {
1067 case PACK(32, SAMPLEFORMAT_IEEEFP
):
1068 guess
= SGILOGDATAFMT_FLOAT
;
1070 case PACK(32, SAMPLEFORMAT_VOID
):
1071 case PACK(32, SAMPLEFORMAT_UINT
):
1072 case PACK(32, SAMPLEFORMAT_INT
):
1073 guess
= SGILOGDATAFMT_RAW
;
1075 case PACK(16, SAMPLEFORMAT_VOID
):
1076 case PACK(16, SAMPLEFORMAT_INT
):
1077 case PACK(16, SAMPLEFORMAT_UINT
):
1078 guess
= SGILOGDATAFMT_16BIT
;
1080 case PACK( 8, SAMPLEFORMAT_VOID
):
1081 case PACK( 8, SAMPLEFORMAT_UINT
):
1082 guess
= SGILOGDATAFMT_8BIT
;
1085 guess
= SGILOGDATAFMT_UNKNOWN
;
1090 * Double-check samples per pixel.
1092 switch (td
->td_samplesperpixel
) {
1094 if (guess
!= SGILOGDATAFMT_RAW
)
1095 guess
= SGILOGDATAFMT_UNKNOWN
;
1098 if (guess
== SGILOGDATAFMT_RAW
)
1099 guess
= SGILOGDATAFMT_UNKNOWN
;
1102 guess
= SGILOGDATAFMT_UNKNOWN
;
1109 LogLuvInitState(TIFF
* tif
)
1111 TIFFDirectory
* td
= &tif
->tif_dir
;
1112 LogLuvState
* sp
= DecoderState(tif
);
1113 static const char module[] = "LogLuvInitState";
1116 assert(td
->td_photometric
== PHOTOMETRIC_LOGLUV
);
1118 /* for some reason, we can't do this in TIFFInitLogLuv */
1119 if (td
->td_planarconfig
!= PLANARCONFIG_CONTIG
) {
1121 "SGILog compression cannot handle non-contiguous data");
1124 if (sp
->user_datafmt
== SGILOGDATAFMT_UNKNOWN
)
1125 sp
->user_datafmt
= LogLuvGuessDataFmt(td
);
1126 switch (sp
->user_datafmt
) {
1127 case SGILOGDATAFMT_FLOAT
:
1128 sp
->pixel_size
= 3*sizeof (float);
1130 case SGILOGDATAFMT_16BIT
:
1131 sp
->pixel_size
= 3*sizeof (int16
);
1133 case SGILOGDATAFMT_RAW
:
1134 sp
->pixel_size
= sizeof (uint32
);
1136 case SGILOGDATAFMT_8BIT
:
1137 sp
->pixel_size
= 3*sizeof (uint8
);
1140 TIFFError(tif
->tif_name
,
1141 "No support for converting user data format to LogLuv");
1144 sp
->tbuflen
= td
->td_imagewidth
* td
->td_rowsperstrip
;
1145 sp
->tbuf
= (tidata_t
*) _TIFFmalloc(sp
->tbuflen
* sizeof (uint32
));
1146 if (sp
->tbuf
== NULL
) {
1147 TIFFError(module, "%s: No space for SGILog translation buffer",
1155 LogLuvSetupDecode(TIFF
* tif
)
1157 LogLuvState
* sp
= DecoderState(tif
);
1158 TIFFDirectory
* td
= &tif
->tif_dir
;
1160 tif
->tif_postdecode
= _TIFFNoPostDecode
;
1161 switch (td
->td_photometric
) {
1162 case PHOTOMETRIC_LOGLUV
:
1163 if (!LogLuvInitState(tif
))
1165 if (td
->td_compression
== COMPRESSION_SGILOG24
) {
1166 tif
->tif_decoderow
= LogLuvDecode24
;
1167 switch (sp
->user_datafmt
) {
1168 case SGILOGDATAFMT_FLOAT
:
1169 sp
->tfunc
= Luv24toXYZ
;
1171 case SGILOGDATAFMT_16BIT
:
1172 sp
->tfunc
= Luv24toLuv48
;
1174 case SGILOGDATAFMT_8BIT
:
1175 sp
->tfunc
= Luv24toRGB
;
1179 tif
->tif_decoderow
= LogLuvDecode32
;
1180 switch (sp
->user_datafmt
) {
1181 case SGILOGDATAFMT_FLOAT
:
1182 sp
->tfunc
= Luv32toXYZ
;
1184 case SGILOGDATAFMT_16BIT
:
1185 sp
->tfunc
= Luv32toLuv48
;
1187 case SGILOGDATAFMT_8BIT
:
1188 sp
->tfunc
= Luv32toRGB
;
1193 case PHOTOMETRIC_LOGL
:
1194 if (!LogL16InitState(tif
))
1196 tif
->tif_decoderow
= LogL16Decode
;
1197 switch (sp
->user_datafmt
) {
1198 case SGILOGDATAFMT_FLOAT
:
1201 case SGILOGDATAFMT_8BIT
:
1202 sp
->tfunc
= L16toGry
;
1207 TIFFError(tif
->tif_name
,
1208 "Inappropriate photometric interpretation %d for SGILog compression; %s",
1209 td
->td_photometric
, "must be either LogLUV or LogL");
1216 LogLuvSetupEncode(TIFF
* tif
)
1218 LogLuvState
* sp
= EncoderState(tif
);
1219 TIFFDirectory
* td
= &tif
->tif_dir
;
1221 switch (td
->td_photometric
) {
1222 case PHOTOMETRIC_LOGLUV
:
1223 if (!LogLuvInitState(tif
))
1225 if (td
->td_compression
== COMPRESSION_SGILOG24
) {
1226 tif
->tif_encoderow
= LogLuvEncode24
;
1227 switch (sp
->user_datafmt
) {
1228 case SGILOGDATAFMT_FLOAT
:
1229 sp
->tfunc
= Luv24fromXYZ
;
1231 case SGILOGDATAFMT_16BIT
:
1232 sp
->tfunc
= Luv24fromLuv48
;
1234 case SGILOGDATAFMT_RAW
:
1240 tif
->tif_encoderow
= LogLuvEncode32
;
1241 switch (sp
->user_datafmt
) {
1242 case SGILOGDATAFMT_FLOAT
:
1243 sp
->tfunc
= Luv32fromXYZ
;
1245 case SGILOGDATAFMT_16BIT
:
1246 sp
->tfunc
= Luv32fromLuv48
;
1248 case SGILOGDATAFMT_RAW
:
1255 case PHOTOMETRIC_LOGL
:
1256 if (!LogL16InitState(tif
))
1258 tif
->tif_encoderow
= LogL16Encode
;
1259 switch (sp
->user_datafmt
) {
1260 case SGILOGDATAFMT_FLOAT
:
1261 sp
->tfunc
= L16fromY
;
1263 case SGILOGDATAFMT_16BIT
:
1270 TIFFError(tif
->tif_name
,
1271 "Inappropriate photometric interpretation %d for SGILog compression; %s",
1272 td
->td_photometric
, "must be either LogLUV or LogL");
1277 TIFFError(tif
->tif_name
,
1278 "SGILog compression supported only for %s, or raw data",
1279 td
->td_photometric
== PHOTOMETRIC_LOGL
? "Y, L" : "XYZ, Luv");
1284 LogLuvClose(TIFF
* tif
)
1286 TIFFDirectory
*td
= &tif
->tif_dir
;
1289 * For consistency, we always want to write out the same
1290 * bitspersample and sampleformat for our TIFF file,
1291 * regardless of the data format being used by the application.
1292 * Since this routine is called after tags have been set but
1293 * before they have been recorded in the file, we reset them here.
1295 td
->td_samplesperpixel
=
1296 (td
->td_photometric
== PHOTOMETRIC_LOGL
) ? 1 : 3;
1297 td
->td_bitspersample
= 16;
1298 td
->td_sampleformat
= SAMPLEFORMAT_INT
;
1302 LogLuvCleanup(TIFF
* tif
)
1304 LogLuvState
* sp
= (LogLuvState
*)tif
->tif_data
;
1308 _TIFFfree(sp
->tbuf
);
1310 tif
->tif_data
= NULL
;
1315 LogLuvVSetField(TIFF
* tif
, ttag_t tag
, va_list ap
)
1317 LogLuvState
* sp
= DecoderState(tif
);
1321 case TIFFTAG_SGILOGDATAFMT
:
1322 sp
->user_datafmt
= va_arg(ap
, int);
1324 * Tweak the TIFF header so that the rest of libtiff knows what
1325 * size of data will be passed between app and library, and
1326 * assume that the app knows what it is doing and is not
1327 * confused by these header manipulations...
1329 switch (sp
->user_datafmt
) {
1330 case SGILOGDATAFMT_FLOAT
:
1331 bps
= 32, fmt
= SAMPLEFORMAT_IEEEFP
;
1333 case SGILOGDATAFMT_16BIT
:
1334 bps
= 16, fmt
= SAMPLEFORMAT_INT
;
1336 case SGILOGDATAFMT_RAW
:
1337 bps
= 32, fmt
= SAMPLEFORMAT_UINT
;
1339 case SGILOGDATAFMT_8BIT
:
1340 bps
= 8, fmt
= SAMPLEFORMAT_UINT
;
1343 TIFFError(tif
->tif_name
,
1344 "Unknown data format %d for LogLuv compression",
1348 TIFFSetField(tif
, TIFFTAG_BITSPERSAMPLE
, bps
);
1349 TIFFSetField(tif
, TIFFTAG_SAMPLEFORMAT
, fmt
);
1351 * Must recalculate sizes should bits/sample change.
1353 tif
->tif_tilesize
= TIFFTileSize(tif
);
1354 tif
->tif_scanlinesize
= TIFFScanlineSize(tif
);
1357 return (*sp
->vsetparent
)(tif
, tag
, ap
);
1362 LogLuvVGetField(TIFF
* tif
, ttag_t tag
, va_list ap
)
1364 LogLuvState
*sp
= (LogLuvState
*)tif
->tif_data
;
1367 case TIFFTAG_SGILOGDATAFMT
:
1368 *va_arg(ap
, int*) = sp
->user_datafmt
;
1371 return (*sp
->vgetparent
)(tif
, tag
, ap
);
1375 static const TIFFFieldInfo LogLuvFieldInfo
[] = {
1376 { TIFFTAG_SGILOGDATAFMT
, 0, 0, TIFF_SHORT
, FIELD_PSEUDO
,
1377 TRUE
, FALSE
, "SGILogDataFmt"}
1381 TIFFInitSGILog(TIFF
* tif
, int scheme
)
1383 static const char module[] = "TIFFInitSGILog";
1386 assert(scheme
== COMPRESSION_SGILOG24
|| scheme
== COMPRESSION_SGILOG
);
1389 * Allocate state block so tag methods have storage to record values.
1391 tif
->tif_data
= (tidata_t
) _TIFFmalloc(sizeof (LogLuvState
));
1392 if (tif
->tif_data
== NULL
)
1394 sp
= (LogLuvState
*) tif
->tif_data
;
1395 memset(sp
, 0, sizeof (*sp
));
1396 sp
->user_datafmt
= SGILOGDATAFMT_UNKNOWN
;
1397 sp
->tfunc
= _logLuvNop
;
1400 * Install codec methods.
1401 * NB: tif_decoderow & tif_encoderow are filled
1404 tif
->tif_setupdecode
= LogLuvSetupDecode
;
1405 tif
->tif_decodestrip
= LogLuvDecodeStrip
;
1406 tif
->tif_decodetile
= LogLuvDecodeTile
;
1407 tif
->tif_setupencode
= LogLuvSetupEncode
;
1408 tif
->tif_encodestrip
= LogLuvEncodeStrip
;
1409 tif
->tif_encodetile
= LogLuvEncodeTile
;
1410 tif
->tif_close
= LogLuvClose
;
1411 tif
->tif_cleanup
= LogLuvCleanup
;
1413 /* override SetField so we can handle our private pseudo-tag */
1414 _TIFFMergeFieldInfo(tif
, LogLuvFieldInfo
, N(LogLuvFieldInfo
));
1415 sp
->vgetparent
= tif
->tif_vgetfield
;
1416 tif
->tif_vgetfield
= LogLuvVGetField
; /* hook for codec tags */
1417 sp
->vsetparent
= tif
->tif_vsetfield
;
1418 tif
->tif_vsetfield
= LogLuvVSetField
; /* hook for codec tags */
1422 TIFFError(module, "%s: No space for LogLuv state block", tif
->tif_name
);
1425 #endif /* LOGLUV_SUPPORT */