• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* $Id: tif_luv.c,v 1.40 2015-06-21 01:09:09 bfriesen Exp $ */
2 
3 /*
4  * Copyright (c) 1997 Greg Ward Larson
5  * Copyright (c) 1997 Silicon Graphics, Inc.
6  *
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  * Sam Leffler, Greg Larson and Silicon Graphics may not be used in any
12  * advertising or publicity relating to the software without the specific,
13  * prior written permission of Sam Leffler, Greg Larson and Silicon Graphics.
14  *
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.
18  *
19  * IN NO EVENT SHALL SAM LEFFLER, GREG LARSON OR SILICON GRAPHICS BE LIABLE
20  * FOR 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
24  * OF THIS SOFTWARE.
25  */
26 
27 #include "tiffiop.h"
28 #ifdef LOGLUV_SUPPORT
29 
30 /*
31  * TIFF Library.
32  * LogLuv compression support for high dynamic range images.
33  *
34  * Contributed by Greg Larson.
35  *
36  * LogLuv image support uses the TIFF library to store 16 or 10-bit
37  * log luminance values with 8 bits each of u and v or a 14-bit index.
38  *
39  * The codec can take as input and produce as output 32-bit IEEE float values
40  * as well as 16-bit integer values.  A 16-bit luminance is interpreted
41  * as a sign bit followed by a 15-bit integer that is converted
42  * to and from a linear magnitude using the transformation:
43  *
44  *	L = 2^( (Le+.5)/256 - 64 )		# real from 15-bit
45  *
46  *	Le = floor( 256*(log2(L) + 64) )	# 15-bit from real
47  *
48  * The actual conversion to world luminance units in candelas per sq. meter
49  * requires an additional multiplier, which is stored in the TIFFTAG_STONITS.
50  * This value is usually set such that a reasonable exposure comes from
51  * clamping decoded luminances above 1 to 1 in the displayed image.
52  *
53  * The 16-bit values for u and v may be converted to real values by dividing
54  * each by 32768.  (This allows for negative values, which aren't useful as
55  * far as we know, but are left in case of future improvements in human
56  * color vision.)
57  *
58  * Conversion from (u,v), which is actually the CIE (u',v') system for
59  * you color scientists, is accomplished by the following transformation:
60  *
61  *	u = 4*x / (-2*x + 12*y + 3)
62  *	v = 9*y / (-2*x + 12*y + 3)
63  *
64  *	x = 9*u / (6*u - 16*v + 12)
65  *	y = 4*v / (6*u - 16*v + 12)
66  *
67  * This process is greatly simplified by passing 32-bit IEEE floats
68  * for each of three CIE XYZ coordinates.  The codec then takes care
69  * of conversion to and from LogLuv, though the application is still
70  * responsible for interpreting the TIFFTAG_STONITS calibration factor.
71  *
72  * By definition, a CIE XYZ vector of [1 1 1] corresponds to a neutral white
73  * point of (x,y)=(1/3,1/3).  However, most color systems assume some other
74  * white point, such as D65, and an absolute color conversion to XYZ then
75  * to another color space with a different white point may introduce an
76  * unwanted color cast to the image.  It is often desirable, therefore, to
77  * perform a white point conversion that maps the input white to [1 1 1]
78  * in XYZ, then record the original white point using the TIFFTAG_WHITEPOINT
79  * tag value.  A decoder that demands absolute color calibration may use
80  * this white point tag to get back the original colors, but usually it
81  * will be ignored and the new white point will be used instead that
82  * matches the output color space.
83  *
84  * Pixel information is compressed into one of two basic encodings, depending
85  * on the setting of the compression tag, which is one of COMPRESSION_SGILOG
86  * or COMPRESSION_SGILOG24.  For COMPRESSION_SGILOG, greyscale data is
87  * stored as:
88  *
89  *	 1       15
90  *	|-+---------------|
91  *
92  * COMPRESSION_SGILOG color data is stored as:
93  *
94  *	 1       15           8        8
95  *	|-+---------------|--------+--------|
96  *	 S       Le           ue       ve
97  *
98  * For the 24-bit COMPRESSION_SGILOG24 color format, the data is stored as:
99  *
100  *	     10           14
101  *	|----------|--------------|
102  *	     Le'          Ce
103  *
104  * There is no sign bit in the 24-bit case, and the (u,v) chromaticity is
105  * encoded as an index for optimal color resolution.  The 10 log bits are
106  * defined by the following conversions:
107  *
108  *	L = 2^((Le'+.5)/64 - 12)		# real from 10-bit
109  *
110  *	Le' = floor( 64*(log2(L) + 12) )	# 10-bit from real
111  *
112  * The 10 bits of the smaller format may be converted into the 15 bits of
113  * the larger format by multiplying by 4 and adding 13314.  Obviously,
114  * a smaller range of magnitudes is covered (about 5 orders of magnitude
115  * instead of 38), and the lack of a sign bit means that negative luminances
116  * are not allowed.  (Well, they aren't allowed in the real world, either,
117  * but they are useful for certain types of image processing.)
118  *
119  * The desired user format is controlled by the setting the internal
120  * pseudo tag TIFFTAG_SGILOGDATAFMT to one of:
121  *  SGILOGDATAFMT_FLOAT       = IEEE 32-bit float XYZ values
122  *  SGILOGDATAFMT_16BIT	      = 16-bit integer encodings of logL, u and v
123  * Raw data i/o is also possible using:
124  *  SGILOGDATAFMT_RAW         = 32-bit unsigned integer with encoded pixel
125  * In addition, the following decoding is provided for ease of display:
126  *  SGILOGDATAFMT_8BIT        = 8-bit default RGB gamma-corrected values
127  *
128  * For grayscale images, we provide the following data formats:
129  *  SGILOGDATAFMT_FLOAT       = IEEE 32-bit float Y values
130  *  SGILOGDATAFMT_16BIT       = 16-bit integer w/ encoded luminance
131  *  SGILOGDATAFMT_8BIT        = 8-bit gray monitor values
132  *
133  * Note that the COMPRESSION_SGILOG applies a simple run-length encoding
134  * scheme by separating the logL, u and v bytes for each row and applying
135  * a PackBits type of compression.  Since the 24-bit encoding is not
136  * adaptive, the 32-bit color format takes less space in many cases.
137  *
138  * Further control is provided over the conversion from higher-resolution
139  * formats to final encoded values through the pseudo tag
140  * TIFFTAG_SGILOGENCODE:
141  *  SGILOGENCODE_NODITHER     = do not dither encoded values
142  *  SGILOGENCODE_RANDITHER    = apply random dithering during encoding
143  *
144  * The default value of this tag is SGILOGENCODE_NODITHER for
145  * COMPRESSION_SGILOG to maximize run-length encoding and
146  * SGILOGENCODE_RANDITHER for COMPRESSION_SGILOG24 to turn
147  * quantization errors into noise.
148  */
149 
150 #include <stdio.h>
151 #include <stdlib.h>
152 #include <math.h>
153 
154 /*
155  * State block for each open TIFF
156  * file using LogLuv compression/decompression.
157  */
158 typedef struct logLuvState LogLuvState;
159 
160 struct logLuvState {
161 	int                     user_datafmt;   /* user data format */
162 	int                     encode_meth;    /* encoding method */
163 	int                     pixel_size;     /* bytes per pixel */
164 
165 	uint8*                  tbuf;           /* translation buffer */
166 	tmsize_t                tbuflen;        /* buffer length */
167 	void (*tfunc)(LogLuvState*, uint8*, tmsize_t);
168 
169 	TIFFVSetMethod          vgetparent;     /* super-class method */
170 	TIFFVSetMethod          vsetparent;     /* super-class method */
171 };
172 
173 #define DecoderState(tif)	((LogLuvState*) (tif)->tif_data)
174 #define EncoderState(tif)	((LogLuvState*) (tif)->tif_data)
175 
176 #define SGILOGDATAFMT_UNKNOWN -1
177 
178 #define MINRUN 4 /* minimum run length */
179 
180 /*
181  * Decode a string of 16-bit gray pixels.
182  */
183 static int
LogL16Decode(TIFF * tif,uint8 * op,tmsize_t occ,uint16 s)184 LogL16Decode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
185 {
186 	static const char module[] = "LogL16Decode";
187 	LogLuvState* sp = DecoderState(tif);
188 	int shft;
189 	tmsize_t i;
190 	tmsize_t npixels;
191 	unsigned char* bp;
192 	int16* tp;
193 	int16 b;
194 	tmsize_t cc;
195 	int rc;
196 
197 	assert(s == 0);
198 	assert(sp != NULL);
199 
200 	npixels = occ / sp->pixel_size;
201 
202 	if (sp->user_datafmt == SGILOGDATAFMT_16BIT)
203 		tp = (int16*) op;
204 	else {
205 		assert(sp->tbuflen >= npixels);
206 		tp = (int16*) sp->tbuf;
207 	}
208 	_TIFFmemset((void*) tp, 0, npixels*sizeof (tp[0]));
209 
210 	bp = (unsigned char*) tif->tif_rawcp;
211 	cc = tif->tif_rawcc;
212 	/* get each byte string */
213 	for (shft = 2*8; (shft -= 8) >= 0; ) {
214 		for (i = 0; i < npixels && cc > 0; )
215 			if (*bp >= 128) {		/* run */
216 				rc = *bp++ + (2-128);   /* TODO: potential input buffer overrun when decoding corrupt or truncated data */
217 				b = (int16)(*bp++ << shft);
218 				cc -= 2;
219 				while (rc-- && i < npixels)
220 					tp[i++] |= b;
221 			} else {			/* non-run */
222 				rc = *bp++;		/* nul is noop */
223 				while (--cc && rc-- && i < npixels)
224 					tp[i++] |= (int16)*bp++ << shft;
225 			}
226 		if (i != npixels) {
227 #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
228 			TIFFErrorExt(tif->tif_clientdata, module,
229 			    "Not enough data at row %lu (short %I64d pixels)",
230 				     (unsigned long) tif->tif_row,
231 				     (unsigned __int64) (npixels - i));
232 #else
233 			TIFFErrorExt(tif->tif_clientdata, module,
234 			    "Not enough data at row %lu (short %llu pixels)",
235 				     (unsigned long) tif->tif_row,
236 				     (unsigned long long) (npixels - i));
237 #endif
238 			tif->tif_rawcp = (uint8*) bp;
239 			tif->tif_rawcc = cc;
240 			return (0);
241 		}
242 	}
243 	(*sp->tfunc)(sp, op, npixels);
244 	tif->tif_rawcp = (uint8*) bp;
245 	tif->tif_rawcc = cc;
246 	return (1);
247 }
248 
249 /*
250  * Decode a string of 24-bit pixels.
251  */
252 static int
LogLuvDecode24(TIFF * tif,uint8 * op,tmsize_t occ,uint16 s)253 LogLuvDecode24(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
254 {
255 	static const char module[] = "LogLuvDecode24";
256 	LogLuvState* sp = DecoderState(tif);
257 	tmsize_t cc;
258 	tmsize_t i;
259 	tmsize_t npixels;
260 	unsigned char* bp;
261 	uint32* tp;
262 
263 	assert(s == 0);
264 	assert(sp != NULL);
265 
266 	npixels = occ / sp->pixel_size;
267 
268 	if (sp->user_datafmt == SGILOGDATAFMT_RAW)
269 		tp = (uint32 *)op;
270 	else {
271 		assert(sp->tbuflen >= npixels);
272 		tp = (uint32 *) sp->tbuf;
273 	}
274 	/* copy to array of uint32 */
275 	bp = (unsigned char*) tif->tif_rawcp;
276 	cc = tif->tif_rawcc;
277 	for (i = 0; i < npixels && cc > 0; i++) {
278 		tp[i] = bp[0] << 16 | bp[1] << 8 | bp[2];
279 		bp += 3;
280 		cc -= 3;
281 	}
282 	tif->tif_rawcp = (uint8*) bp;
283 	tif->tif_rawcc = cc;
284 	if (i != npixels) {
285 #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
286 		TIFFErrorExt(tif->tif_clientdata, module,
287 			"Not enough data at row %lu (short %I64d pixels)",
288 			     (unsigned long) tif->tif_row,
289 			     (unsigned __int64) (npixels - i));
290 #else
291 		TIFFErrorExt(tif->tif_clientdata, module,
292 			"Not enough data at row %lu (short %llu pixels)",
293 			     (unsigned long) tif->tif_row,
294 			     (unsigned long long) (npixels - i));
295 #endif
296 		return (0);
297 	}
298 	(*sp->tfunc)(sp, op, npixels);
299 	return (1);
300 }
301 
302 /*
303  * Decode a string of 32-bit pixels.
304  */
305 static int
LogLuvDecode32(TIFF * tif,uint8 * op,tmsize_t occ,uint16 s)306 LogLuvDecode32(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
307 {
308 	static const char module[] = "LogLuvDecode32";
309 	LogLuvState* sp;
310 	int shft;
311 	tmsize_t i;
312 	tmsize_t npixels;
313 	unsigned char* bp;
314 	uint32* tp;
315 	uint32 b;
316 	tmsize_t cc;
317 	int rc;
318 
319 	assert(s == 0);
320 	sp = DecoderState(tif);
321 	assert(sp != NULL);
322 
323 	npixels = occ / sp->pixel_size;
324 
325 	if (sp->user_datafmt == SGILOGDATAFMT_RAW)
326 		tp = (uint32*) op;
327 	else {
328 		assert(sp->tbuflen >= npixels);
329 		tp = (uint32*) sp->tbuf;
330 	}
331 	_TIFFmemset((void*) tp, 0, npixels*sizeof (tp[0]));
332 
333 	bp = (unsigned char*) tif->tif_rawcp;
334 	cc = tif->tif_rawcc;
335 	/* get each byte string */
336 	for (shft = 4*8; (shft -= 8) >= 0; ) {
337 		for (i = 0; i < npixels && cc > 0; )
338 			if (*bp >= 128) {		/* run */
339 				rc = *bp++ + (2-128);
340 				b = (uint32)*bp++ << shft;
341 				cc -= 2;                /* TODO: potential input buffer overrun when decoding corrupt or truncated data */
342 				while (rc-- && i < npixels)
343 					tp[i++] |= b;
344 			} else {			/* non-run */
345 				rc = *bp++;		/* nul is noop */
346 				while (--cc && rc-- && i < npixels)
347 					tp[i++] |= (uint32)*bp++ << shft;
348 			}
349 		if (i != npixels) {
350 #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__))
351 			TIFFErrorExt(tif->tif_clientdata, module,
352 			"Not enough data at row %lu (short %I64d pixels)",
353 				     (unsigned long) tif->tif_row,
354 				     (unsigned __int64) (npixels - i));
355 #else
356 			TIFFErrorExt(tif->tif_clientdata, module,
357 			"Not enough data at row %lu (short %llu pixels)",
358 				     (unsigned long) tif->tif_row,
359 				     (unsigned long long) (npixels - i));
360 #endif
361 			tif->tif_rawcp = (uint8*) bp;
362 			tif->tif_rawcc = cc;
363 			return (0);
364 		}
365 	}
366 	(*sp->tfunc)(sp, op, npixels);
367 	tif->tif_rawcp = (uint8*) bp;
368 	tif->tif_rawcc = cc;
369 	return (1);
370 }
371 
372 /*
373  * Decode a strip of pixels.  We break it into rows to
374  * maintain synchrony with the encode algorithm, which
375  * is row by row.
376  */
377 static int
LogLuvDecodeStrip(TIFF * tif,uint8 * bp,tmsize_t cc,uint16 s)378 LogLuvDecodeStrip(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
379 {
380 	tmsize_t rowlen = TIFFScanlineSize(tif);
381 
382         if (rowlen == 0)
383                 return 0;
384 
385 	assert(cc%rowlen == 0);
386 	while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s))
387 		bp += rowlen, cc -= rowlen;
388 	return (cc == 0);
389 }
390 
391 /*
392  * Decode a tile of pixels.  We break it into rows to
393  * maintain synchrony with the encode algorithm, which
394  * is row by row.
395  */
396 static int
LogLuvDecodeTile(TIFF * tif,uint8 * bp,tmsize_t cc,uint16 s)397 LogLuvDecodeTile(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
398 {
399 	tmsize_t rowlen = TIFFTileRowSize(tif);
400 
401         if (rowlen == 0)
402                 return 0;
403 
404 	assert(cc%rowlen == 0);
405 	while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s))
406 		bp += rowlen, cc -= rowlen;
407 	return (cc == 0);
408 }
409 
410 /*
411  * Encode a row of 16-bit pixels.
412  */
413 static int
LogL16Encode(TIFF * tif,uint8 * bp,tmsize_t cc,uint16 s)414 LogL16Encode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
415 {
416 	LogLuvState* sp = EncoderState(tif);
417 	int shft;
418 	tmsize_t i;
419 	tmsize_t j;
420 	tmsize_t npixels;
421 	uint8* op;
422 	int16* tp;
423 	int16 b;
424 	tmsize_t occ;
425 	int rc=0, mask;
426 	tmsize_t beg;
427 
428 	assert(s == 0);
429 	assert(sp != NULL);
430 	npixels = cc / sp->pixel_size;
431 
432 	if (sp->user_datafmt == SGILOGDATAFMT_16BIT)
433 		tp = (int16*) bp;
434 	else {
435 		tp = (int16*) sp->tbuf;
436 		assert(sp->tbuflen >= npixels);
437 		(*sp->tfunc)(sp, bp, npixels);
438 	}
439 	/* compress each byte string */
440 	op = tif->tif_rawcp;
441 	occ = tif->tif_rawdatasize - tif->tif_rawcc;
442 	for (shft = 2*8; (shft -= 8) >= 0; )
443 		for (i = 0; i < npixels; i += rc) {
444 			if (occ < 4) {
445 				tif->tif_rawcp = op;
446 				tif->tif_rawcc = tif->tif_rawdatasize - occ;
447 				if (!TIFFFlushData1(tif))
448 					return (-1);
449 				op = tif->tif_rawcp;
450 				occ = tif->tif_rawdatasize - tif->tif_rawcc;
451 			}
452 			mask = 0xff << shft;		/* find next run */
453 			for (beg = i; beg < npixels; beg += rc) {
454 				b = (int16) (tp[beg] & mask);
455 				rc = 1;
456 				while (rc < 127+2 && beg+rc < npixels &&
457 				    (tp[beg+rc] & mask) == b)
458 					rc++;
459 				if (rc >= MINRUN)
460 					break;		/* long enough */
461 			}
462 			if (beg-i > 1 && beg-i < MINRUN) {
463 				b = (int16) (tp[i] & mask);/*check short run */
464 				j = i+1;
465 				while ((tp[j++] & mask) == b)
466 					if (j == beg) {
467 						*op++ = (uint8)(128-2+j-i);
468 						*op++ = (uint8)(b >> shft);
469 						occ -= 2;
470 						i = beg;
471 						break;
472 					}
473 			}
474 			while (i < beg) {		/* write out non-run */
475 				if ((j = beg-i) > 127) j = 127;
476 				if (occ < j+3) {
477 					tif->tif_rawcp = op;
478 					tif->tif_rawcc = tif->tif_rawdatasize - occ;
479 					if (!TIFFFlushData1(tif))
480 						return (-1);
481 					op = tif->tif_rawcp;
482 					occ = tif->tif_rawdatasize - tif->tif_rawcc;
483 				}
484 				*op++ = (uint8) j; occ--;
485 				while (j--) {
486 					*op++ = (uint8) (tp[i++] >> shft & 0xff);
487 					occ--;
488 				}
489 			}
490 			if (rc >= MINRUN) {		/* write out run */
491 				*op++ = (uint8) (128-2+rc);
492 				*op++ = (uint8) (tp[beg] >> shft & 0xff);
493 				occ -= 2;
494 			} else
495 				rc = 0;
496 		}
497 	tif->tif_rawcp = op;
498 	tif->tif_rawcc = tif->tif_rawdatasize - occ;
499 
500 	return (1);
501 }
502 
503 /*
504  * Encode a row of 24-bit pixels.
505  */
506 static int
LogLuvEncode24(TIFF * tif,uint8 * bp,tmsize_t cc,uint16 s)507 LogLuvEncode24(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
508 {
509 	LogLuvState* sp = EncoderState(tif);
510 	tmsize_t i;
511 	tmsize_t npixels;
512 	tmsize_t occ;
513 	uint8* op;
514 	uint32* tp;
515 
516 	assert(s == 0);
517 	assert(sp != NULL);
518 	npixels = cc / sp->pixel_size;
519 
520 	if (sp->user_datafmt == SGILOGDATAFMT_RAW)
521 		tp = (uint32*) bp;
522 	else {
523 		tp = (uint32*) sp->tbuf;
524 		assert(sp->tbuflen >= npixels);
525 		(*sp->tfunc)(sp, bp, npixels);
526 	}
527 	/* write out encoded pixels */
528 	op = tif->tif_rawcp;
529 	occ = tif->tif_rawdatasize - tif->tif_rawcc;
530 	for (i = npixels; i--; ) {
531 		if (occ < 3) {
532 			tif->tif_rawcp = op;
533 			tif->tif_rawcc = tif->tif_rawdatasize - occ;
534 			if (!TIFFFlushData1(tif))
535 				return (-1);
536 			op = tif->tif_rawcp;
537 			occ = tif->tif_rawdatasize - tif->tif_rawcc;
538 		}
539 		*op++ = (uint8)(*tp >> 16);
540 		*op++ = (uint8)(*tp >> 8 & 0xff);
541 		*op++ = (uint8)(*tp++ & 0xff);
542 		occ -= 3;
543 	}
544 	tif->tif_rawcp = op;
545 	tif->tif_rawcc = tif->tif_rawdatasize - occ;
546 
547 	return (1);
548 }
549 
550 /*
551  * Encode a row of 32-bit pixels.
552  */
553 static int
LogLuvEncode32(TIFF * tif,uint8 * bp,tmsize_t cc,uint16 s)554 LogLuvEncode32(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
555 {
556 	LogLuvState* sp = EncoderState(tif);
557 	int shft;
558 	tmsize_t i;
559 	tmsize_t j;
560 	tmsize_t npixels;
561 	uint8* op;
562 	uint32* tp;
563 	uint32 b;
564 	tmsize_t occ;
565 	int rc=0, mask;
566 	tmsize_t beg;
567 
568 	assert(s == 0);
569 	assert(sp != NULL);
570 
571 	npixels = cc / sp->pixel_size;
572 
573 	if (sp->user_datafmt == SGILOGDATAFMT_RAW)
574 		tp = (uint32*) bp;
575 	else {
576 		tp = (uint32*) sp->tbuf;
577 		assert(sp->tbuflen >= npixels);
578 		(*sp->tfunc)(sp, bp, npixels);
579 	}
580 	/* compress each byte string */
581 	op = tif->tif_rawcp;
582 	occ = tif->tif_rawdatasize - tif->tif_rawcc;
583 	for (shft = 4*8; (shft -= 8) >= 0; )
584 		for (i = 0; i < npixels; i += rc) {
585 			if (occ < 4) {
586 				tif->tif_rawcp = op;
587 				tif->tif_rawcc = tif->tif_rawdatasize - occ;
588 				if (!TIFFFlushData1(tif))
589 					return (-1);
590 				op = tif->tif_rawcp;
591 				occ = tif->tif_rawdatasize - tif->tif_rawcc;
592 			}
593 			mask = 0xff << shft;		/* find next run */
594 			for (beg = i; beg < npixels; beg += rc) {
595 				b = tp[beg] & mask;
596 				rc = 1;
597 				while (rc < 127+2 && beg+rc < npixels &&
598 						(tp[beg+rc] & mask) == b)
599 					rc++;
600 				if (rc >= MINRUN)
601 					break;		/* long enough */
602 			}
603 			if (beg-i > 1 && beg-i < MINRUN) {
604 				b = tp[i] & mask;	/* check short run */
605 				j = i+1;
606 				while ((tp[j++] & mask) == b)
607 					if (j == beg) {
608 						*op++ = (uint8)(128-2+j-i);
609 						*op++ = (uint8)(b >> shft);
610 						occ -= 2;
611 						i = beg;
612 						break;
613 					}
614 			}
615 			while (i < beg) {		/* write out non-run */
616 				if ((j = beg-i) > 127) j = 127;
617 				if (occ < j+3) {
618 					tif->tif_rawcp = op;
619 					tif->tif_rawcc = tif->tif_rawdatasize - occ;
620 					if (!TIFFFlushData1(tif))
621 						return (-1);
622 					op = tif->tif_rawcp;
623 					occ = tif->tif_rawdatasize - tif->tif_rawcc;
624 				}
625 				*op++ = (uint8) j; occ--;
626 				while (j--) {
627 					*op++ = (uint8)(tp[i++] >> shft & 0xff);
628 					occ--;
629 				}
630 			}
631 			if (rc >= MINRUN) {		/* write out run */
632 				*op++ = (uint8) (128-2+rc);
633 				*op++ = (uint8)(tp[beg] >> shft & 0xff);
634 				occ -= 2;
635 			} else
636 				rc = 0;
637 		}
638 	tif->tif_rawcp = op;
639 	tif->tif_rawcc = tif->tif_rawdatasize - occ;
640 
641 	return (1);
642 }
643 
644 /*
645  * Encode a strip of pixels.  We break it into rows to
646  * avoid encoding runs across row boundaries.
647  */
648 static int
LogLuvEncodeStrip(TIFF * tif,uint8 * bp,tmsize_t cc,uint16 s)649 LogLuvEncodeStrip(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
650 {
651 	tmsize_t rowlen = TIFFScanlineSize(tif);
652 
653         if (rowlen == 0)
654                 return 0;
655 
656 	assert(cc%rowlen == 0);
657 	while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 1)
658 		bp += rowlen, cc -= rowlen;
659 	return (cc == 0);
660 }
661 
662 /*
663  * Encode a tile of pixels.  We break it into rows to
664  * avoid encoding runs across row boundaries.
665  */
666 static int
LogLuvEncodeTile(TIFF * tif,uint8 * bp,tmsize_t cc,uint16 s)667 LogLuvEncodeTile(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
668 {
669 	tmsize_t rowlen = TIFFTileRowSize(tif);
670 
671         if (rowlen == 0)
672                 return 0;
673 
674 	assert(cc%rowlen == 0);
675 	while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 1)
676 		bp += rowlen, cc -= rowlen;
677 	return (cc == 0);
678 }
679 
680 /*
681  * Encode/Decode functions for converting to and from user formats.
682  */
683 
684 #include "uvcode.h"
685 
686 #ifndef UVSCALE
687 #define U_NEU		0.210526316
688 #define V_NEU		0.473684211
689 #define UVSCALE		410.
690 #endif
691 
692 #ifndef	M_LN2
693 #define M_LN2		0.69314718055994530942
694 #endif
695 #ifndef M_PI
696 #define M_PI		3.14159265358979323846
697 #endif
698 #undef log2 /* Conflict with C'99 function */
699 #define log2(x)		((1./M_LN2)*log(x))
700 #undef exp2  /* Conflict with C'99 function */
701 #define exp2(x)		exp(M_LN2*(x))
702 
703 #define itrunc(x,m)	((m)==SGILOGENCODE_NODITHER ? \
704 				(int)(x) : \
705 				(int)((x) + rand()*(1./RAND_MAX) - .5))
706 
707 #if !LOGLUV_PUBLIC
708 static
709 #endif
710 double
LogL16toY(int p16)711 LogL16toY(int p16)		/* compute luminance from 16-bit LogL */
712 {
713 	int	Le = p16 & 0x7fff;
714 	double	Y;
715 
716 	if (!Le)
717 		return (0.);
718 	Y = exp(M_LN2/256.*(Le+.5) - M_LN2*64.);
719 	return (!(p16 & 0x8000) ? Y : -Y);
720 }
721 
722 #if !LOGLUV_PUBLIC
723 static
724 #endif
725 int
LogL16fromY(double Y,int em)726 LogL16fromY(double Y, int em)	/* get 16-bit LogL from Y */
727 {
728 	if (Y >= 1.8371976e19)
729 		return (0x7fff);
730 	if (Y <= -1.8371976e19)
731 		return (0xffff);
732 	if (Y > 5.4136769e-20)
733 		return itrunc(256.*(log2(Y) + 64.), em);
734 	if (Y < -5.4136769e-20)
735 		return (~0x7fff | itrunc(256.*(log2(-Y) + 64.), em));
736 	return (0);
737 }
738 
739 static void
L16toY(LogLuvState * sp,uint8 * op,tmsize_t n)740 L16toY(LogLuvState* sp, uint8* op, tmsize_t n)
741 {
742 	int16* l16 = (int16*) sp->tbuf;
743 	float* yp = (float*) op;
744 
745 	while (n-- > 0)
746 		*yp++ = (float)LogL16toY(*l16++);
747 }
748 
749 static void
L16toGry(LogLuvState * sp,uint8 * op,tmsize_t n)750 L16toGry(LogLuvState* sp, uint8* op, tmsize_t n)
751 {
752 	int16* l16 = (int16*) sp->tbuf;
753 	uint8* gp = (uint8*) op;
754 
755 	while (n-- > 0) {
756 		double Y = LogL16toY(*l16++);
757 		*gp++ = (uint8) ((Y <= 0.) ? 0 : (Y >= 1.) ? 255 : (int)(256.*sqrt(Y)));
758 	}
759 }
760 
761 static void
L16fromY(LogLuvState * sp,uint8 * op,tmsize_t n)762 L16fromY(LogLuvState* sp, uint8* op, tmsize_t n)
763 {
764 	int16* l16 = (int16*) sp->tbuf;
765 	float* yp = (float*) op;
766 
767 	while (n-- > 0)
768 		*l16++ = (int16) (LogL16fromY(*yp++, sp->encode_meth));
769 }
770 
771 #if !LOGLUV_PUBLIC
772 static
773 #endif
774 void
XYZtoRGB24(float xyz[3],uint8 rgb[3])775 XYZtoRGB24(float xyz[3], uint8 rgb[3])
776 {
777 	double	r, g, b;
778 					/* assume CCIR-709 primaries */
779 	r =  2.690*xyz[0] + -1.276*xyz[1] + -0.414*xyz[2];
780 	g = -1.022*xyz[0] +  1.978*xyz[1] +  0.044*xyz[2];
781 	b =  0.061*xyz[0] + -0.224*xyz[1] +  1.163*xyz[2];
782 					/* assume 2.0 gamma for speed */
783 	/* could use integer sqrt approx., but this is probably faster */
784 	rgb[0] = (uint8)((r<=0.) ? 0 : (r >= 1.) ? 255 : (int)(256.*sqrt(r)));
785 	rgb[1] = (uint8)((g<=0.) ? 0 : (g >= 1.) ? 255 : (int)(256.*sqrt(g)));
786 	rgb[2] = (uint8)((b<=0.) ? 0 : (b >= 1.) ? 255 : (int)(256.*sqrt(b)));
787 }
788 
789 #if !LOGLUV_PUBLIC
790 static
791 #endif
792 double
LogL10toY(int p10)793 LogL10toY(int p10)		/* compute luminance from 10-bit LogL */
794 {
795 	if (p10 == 0)
796 		return (0.);
797 	return (exp(M_LN2/64.*(p10+.5) - M_LN2*12.));
798 }
799 
800 #if !LOGLUV_PUBLIC
801 static
802 #endif
803 int
LogL10fromY(double Y,int em)804 LogL10fromY(double Y, int em)	/* get 10-bit LogL from Y */
805 {
806 	if (Y >= 15.742)
807 		return (0x3ff);
808 	else if (Y <= .00024283)
809 		return (0);
810 	else
811 		return itrunc(64.*(log2(Y) + 12.), em);
812 }
813 
814 #define NANGLES		100
815 #define uv2ang(u, v)	( (NANGLES*.499999999/M_PI) \
816 				* atan2((v)-V_NEU,(u)-U_NEU) + .5*NANGLES )
817 
818 static int
oog_encode(double u,double v)819 oog_encode(double u, double v)		/* encode out-of-gamut chroma */
820 {
821 	static int	oog_table[NANGLES];
822 	static int	initialized = 0;
823 	register int	i;
824 
825 	if (!initialized) {		/* set up perimeter table */
826 		double	eps[NANGLES], ua, va, ang, epsa;
827 		int	ui, vi, ustep;
828 		for (i = NANGLES; i--; )
829 			eps[i] = 2.;
830 		for (vi = UV_NVS; vi--; ) {
831 			va = UV_VSTART + (vi+.5)*UV_SQSIZ;
832 			ustep = uv_row[vi].nus-1;
833 			if (vi == UV_NVS-1 || vi == 0 || ustep <= 0)
834 				ustep = 1;
835 			for (ui = uv_row[vi].nus-1; ui >= 0; ui -= ustep) {
836 				ua = uv_row[vi].ustart + (ui+.5)*UV_SQSIZ;
837 				ang = uv2ang(ua, va);
838 				i = (int) ang;
839 				epsa = fabs(ang - (i+.5));
840 				if (epsa < eps[i]) {
841 					oog_table[i] = uv_row[vi].ncum + ui;
842 					eps[i] = epsa;
843 				}
844 			}
845 		}
846 		for (i = NANGLES; i--; )	/* fill any holes */
847 			if (eps[i] > 1.5) {
848 				int	i1, i2;
849 				for (i1 = 1; i1 < NANGLES/2; i1++)
850 					if (eps[(i+i1)%NANGLES] < 1.5)
851 						break;
852 				for (i2 = 1; i2 < NANGLES/2; i2++)
853 					if (eps[(i+NANGLES-i2)%NANGLES] < 1.5)
854 						break;
855 				if (i1 < i2)
856 					oog_table[i] =
857 						oog_table[(i+i1)%NANGLES];
858 				else
859 					oog_table[i] =
860 						oog_table[(i+NANGLES-i2)%NANGLES];
861 			}
862 		initialized = 1;
863 	}
864 	i = (int) uv2ang(u, v);		/* look up hue angle */
865 	return (oog_table[i]);
866 }
867 
868 #undef uv2ang
869 #undef NANGLES
870 
871 #if !LOGLUV_PUBLIC
872 static
873 #endif
874 int
uv_encode(double u,double v,int em)875 uv_encode(double u, double v, int em)	/* encode (u',v') coordinates */
876 {
877 	register int	vi, ui;
878 
879 	if (v < UV_VSTART)
880 		return oog_encode(u, v);
881 	vi = itrunc((v - UV_VSTART)*(1./UV_SQSIZ), em);
882 	if (vi >= UV_NVS)
883 		return oog_encode(u, v);
884 	if (u < uv_row[vi].ustart)
885 		return oog_encode(u, v);
886 	ui = itrunc((u - uv_row[vi].ustart)*(1./UV_SQSIZ), em);
887 	if (ui >= uv_row[vi].nus)
888 		return oog_encode(u, v);
889 
890 	return (uv_row[vi].ncum + ui);
891 }
892 
893 #if !LOGLUV_PUBLIC
894 static
895 #endif
896 int
uv_decode(double * up,double * vp,int c)897 uv_decode(double *up, double *vp, int c)	/* decode (u',v') index */
898 {
899 	int	upper, lower;
900 	register int	ui, vi;
901 
902 	if (c < 0 || c >= UV_NDIVS)
903 		return (-1);
904 	lower = 0;				/* binary search */
905 	upper = UV_NVS;
906 	while (upper - lower > 1) {
907 		vi = (lower + upper) >> 1;
908 		ui = c - uv_row[vi].ncum;
909 		if (ui > 0)
910 			lower = vi;
911 		else if (ui < 0)
912 			upper = vi;
913 		else {
914 			lower = vi;
915 			break;
916 		}
917 	}
918 	vi = lower;
919 	ui = c - uv_row[vi].ncum;
920 	*up = uv_row[vi].ustart + (ui+.5)*UV_SQSIZ;
921 	*vp = UV_VSTART + (vi+.5)*UV_SQSIZ;
922 	return (0);
923 }
924 
925 #if !LOGLUV_PUBLIC
926 static
927 #endif
928 void
LogLuv24toXYZ(uint32 p,float XYZ[3])929 LogLuv24toXYZ(uint32 p, float XYZ[3])
930 {
931 	int	Ce;
932 	double	L, u, v, s, x, y;
933 					/* decode luminance */
934 	L = LogL10toY(p>>14 & 0x3ff);
935 	if (L <= 0.) {
936 		XYZ[0] = XYZ[1] = XYZ[2] = 0.;
937 		return;
938 	}
939 					/* decode color */
940 	Ce = p & 0x3fff;
941 	if (uv_decode(&u, &v, Ce) < 0) {
942 		u = U_NEU; v = V_NEU;
943 	}
944 	s = 1./(6.*u - 16.*v + 12.);
945 	x = 9.*u * s;
946 	y = 4.*v * s;
947 					/* convert to XYZ */
948 	XYZ[0] = (float)(x/y * L);
949 	XYZ[1] = (float)L;
950 	XYZ[2] = (float)((1.-x-y)/y * L);
951 }
952 
953 #if !LOGLUV_PUBLIC
954 static
955 #endif
956 uint32
LogLuv24fromXYZ(float XYZ[3],int em)957 LogLuv24fromXYZ(float XYZ[3], int em)
958 {
959 	int	Le, Ce;
960 	double	u, v, s;
961 					/* encode luminance */
962 	Le = LogL10fromY(XYZ[1], em);
963 					/* encode color */
964 	s = XYZ[0] + 15.*XYZ[1] + 3.*XYZ[2];
965 	if (!Le || s <= 0.) {
966 		u = U_NEU;
967 		v = V_NEU;
968 	} else {
969 		u = 4.*XYZ[0] / s;
970 		v = 9.*XYZ[1] / s;
971 	}
972 	Ce = uv_encode(u, v, em);
973 	if (Ce < 0)			/* never happens */
974 		Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER);
975 					/* combine encodings */
976 	return (Le << 14 | Ce);
977 }
978 
979 static void
Luv24toXYZ(LogLuvState * sp,uint8 * op,tmsize_t n)980 Luv24toXYZ(LogLuvState* sp, uint8* op, tmsize_t n)
981 {
982 	uint32* luv = (uint32*) sp->tbuf;
983 	float* xyz = (float*) op;
984 
985 	while (n-- > 0) {
986 		LogLuv24toXYZ(*luv, xyz);
987 		xyz += 3;
988 		luv++;
989 	}
990 }
991 
992 static void
Luv24toLuv48(LogLuvState * sp,uint8 * op,tmsize_t n)993 Luv24toLuv48(LogLuvState* sp, uint8* op, tmsize_t n)
994 {
995 	uint32* luv = (uint32*) sp->tbuf;
996 	int16* luv3 = (int16*) op;
997 
998 	while (n-- > 0) {
999 		double u, v;
1000 
1001 		*luv3++ = (int16)((*luv >> 12 & 0xffd) + 13314);
1002 		if (uv_decode(&u, &v, *luv&0x3fff) < 0) {
1003 			u = U_NEU;
1004 			v = V_NEU;
1005 		}
1006 		*luv3++ = (int16)(u * (1L<<15));
1007 		*luv3++ = (int16)(v * (1L<<15));
1008 		luv++;
1009 	}
1010 }
1011 
1012 static void
Luv24toRGB(LogLuvState * sp,uint8 * op,tmsize_t n)1013 Luv24toRGB(LogLuvState* sp, uint8* op, tmsize_t n)
1014 {
1015 	uint32* luv = (uint32*) sp->tbuf;
1016 	uint8* rgb = (uint8*) op;
1017 
1018 	while (n-- > 0) {
1019 		float xyz[3];
1020 
1021 		LogLuv24toXYZ(*luv++, xyz);
1022 		XYZtoRGB24(xyz, rgb);
1023 		rgb += 3;
1024 	}
1025 }
1026 
1027 static void
Luv24fromXYZ(LogLuvState * sp,uint8 * op,tmsize_t n)1028 Luv24fromXYZ(LogLuvState* sp, uint8* op, tmsize_t n)
1029 {
1030 	uint32* luv = (uint32*) sp->tbuf;
1031 	float* xyz = (float*) op;
1032 
1033 	while (n-- > 0) {
1034 		*luv++ = LogLuv24fromXYZ(xyz, sp->encode_meth);
1035 		xyz += 3;
1036 	}
1037 }
1038 
1039 static void
Luv24fromLuv48(LogLuvState * sp,uint8 * op,tmsize_t n)1040 Luv24fromLuv48(LogLuvState* sp, uint8* op, tmsize_t n)
1041 {
1042 	uint32* luv = (uint32*) sp->tbuf;
1043 	int16* luv3 = (int16*) op;
1044 
1045 	while (n-- > 0) {
1046 		int Le, Ce;
1047 
1048 		if (luv3[0] <= 0)
1049 			Le = 0;
1050 		else if (luv3[0] >= (1<<12)+3314)
1051 			Le = (1<<10) - 1;
1052 		else if (sp->encode_meth == SGILOGENCODE_NODITHER)
1053 			Le = (luv3[0]-3314) >> 2;
1054 		else
1055 			Le = itrunc(.25*(luv3[0]-3314.), sp->encode_meth);
1056 
1057 		Ce = uv_encode((luv3[1]+.5)/(1<<15), (luv3[2]+.5)/(1<<15),
1058 					sp->encode_meth);
1059 		if (Ce < 0)	/* never happens */
1060 			Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER);
1061 		*luv++ = (uint32)Le << 14 | Ce;
1062 		luv3 += 3;
1063 	}
1064 }
1065 
1066 #if !LOGLUV_PUBLIC
1067 static
1068 #endif
1069 void
LogLuv32toXYZ(uint32 p,float XYZ[3])1070 LogLuv32toXYZ(uint32 p, float XYZ[3])
1071 {
1072 	double	L, u, v, s, x, y;
1073 					/* decode luminance */
1074 	L = LogL16toY((int)p >> 16);
1075 	if (L <= 0.) {
1076 		XYZ[0] = XYZ[1] = XYZ[2] = 0.;
1077 		return;
1078 	}
1079 					/* decode color */
1080 	u = 1./UVSCALE * ((p>>8 & 0xff) + .5);
1081 	v = 1./UVSCALE * ((p & 0xff) + .5);
1082 	s = 1./(6.*u - 16.*v + 12.);
1083 	x = 9.*u * s;
1084 	y = 4.*v * s;
1085 					/* convert to XYZ */
1086 	XYZ[0] = (float)(x/y * L);
1087 	XYZ[1] = (float)L;
1088 	XYZ[2] = (float)((1.-x-y)/y * L);
1089 }
1090 
1091 #if !LOGLUV_PUBLIC
1092 static
1093 #endif
1094 uint32
LogLuv32fromXYZ(float XYZ[3],int em)1095 LogLuv32fromXYZ(float XYZ[3], int em)
1096 {
1097 	unsigned int	Le, ue, ve;
1098 	double	u, v, s;
1099 					/* encode luminance */
1100 	Le = (unsigned int)LogL16fromY(XYZ[1], em);
1101 					/* encode color */
1102 	s = XYZ[0] + 15.*XYZ[1] + 3.*XYZ[2];
1103 	if (!Le || s <= 0.) {
1104 		u = U_NEU;
1105 		v = V_NEU;
1106 	} else {
1107 		u = 4.*XYZ[0] / s;
1108 		v = 9.*XYZ[1] / s;
1109 	}
1110 	if (u <= 0.) ue = 0;
1111 	else ue = itrunc(UVSCALE*u, em);
1112 	if (ue > 255) ue = 255;
1113 	if (v <= 0.) ve = 0;
1114 	else ve = itrunc(UVSCALE*v, em);
1115 	if (ve > 255) ve = 255;
1116 					/* combine encodings */
1117 	return (Le << 16 | ue << 8 | ve);
1118 }
1119 
1120 static void
Luv32toXYZ(LogLuvState * sp,uint8 * op,tmsize_t n)1121 Luv32toXYZ(LogLuvState* sp, uint8* op, tmsize_t n)
1122 {
1123 	uint32* luv = (uint32*) sp->tbuf;
1124 	float* xyz = (float*) op;
1125 
1126 	while (n-- > 0) {
1127 		LogLuv32toXYZ(*luv++, xyz);
1128 		xyz += 3;
1129 	}
1130 }
1131 
1132 static void
Luv32toLuv48(LogLuvState * sp,uint8 * op,tmsize_t n)1133 Luv32toLuv48(LogLuvState* sp, uint8* op, tmsize_t n)
1134 {
1135 	uint32* luv = (uint32*) sp->tbuf;
1136 	int16* luv3 = (int16*) op;
1137 
1138 	while (n-- > 0) {
1139 		double u, v;
1140 
1141 		*luv3++ = (int16)(*luv >> 16);
1142 		u = 1./UVSCALE * ((*luv>>8 & 0xff) + .5);
1143 		v = 1./UVSCALE * ((*luv & 0xff) + .5);
1144 		*luv3++ = (int16)(u * (1L<<15));
1145 		*luv3++ = (int16)(v * (1L<<15));
1146 		luv++;
1147 	}
1148 }
1149 
1150 static void
Luv32toRGB(LogLuvState * sp,uint8 * op,tmsize_t n)1151 Luv32toRGB(LogLuvState* sp, uint8* op, tmsize_t n)
1152 {
1153 	uint32* luv = (uint32*) sp->tbuf;
1154 	uint8* rgb = (uint8*) op;
1155 
1156 	while (n-- > 0) {
1157 		float xyz[3];
1158 
1159 		LogLuv32toXYZ(*luv++, xyz);
1160 		XYZtoRGB24(xyz, rgb);
1161 		rgb += 3;
1162 	}
1163 }
1164 
1165 static void
Luv32fromXYZ(LogLuvState * sp,uint8 * op,tmsize_t n)1166 Luv32fromXYZ(LogLuvState* sp, uint8* op, tmsize_t n)
1167 {
1168 	uint32* luv = (uint32*) sp->tbuf;
1169 	float* xyz = (float*) op;
1170 
1171 	while (n-- > 0) {
1172 		*luv++ = LogLuv32fromXYZ(xyz, sp->encode_meth);
1173 		xyz += 3;
1174 	}
1175 }
1176 
1177 static void
Luv32fromLuv48(LogLuvState * sp,uint8 * op,tmsize_t n)1178 Luv32fromLuv48(LogLuvState* sp, uint8* op, tmsize_t n)
1179 {
1180 	uint32* luv = (uint32*) sp->tbuf;
1181 	int16* luv3 = (int16*) op;
1182 
1183 	if (sp->encode_meth == SGILOGENCODE_NODITHER) {
1184 		while (n-- > 0) {
1185 			*luv++ = (uint32)luv3[0] << 16 |
1186 				(luv3[1]*(uint32)(UVSCALE+.5) >> 7 & 0xff00) |
1187 				(luv3[2]*(uint32)(UVSCALE+.5) >> 15 & 0xff);
1188 			luv3 += 3;
1189 		}
1190 		return;
1191 	}
1192 	while (n-- > 0) {
1193 		*luv++ = (uint32)luv3[0] << 16 |
1194 	(itrunc(luv3[1]*(UVSCALE/(1<<15)), sp->encode_meth) << 8 & 0xff00) |
1195 		(itrunc(luv3[2]*(UVSCALE/(1<<15)), sp->encode_meth) & 0xff);
1196 		luv3 += 3;
1197 	}
1198 }
1199 
1200 static void
_logLuvNop(LogLuvState * sp,uint8 * op,tmsize_t n)1201 _logLuvNop(LogLuvState* sp, uint8* op, tmsize_t n)
1202 {
1203 	(void) sp; (void) op; (void) n;
1204 }
1205 
1206 static int
LogL16GuessDataFmt(TIFFDirectory * td)1207 LogL16GuessDataFmt(TIFFDirectory *td)
1208 {
1209 #define	PACK(s,b,f)	(((b)<<6)|((s)<<3)|(f))
1210 	switch (PACK(td->td_samplesperpixel, td->td_bitspersample, td->td_sampleformat)) {
1211 	case PACK(1, 32, SAMPLEFORMAT_IEEEFP):
1212 		return (SGILOGDATAFMT_FLOAT);
1213 	case PACK(1, 16, SAMPLEFORMAT_VOID):
1214 	case PACK(1, 16, SAMPLEFORMAT_INT):
1215 	case PACK(1, 16, SAMPLEFORMAT_UINT):
1216 		return (SGILOGDATAFMT_16BIT);
1217 	case PACK(1,  8, SAMPLEFORMAT_VOID):
1218 	case PACK(1,  8, SAMPLEFORMAT_UINT):
1219 		return (SGILOGDATAFMT_8BIT);
1220 	}
1221 #undef PACK
1222 	return (SGILOGDATAFMT_UNKNOWN);
1223 }
1224 
1225 static tmsize_t
multiply_ms(tmsize_t m1,tmsize_t m2)1226 multiply_ms(tmsize_t m1, tmsize_t m2)
1227 {
1228 	tmsize_t bytes = m1 * m2;
1229 
1230 	if (m1 && bytes / m1 != m2)
1231 		bytes = 0;
1232 
1233 	return bytes;
1234 }
1235 
1236 static int
LogL16InitState(TIFF * tif)1237 LogL16InitState(TIFF* tif)
1238 {
1239 	static const char module[] = "LogL16InitState";
1240 	TIFFDirectory *td = &tif->tif_dir;
1241 	LogLuvState* sp = DecoderState(tif);
1242 
1243 	assert(sp != NULL);
1244 	assert(td->td_photometric == PHOTOMETRIC_LOGL);
1245 
1246 	/* for some reason, we can't do this in TIFFInitLogL16 */
1247 	if (sp->user_datafmt == SGILOGDATAFMT_UNKNOWN)
1248 		sp->user_datafmt = LogL16GuessDataFmt(td);
1249 	switch (sp->user_datafmt) {
1250 	case SGILOGDATAFMT_FLOAT:
1251 		sp->pixel_size = sizeof (float);
1252 		break;
1253 	case SGILOGDATAFMT_16BIT:
1254 		sp->pixel_size = sizeof (int16);
1255 		break;
1256 	case SGILOGDATAFMT_8BIT:
1257 		sp->pixel_size = sizeof (uint8);
1258 		break;
1259 	default:
1260 		TIFFErrorExt(tif->tif_clientdata, module,
1261 		    "No support for converting user data format to LogL");
1262 		return (0);
1263 	}
1264         if( isTiled(tif) )
1265             sp->tbuflen = multiply_ms(td->td_tilewidth, td->td_tilelength);
1266         else
1267             sp->tbuflen = multiply_ms(td->td_imagewidth, td->td_rowsperstrip);
1268 	if (multiply_ms(sp->tbuflen, sizeof (int16)) == 0 ||
1269 	    (sp->tbuf = (uint8*) _TIFFmalloc(sp->tbuflen * sizeof (int16))) == NULL) {
1270 		TIFFErrorExt(tif->tif_clientdata, module, "No space for SGILog translation buffer");
1271 		return (0);
1272 	}
1273 	return (1);
1274 }
1275 
1276 static int
LogLuvGuessDataFmt(TIFFDirectory * td)1277 LogLuvGuessDataFmt(TIFFDirectory *td)
1278 {
1279 	int guess;
1280 
1281 	/*
1282 	 * If the user didn't tell us their datafmt,
1283 	 * take our best guess from the bitspersample.
1284 	 */
1285 #define	PACK(a,b)	(((a)<<3)|(b))
1286 	switch (PACK(td->td_bitspersample, td->td_sampleformat)) {
1287 	case PACK(32, SAMPLEFORMAT_IEEEFP):
1288 		guess = SGILOGDATAFMT_FLOAT;
1289 		break;
1290 	case PACK(32, SAMPLEFORMAT_VOID):
1291 	case PACK(32, SAMPLEFORMAT_UINT):
1292 	case PACK(32, SAMPLEFORMAT_INT):
1293 		guess = SGILOGDATAFMT_RAW;
1294 		break;
1295 	case PACK(16, SAMPLEFORMAT_VOID):
1296 	case PACK(16, SAMPLEFORMAT_INT):
1297 	case PACK(16, SAMPLEFORMAT_UINT):
1298 		guess = SGILOGDATAFMT_16BIT;
1299 		break;
1300 	case PACK( 8, SAMPLEFORMAT_VOID):
1301 	case PACK( 8, SAMPLEFORMAT_UINT):
1302 		guess = SGILOGDATAFMT_8BIT;
1303 		break;
1304 	default:
1305 		guess = SGILOGDATAFMT_UNKNOWN;
1306 		break;
1307 #undef PACK
1308 	}
1309 	/*
1310 	 * Double-check samples per pixel.
1311 	 */
1312 	switch (td->td_samplesperpixel) {
1313 	case 1:
1314 		if (guess != SGILOGDATAFMT_RAW)
1315 			guess = SGILOGDATAFMT_UNKNOWN;
1316 		break;
1317 	case 3:
1318 		if (guess == SGILOGDATAFMT_RAW)
1319 			guess = SGILOGDATAFMT_UNKNOWN;
1320 		break;
1321 	default:
1322 		guess = SGILOGDATAFMT_UNKNOWN;
1323 		break;
1324 	}
1325 	return (guess);
1326 }
1327 
1328 static int
LogLuvInitState(TIFF * tif)1329 LogLuvInitState(TIFF* tif)
1330 {
1331 	static const char module[] = "LogLuvInitState";
1332 	TIFFDirectory* td = &tif->tif_dir;
1333 	LogLuvState* sp = DecoderState(tif);
1334 
1335 	assert(sp != NULL);
1336 	assert(td->td_photometric == PHOTOMETRIC_LOGLUV);
1337 
1338 	/* for some reason, we can't do this in TIFFInitLogLuv */
1339 	if (td->td_planarconfig != PLANARCONFIG_CONTIG) {
1340 		TIFFErrorExt(tif->tif_clientdata, module,
1341 		    "SGILog compression cannot handle non-contiguous data");
1342 		return (0);
1343 	}
1344 	if (sp->user_datafmt == SGILOGDATAFMT_UNKNOWN)
1345 		sp->user_datafmt = LogLuvGuessDataFmt(td);
1346 	switch (sp->user_datafmt) {
1347 	case SGILOGDATAFMT_FLOAT:
1348 		sp->pixel_size = 3*sizeof (float);
1349 		break;
1350 	case SGILOGDATAFMT_16BIT:
1351 		sp->pixel_size = 3*sizeof (int16);
1352 		break;
1353 	case SGILOGDATAFMT_RAW:
1354 		sp->pixel_size = sizeof (uint32);
1355 		break;
1356 	case SGILOGDATAFMT_8BIT:
1357 		sp->pixel_size = 3*sizeof (uint8);
1358 		break;
1359 	default:
1360 		TIFFErrorExt(tif->tif_clientdata, module,
1361 		    "No support for converting user data format to LogLuv");
1362 		return (0);
1363 	}
1364         if( isTiled(tif) )
1365             sp->tbuflen = multiply_ms(td->td_tilewidth, td->td_tilelength);
1366         else
1367             sp->tbuflen = multiply_ms(td->td_imagewidth, td->td_rowsperstrip);
1368 	if (multiply_ms(sp->tbuflen, sizeof (uint32)) == 0 ||
1369 	    (sp->tbuf = (uint8*) _TIFFmalloc(sp->tbuflen * sizeof (uint32))) == NULL) {
1370 		TIFFErrorExt(tif->tif_clientdata, module, "No space for SGILog translation buffer");
1371 		return (0);
1372 	}
1373 	return (1);
1374 }
1375 
1376 static int
LogLuvFixupTags(TIFF * tif)1377 LogLuvFixupTags(TIFF* tif)
1378 {
1379 	(void) tif;
1380 	return (1);
1381 }
1382 
1383 static int
LogLuvSetupDecode(TIFF * tif)1384 LogLuvSetupDecode(TIFF* tif)
1385 {
1386 	static const char module[] = "LogLuvSetupDecode";
1387 	LogLuvState* sp = DecoderState(tif);
1388 	TIFFDirectory* td = &tif->tif_dir;
1389 
1390 	tif->tif_postdecode = _TIFFNoPostDecode;
1391 	switch (td->td_photometric) {
1392 	case PHOTOMETRIC_LOGLUV:
1393 		if (!LogLuvInitState(tif))
1394 			break;
1395 		if (td->td_compression == COMPRESSION_SGILOG24) {
1396 			tif->tif_decoderow = LogLuvDecode24;
1397 			switch (sp->user_datafmt) {
1398 			case SGILOGDATAFMT_FLOAT:
1399 				sp->tfunc = Luv24toXYZ;
1400 				break;
1401 			case SGILOGDATAFMT_16BIT:
1402 				sp->tfunc = Luv24toLuv48;
1403 				break;
1404 			case SGILOGDATAFMT_8BIT:
1405 				sp->tfunc = Luv24toRGB;
1406 				break;
1407 			}
1408 		} else {
1409 			tif->tif_decoderow = LogLuvDecode32;
1410 			switch (sp->user_datafmt) {
1411 			case SGILOGDATAFMT_FLOAT:
1412 				sp->tfunc = Luv32toXYZ;
1413 				break;
1414 			case SGILOGDATAFMT_16BIT:
1415 				sp->tfunc = Luv32toLuv48;
1416 				break;
1417 			case SGILOGDATAFMT_8BIT:
1418 				sp->tfunc = Luv32toRGB;
1419 				break;
1420 			}
1421 		}
1422 		return (1);
1423 	case PHOTOMETRIC_LOGL:
1424 		if (!LogL16InitState(tif))
1425 			break;
1426 		tif->tif_decoderow = LogL16Decode;
1427 		switch (sp->user_datafmt) {
1428 		case SGILOGDATAFMT_FLOAT:
1429 			sp->tfunc = L16toY;
1430 			break;
1431 		case SGILOGDATAFMT_8BIT:
1432 			sp->tfunc = L16toGry;
1433 			break;
1434 		}
1435 		return (1);
1436 	default:
1437 		TIFFErrorExt(tif->tif_clientdata, module,
1438 		    "Inappropriate photometric interpretation %d for SGILog compression; %s",
1439 		    td->td_photometric, "must be either LogLUV or LogL");
1440 		break;
1441 	}
1442 	return (0);
1443 }
1444 
1445 static int
LogLuvSetupEncode(TIFF * tif)1446 LogLuvSetupEncode(TIFF* tif)
1447 {
1448 	static const char module[] = "LogLuvSetupEncode";
1449 	LogLuvState* sp = EncoderState(tif);
1450 	TIFFDirectory* td = &tif->tif_dir;
1451 
1452 	switch (td->td_photometric) {
1453 	case PHOTOMETRIC_LOGLUV:
1454 		if (!LogLuvInitState(tif))
1455 			break;
1456 		if (td->td_compression == COMPRESSION_SGILOG24) {
1457 			tif->tif_encoderow = LogLuvEncode24;
1458 			switch (sp->user_datafmt) {
1459 			case SGILOGDATAFMT_FLOAT:
1460 				sp->tfunc = Luv24fromXYZ;
1461 				break;
1462 			case SGILOGDATAFMT_16BIT:
1463 				sp->tfunc = Luv24fromLuv48;
1464 				break;
1465 			case SGILOGDATAFMT_RAW:
1466 				break;
1467 			default:
1468 				goto notsupported;
1469 			}
1470 		} else {
1471 			tif->tif_encoderow = LogLuvEncode32;
1472 			switch (sp->user_datafmt) {
1473 			case SGILOGDATAFMT_FLOAT:
1474 				sp->tfunc = Luv32fromXYZ;
1475 				break;
1476 			case SGILOGDATAFMT_16BIT:
1477 				sp->tfunc = Luv32fromLuv48;
1478 				break;
1479 			case SGILOGDATAFMT_RAW:
1480 				break;
1481 			default:
1482 				goto notsupported;
1483 			}
1484 		}
1485 		break;
1486 	case PHOTOMETRIC_LOGL:
1487 		if (!LogL16InitState(tif))
1488 			break;
1489 		tif->tif_encoderow = LogL16Encode;
1490 		switch (sp->user_datafmt) {
1491 		case SGILOGDATAFMT_FLOAT:
1492 			sp->tfunc = L16fromY;
1493 			break;
1494 		case SGILOGDATAFMT_16BIT:
1495 			break;
1496 		default:
1497 			goto notsupported;
1498 		}
1499 		break;
1500 	default:
1501 		TIFFErrorExt(tif->tif_clientdata, module,
1502 		    "Inappropriate photometric interpretation %d for SGILog compression; %s",
1503 		    td->td_photometric, "must be either LogLUV or LogL");
1504 		break;
1505 	}
1506 	return (1);
1507 notsupported:
1508 	TIFFErrorExt(tif->tif_clientdata, module,
1509 	    "SGILog compression supported only for %s, or raw data",
1510 	    td->td_photometric == PHOTOMETRIC_LOGL ? "Y, L" : "XYZ, Luv");
1511 	return (0);
1512 }
1513 
1514 static void
LogLuvClose(TIFF * tif)1515 LogLuvClose(TIFF* tif)
1516 {
1517 	TIFFDirectory *td = &tif->tif_dir;
1518 
1519 	/*
1520 	 * For consistency, we always want to write out the same
1521 	 * bitspersample and sampleformat for our TIFF file,
1522 	 * regardless of the data format being used by the application.
1523 	 * Since this routine is called after tags have been set but
1524 	 * before they have been recorded in the file, we reset them here.
1525 	 */
1526 	td->td_samplesperpixel =
1527 	    (td->td_photometric == PHOTOMETRIC_LOGL) ? 1 : 3;
1528 	td->td_bitspersample = 16;
1529 	td->td_sampleformat = SAMPLEFORMAT_INT;
1530 }
1531 
1532 static void
LogLuvCleanup(TIFF * tif)1533 LogLuvCleanup(TIFF* tif)
1534 {
1535 	LogLuvState* sp = (LogLuvState *)tif->tif_data;
1536 
1537 	assert(sp != 0);
1538 
1539 	tif->tif_tagmethods.vgetfield = sp->vgetparent;
1540 	tif->tif_tagmethods.vsetfield = sp->vsetparent;
1541 
1542 	if (sp->tbuf)
1543 		_TIFFfree(sp->tbuf);
1544 	_TIFFfree(sp);
1545 	tif->tif_data = NULL;
1546 
1547 	_TIFFSetDefaultCompressionState(tif);
1548 }
1549 
1550 static int
LogLuvVSetField(TIFF * tif,uint32 tag,va_list ap)1551 LogLuvVSetField(TIFF* tif, uint32 tag, va_list ap)
1552 {
1553 	static const char module[] = "LogLuvVSetField";
1554 	LogLuvState* sp = DecoderState(tif);
1555 	int bps, fmt;
1556 
1557 	switch (tag) {
1558 	case TIFFTAG_SGILOGDATAFMT:
1559 		sp->user_datafmt = (int) va_arg(ap, int);
1560 		/*
1561 		 * Tweak the TIFF header so that the rest of libtiff knows what
1562 		 * size of data will be passed between app and library, and
1563 		 * assume that the app knows what it is doing and is not
1564 		 * confused by these header manipulations...
1565 		 */
1566 		switch (sp->user_datafmt) {
1567 		case SGILOGDATAFMT_FLOAT:
1568 			bps = 32, fmt = SAMPLEFORMAT_IEEEFP;
1569 			break;
1570 		case SGILOGDATAFMT_16BIT:
1571 			bps = 16, fmt = SAMPLEFORMAT_INT;
1572 			break;
1573 		case SGILOGDATAFMT_RAW:
1574 			bps = 32, fmt = SAMPLEFORMAT_UINT;
1575 			TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
1576 			break;
1577 		case SGILOGDATAFMT_8BIT:
1578 			bps = 8, fmt = SAMPLEFORMAT_UINT;
1579 			break;
1580 		default:
1581 			TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
1582 			    "Unknown data format %d for LogLuv compression",
1583 			    sp->user_datafmt);
1584 			return (0);
1585 		}
1586 		TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps);
1587 		TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, fmt);
1588 		/*
1589 		 * Must recalculate sizes should bits/sample change.
1590 		 */
1591 		tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tmsize_t) -1;
1592 		tif->tif_scanlinesize = TIFFScanlineSize(tif);
1593 		return (1);
1594 	case TIFFTAG_SGILOGENCODE:
1595 		sp->encode_meth = (int) va_arg(ap, int);
1596 		if (sp->encode_meth != SGILOGENCODE_NODITHER &&
1597 		    sp->encode_meth != SGILOGENCODE_RANDITHER) {
1598 			TIFFErrorExt(tif->tif_clientdata, module,
1599 			    "Unknown encoding %d for LogLuv compression",
1600 			    sp->encode_meth);
1601 			return (0);
1602 		}
1603 		return (1);
1604 	default:
1605 		return (*sp->vsetparent)(tif, tag, ap);
1606 	}
1607 }
1608 
1609 static int
LogLuvVGetField(TIFF * tif,uint32 tag,va_list ap)1610 LogLuvVGetField(TIFF* tif, uint32 tag, va_list ap)
1611 {
1612 	LogLuvState *sp = (LogLuvState *)tif->tif_data;
1613 
1614 	switch (tag) {
1615 	case TIFFTAG_SGILOGDATAFMT:
1616 		*va_arg(ap, int*) = sp->user_datafmt;
1617 		return (1);
1618 	default:
1619 		return (*sp->vgetparent)(tif, tag, ap);
1620 	}
1621 }
1622 
1623 static const TIFFField LogLuvFields[] = {
1624     { TIFFTAG_SGILOGDATAFMT, 0, 0, TIFF_SHORT, 0, TIFF_SETGET_INT, TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "SGILogDataFmt", NULL},
1625     { TIFFTAG_SGILOGENCODE, 0, 0, TIFF_SHORT, 0, TIFF_SETGET_INT, TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "SGILogEncode", NULL}
1626 };
1627 
1628 int
TIFFInitSGILog(TIFF * tif,int scheme)1629 TIFFInitSGILog(TIFF* tif, int scheme)
1630 {
1631 	static const char module[] = "TIFFInitSGILog";
1632 	LogLuvState* sp;
1633 
1634 	assert(scheme == COMPRESSION_SGILOG24 || scheme == COMPRESSION_SGILOG);
1635 
1636 	/*
1637 	 * Merge codec-specific tag information.
1638 	 */
1639 	if (!_TIFFMergeFields(tif, LogLuvFields,
1640 			      TIFFArrayCount(LogLuvFields))) {
1641 		TIFFErrorExt(tif->tif_clientdata, module,
1642 		    "Merging SGILog codec-specific tags failed");
1643 		return 0;
1644 	}
1645 
1646 	/*
1647 	 * Allocate state block so tag methods have storage to record values.
1648 	 */
1649 	tif->tif_data = (uint8*) _TIFFmalloc(sizeof (LogLuvState));
1650 	if (tif->tif_data == NULL)
1651 		goto bad;
1652 	sp = (LogLuvState*) tif->tif_data;
1653 	_TIFFmemset((void*)sp, 0, sizeof (*sp));
1654 	sp->user_datafmt = SGILOGDATAFMT_UNKNOWN;
1655 	sp->encode_meth = (scheme == COMPRESSION_SGILOG24) ?
1656 	    SGILOGENCODE_RANDITHER : SGILOGENCODE_NODITHER;
1657 	sp->tfunc = _logLuvNop;
1658 
1659 	/*
1660 	 * Install codec methods.
1661 	 * NB: tif_decoderow & tif_encoderow are filled
1662 	 *     in at setup time.
1663 	 */
1664 	tif->tif_fixuptags = LogLuvFixupTags;
1665 	tif->tif_setupdecode = LogLuvSetupDecode;
1666 	tif->tif_decodestrip = LogLuvDecodeStrip;
1667 	tif->tif_decodetile = LogLuvDecodeTile;
1668 	tif->tif_setupencode = LogLuvSetupEncode;
1669 	tif->tif_encodestrip = LogLuvEncodeStrip;
1670 	tif->tif_encodetile = LogLuvEncodeTile;
1671 	tif->tif_close = LogLuvClose;
1672 	tif->tif_cleanup = LogLuvCleanup;
1673 
1674 	/*
1675 	 * Override parent get/set field methods.
1676 	 */
1677 	sp->vgetparent = tif->tif_tagmethods.vgetfield;
1678 	tif->tif_tagmethods.vgetfield = LogLuvVGetField;   /* hook for codec tags */
1679 	sp->vsetparent = tif->tif_tagmethods.vsetfield;
1680 	tif->tif_tagmethods.vsetfield = LogLuvVSetField;   /* hook for codec tags */
1681 
1682 	return (1);
1683 bad:
1684 	TIFFErrorExt(tif->tif_clientdata, module,
1685 		     "%s: No space for LogLuv state block", tif->tif_name);
1686 	return (0);
1687 }
1688 #endif /* LOGLUV_SUPPORT */
1689 
1690 /* vim: set ts=8 sts=8 sw=8 noet: */
1691 /*
1692  * Local Variables:
1693  * mode: c
1694  * c-basic-offset: 8
1695  * fill-column: 78
1696  * End:
1697  */
1698