Home | History | Annotate | Download | only in libtiff
      1 /* $Id: tif_luv.c,v 1.35 2011-04-02 20:54: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
    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
    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
    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
    378 LogLuvDecodeStrip(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
    379 {
    380     tmsize_t rowlen = TIFFScanlineSize(tif);
    381 
    382     assert(cc%rowlen == 0);
    383     while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s))
    384         bp += rowlen, cc -= rowlen;
    385     return (cc == 0);
    386 }
    387 
    388 /*
    389  * Decode a tile of pixels.  We break it into rows to
    390  * maintain synchrony with the encode algorithm, which
    391  * is row by row.
    392  */
    393 static int
    394 LogLuvDecodeTile(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
    395 {
    396     tmsize_t rowlen = TIFFTileRowSize(tif);
    397 
    398     assert(cc%rowlen == 0);
    399     while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s))
    400         bp += rowlen, cc -= rowlen;
    401     return (cc == 0);
    402 }
    403 
    404 /*
    405  * Encode a row of 16-bit pixels.
    406  */
    407 static int
    408 LogL16Encode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
    409 {
    410     LogLuvState* sp = EncoderState(tif);
    411     int shft;
    412     tmsize_t i;
    413     tmsize_t j;
    414     tmsize_t npixels;
    415     uint8* op;
    416     int16* tp;
    417     int16 b;
    418     tmsize_t occ;
    419     int rc=0, mask;
    420     tmsize_t beg;
    421 
    422     assert(s == 0);
    423     assert(sp != NULL);
    424     npixels = cc / sp->pixel_size;
    425 
    426     if (sp->user_datafmt == SGILOGDATAFMT_16BIT)
    427         tp = (int16*) bp;
    428     else {
    429         tp = (int16*) sp->tbuf;
    430         assert(sp->tbuflen >= npixels);
    431         (*sp->tfunc)(sp, bp, npixels);
    432     }
    433     /* compress each byte string */
    434     op = tif->tif_rawcp;
    435     occ = tif->tif_rawdatasize - tif->tif_rawcc;
    436     for (shft = 2*8; (shft -= 8) >= 0; )
    437         for (i = 0; i < npixels; i += rc) {
    438             if (occ < 4) {
    439                 tif->tif_rawcp = op;
    440                 tif->tif_rawcc = tif->tif_rawdatasize - occ;
    441                 if (!TIFFFlushData1(tif))
    442                     return (-1);
    443                 op = tif->tif_rawcp;
    444                 occ = tif->tif_rawdatasize - tif->tif_rawcc;
    445             }
    446             mask = 0xff << shft;		/* find next run */
    447             for (beg = i; beg < npixels; beg += rc) {
    448                 b = (int16) (tp[beg] & mask);
    449                 rc = 1;
    450                 while (rc < 127+2 && beg+rc < npixels &&
    451                     (tp[beg+rc] & mask) == b)
    452                     rc++;
    453                 if (rc >= MINRUN)
    454                     break;		/* long enough */
    455             }
    456             if (beg-i > 1 && beg-i < MINRUN) {
    457                 b = (int16) (tp[i] & mask);/*check short run */
    458                 j = i+1;
    459                 while ((tp[j++] & mask) == b)
    460                     if (j == beg) {
    461                         *op++ = (uint8)(128-2+j-i);
    462                         *op++ = (uint8)(b >> shft);
    463                         occ -= 2;
    464                         i = beg;
    465                         break;
    466                     }
    467             }
    468             while (i < beg) {		/* write out non-run */
    469                 if ((j = beg-i) > 127) j = 127;
    470                 if (occ < j+3) {
    471                     tif->tif_rawcp = op;
    472                     tif->tif_rawcc = tif->tif_rawdatasize - occ;
    473                     if (!TIFFFlushData1(tif))
    474                         return (-1);
    475                     op = tif->tif_rawcp;
    476                     occ = tif->tif_rawdatasize - tif->tif_rawcc;
    477                 }
    478                 *op++ = (uint8) j; occ--;
    479                 while (j--) {
    480                     *op++ = (uint8) (tp[i++] >> shft & 0xff);
    481                     occ--;
    482                 }
    483             }
    484             if (rc >= MINRUN) {		/* write out run */
    485                 *op++ = (uint8) (128-2+rc);
    486                 *op++ = (uint8) (tp[beg] >> shft & 0xff);
    487                 occ -= 2;
    488             } else
    489                 rc = 0;
    490         }
    491     tif->tif_rawcp = op;
    492     tif->tif_rawcc = tif->tif_rawdatasize - occ;
    493 
    494     return (1);
    495 }
    496 
    497 /*
    498  * Encode a row of 24-bit pixels.
    499  */
    500 static int
    501 LogLuvEncode24(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
    502 {
    503     LogLuvState* sp = EncoderState(tif);
    504     tmsize_t i;
    505     tmsize_t npixels;
    506     tmsize_t occ;
    507     uint8* op;
    508     uint32* tp;
    509 
    510     assert(s == 0);
    511     assert(sp != NULL);
    512     npixels = cc / sp->pixel_size;
    513 
    514     if (sp->user_datafmt == SGILOGDATAFMT_RAW)
    515         tp = (uint32*) bp;
    516     else {
    517         tp = (uint32*) sp->tbuf;
    518         assert(sp->tbuflen >= npixels);
    519         (*sp->tfunc)(sp, bp, npixels);
    520     }
    521     /* write out encoded pixels */
    522     op = tif->tif_rawcp;
    523     occ = tif->tif_rawdatasize - tif->tif_rawcc;
    524     for (i = npixels; i--; ) {
    525         if (occ < 3) {
    526             tif->tif_rawcp = op;
    527             tif->tif_rawcc = tif->tif_rawdatasize - occ;
    528             if (!TIFFFlushData1(tif))
    529                 return (-1);
    530             op = tif->tif_rawcp;
    531             occ = tif->tif_rawdatasize - tif->tif_rawcc;
    532         }
    533         *op++ = (uint8)(*tp >> 16);
    534         *op++ = (uint8)(*tp >> 8 & 0xff);
    535         *op++ = (uint8)(*tp++ & 0xff);
    536         occ -= 3;
    537     }
    538     tif->tif_rawcp = op;
    539     tif->tif_rawcc = tif->tif_rawdatasize - occ;
    540 
    541     return (1);
    542 }
    543 
    544 /*
    545  * Encode a row of 32-bit pixels.
    546  */
    547 static int
    548 LogLuvEncode32(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
    549 {
    550     LogLuvState* sp = EncoderState(tif);
    551     int shft;
    552     tmsize_t i;
    553     tmsize_t j;
    554     tmsize_t npixels;
    555     uint8* op;
    556     uint32* tp;
    557     uint32 b;
    558     tmsize_t occ;
    559     int rc=0, mask;
    560     tmsize_t beg;
    561 
    562     assert(s == 0);
    563     assert(sp != NULL);
    564 
    565     npixels = cc / sp->pixel_size;
    566 
    567     if (sp->user_datafmt == SGILOGDATAFMT_RAW)
    568         tp = (uint32*) bp;
    569     else {
    570         tp = (uint32*) sp->tbuf;
    571         assert(sp->tbuflen >= npixels);
    572         (*sp->tfunc)(sp, bp, npixels);
    573     }
    574     /* compress each byte string */
    575     op = tif->tif_rawcp;
    576     occ = tif->tif_rawdatasize - tif->tif_rawcc;
    577     for (shft = 4*8; (shft -= 8) >= 0; )
    578         for (i = 0; i < npixels; i += rc) {
    579             if (occ < 4) {
    580                 tif->tif_rawcp = op;
    581                 tif->tif_rawcc = tif->tif_rawdatasize - occ;
    582                 if (!TIFFFlushData1(tif))
    583                     return (-1);
    584                 op = tif->tif_rawcp;
    585                 occ = tif->tif_rawdatasize - tif->tif_rawcc;
    586             }
    587             mask = 0xff << shft;		/* find next run */
    588             for (beg = i; beg < npixels; beg += rc) {
    589                 b = tp[beg] & mask;
    590                 rc = 1;
    591                 while (rc < 127+2 && beg+rc < npixels &&
    592                         (tp[beg+rc] & mask) == b)
    593                     rc++;
    594                 if (rc >= MINRUN)
    595                     break;		/* long enough */
    596             }
    597             if (beg-i > 1 && beg-i < MINRUN) {
    598                 b = tp[i] & mask;	/* check short run */
    599                 j = i+1;
    600                 while ((tp[j++] & mask) == b)
    601                     if (j == beg) {
    602                         *op++ = (uint8)(128-2+j-i);
    603                         *op++ = (uint8)(b >> shft);
    604                         occ -= 2;
    605                         i = beg;
    606                         break;
    607                     }
    608             }
    609             while (i < beg) {		/* write out non-run */
    610                 if ((j = beg-i) > 127) j = 127;
    611                 if (occ < j+3) {
    612                     tif->tif_rawcp = op;
    613                     tif->tif_rawcc = tif->tif_rawdatasize - occ;
    614                     if (!TIFFFlushData1(tif))
    615                         return (-1);
    616                     op = tif->tif_rawcp;
    617                     occ = tif->tif_rawdatasize - tif->tif_rawcc;
    618                 }
    619                 *op++ = (uint8) j; occ--;
    620                 while (j--) {
    621                     *op++ = (uint8)(tp[i++] >> shft & 0xff);
    622                     occ--;
    623                 }
    624             }
    625             if (rc >= MINRUN) {		/* write out run */
    626                 *op++ = (uint8) (128-2+rc);
    627                 *op++ = (uint8)(tp[beg] >> shft & 0xff);
    628                 occ -= 2;
    629             } else
    630                 rc = 0;
    631         }
    632     tif->tif_rawcp = op;
    633     tif->tif_rawcc = tif->tif_rawdatasize - occ;
    634 
    635     return (1);
    636 }
    637 
    638 /*
    639  * Encode a strip of pixels.  We break it into rows to
    640  * avoid encoding runs across row boundaries.
    641  */
    642 static int
    643 LogLuvEncodeStrip(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
    644 {
    645     tmsize_t rowlen = TIFFScanlineSize(tif);
    646 
    647     assert(cc%rowlen == 0);
    648     while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 1)
    649         bp += rowlen, cc -= rowlen;
    650     return (cc == 0);
    651 }
    652 
    653 /*
    654  * Encode a tile of pixels.  We break it into rows to
    655  * avoid encoding runs across row boundaries.
    656  */
    657 static int
    658 LogLuvEncodeTile(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
    659 {
    660     tmsize_t rowlen = TIFFTileRowSize(tif);
    661 
    662     assert(cc%rowlen == 0);
    663     while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 1)
    664         bp += rowlen, cc -= rowlen;
    665     return (cc == 0);
    666 }
    667 
    668 /*
    669  * Encode/Decode functions for converting to and from user formats.
    670  */
    671 
    672 #include "uvcode.h"
    673 
    674 #ifndef UVSCALE
    675 #define U_NEU		0.210526316
    676 #define V_NEU		0.473684211
    677 #define UVSCALE		410.
    678 #endif
    679 
    680 #ifndef	M_LN2
    681 #define M_LN2		0.69314718055994530942
    682 #endif
    683 #ifndef M_PI
    684 #define M_PI		3.14159265358979323846
    685 #endif
    686 #define log2(x)		((1./M_LN2)*log(x))
    687 #define exp2(x)		exp(M_LN2*(x))
    688 
    689 #define itrunc(x,m)	((m)==SGILOGENCODE_NODITHER ? \
    690                 (int)(x) : \
    691                 (int)((x) + rand()*(1./RAND_MAX) - .5))
    692 
    693 #if !LOGLUV_PUBLIC
    694 static
    695 #endif
    696 double
    697 LogL16toY(int p16)		/* compute luminance from 16-bit LogL */
    698 {
    699     int	Le = p16 & 0x7fff;
    700     double	Y;
    701 
    702     if (!Le)
    703         return (0.);
    704     Y = exp(M_LN2/256.*(Le+.5) - M_LN2*64.);
    705     return (!(p16 & 0x8000) ? Y : -Y);
    706 }
    707 
    708 #if !LOGLUV_PUBLIC
    709 static
    710 #endif
    711 int
    712 LogL16fromY(double Y, int em)	/* get 16-bit LogL from Y */
    713 {
    714     if (Y >= 1.8371976e19)
    715         return (0x7fff);
    716     if (Y <= -1.8371976e19)
    717         return (0xffff);
    718     if (Y > 5.4136769e-20)
    719         return itrunc(256.*(log2(Y) + 64.), em);
    720     if (Y < -5.4136769e-20)
    721         return (~0x7fff | itrunc(256.*(log2(-Y) + 64.), em));
    722     return (0);
    723 }
    724 
    725 static void
    726 L16toY(LogLuvState* sp, uint8* op, tmsize_t n)
    727 {
    728     int16* l16 = (int16*) sp->tbuf;
    729     float* yp = (float*) op;
    730 
    731     while (n-- > 0)
    732         *yp++ = (float)LogL16toY(*l16++);
    733 }
    734 
    735 static void
    736 L16toGry(LogLuvState* sp, uint8* op, tmsize_t n)
    737 {
    738     int16* l16 = (int16*) sp->tbuf;
    739     uint8* gp = (uint8*) op;
    740 
    741     while (n-- > 0) {
    742         double Y = LogL16toY(*l16++);
    743         *gp++ = (uint8) ((Y <= 0.) ? 0 : (Y >= 1.) ? 255 : (int)(256.*sqrt(Y)));
    744     }
    745 }
    746 
    747 static void
    748 L16fromY(LogLuvState* sp, uint8* op, tmsize_t n)
    749 {
    750     int16* l16 = (int16*) sp->tbuf;
    751     float* yp = (float*) op;
    752 
    753     while (n-- > 0)
    754         *l16++ = (int16) (LogL16fromY(*yp++, sp->encode_meth));
    755 }
    756 
    757 #if !LOGLUV_PUBLIC
    758 static
    759 #endif
    760 void
    761 XYZtoRGB24(float xyz[3], uint8 rgb[3])
    762 {
    763     double	r, g, b;
    764                     /* assume CCIR-709 primaries */
    765     r =  2.690*xyz[0] + -1.276*xyz[1] + -0.414*xyz[2];
    766     g = -1.022*xyz[0] +  1.978*xyz[1] +  0.044*xyz[2];
    767     b =  0.061*xyz[0] + -0.224*xyz[1] +  1.163*xyz[2];
    768                     /* assume 2.0 gamma for speed */
    769     /* could use integer sqrt approx., but this is probably faster */
    770     rgb[0] = (uint8)((r<=0.) ? 0 : (r >= 1.) ? 255 : (int)(256.*sqrt(r)));
    771     rgb[1] = (uint8)((g<=0.) ? 0 : (g >= 1.) ? 255 : (int)(256.*sqrt(g)));
    772     rgb[2] = (uint8)((b<=0.) ? 0 : (b >= 1.) ? 255 : (int)(256.*sqrt(b)));
    773 }
    774 
    775 #if !LOGLUV_PUBLIC
    776 static
    777 #endif
    778 double
    779 LogL10toY(int p10)		/* compute luminance from 10-bit LogL */
    780 {
    781     if (p10 == 0)
    782         return (0.);
    783     return (exp(M_LN2/64.*(p10+.5) - M_LN2*12.));
    784 }
    785 
    786 #if !LOGLUV_PUBLIC
    787 static
    788 #endif
    789 int
    790 LogL10fromY(double Y, int em)	/* get 10-bit LogL from Y */
    791 {
    792     if (Y >= 15.742)
    793         return (0x3ff);
    794     else if (Y <= .00024283)
    795         return (0);
    796     else
    797         return itrunc(64.*(log2(Y) + 12.), em);
    798 }
    799 
    800 #define NANGLES		100
    801 #define uv2ang(u, v)	( (NANGLES*.499999999/M_PI) \
    802                 * atan2((v)-V_NEU,(u)-U_NEU) + .5*NANGLES )
    803 
    804 static int
    805 oog_encode(double u, double v)		/* encode out-of-gamut chroma */
    806 {
    807     static int	oog_table[NANGLES];
    808     static int	initialized = 0;
    809     register int	i;
    810 
    811     if (!initialized) {		/* set up perimeter table */
    812         double	eps[NANGLES], ua, va, ang, epsa;
    813         int	ui, vi, ustep;
    814         for (i = NANGLES; i--; )
    815             eps[i] = 2.;
    816         for (vi = UV_NVS; vi--; ) {
    817             va = UV_VSTART + (vi+.5)*UV_SQSIZ;
    818             ustep = uv_row[vi].nus-1;
    819             if (vi == UV_NVS-1 || vi == 0 || ustep <= 0)
    820                 ustep = 1;
    821             for (ui = uv_row[vi].nus-1; ui >= 0; ui -= ustep) {
    822                 ua = uv_row[vi].ustart + (ui+.5)*UV_SQSIZ;
    823                 ang = uv2ang(ua, va);
    824                 i = (int) ang;
    825                 epsa = fabs(ang - (i+.5));
    826                 if (epsa < eps[i]) {
    827                     oog_table[i] = uv_row[vi].ncum + ui;
    828                     eps[i] = epsa;
    829                 }
    830             }
    831         }
    832         for (i = NANGLES; i--; )	/* fill any holes */
    833             if (eps[i] > 1.5) {
    834                 int	i1, i2;
    835                 for (i1 = 1; i1 < NANGLES/2; i1++)
    836                     if (eps[(i+i1)%NANGLES] < 1.5)
    837                         break;
    838                 for (i2 = 1; i2 < NANGLES/2; i2++)
    839                     if (eps[(i+NANGLES-i2)%NANGLES] < 1.5)
    840                         break;
    841                 if (i1 < i2)
    842                     oog_table[i] =
    843                         oog_table[(i+i1)%NANGLES];
    844                 else
    845                     oog_table[i] =
    846                         oog_table[(i+NANGLES-i2)%NANGLES];
    847             }
    848         initialized = 1;
    849     }
    850     i = (int) uv2ang(u, v);		/* look up hue angle */
    851     return (oog_table[i]);
    852 }
    853 
    854 #undef uv2ang
    855 #undef NANGLES
    856 
    857 #if !LOGLUV_PUBLIC
    858 static
    859 #endif
    860 int
    861 uv_encode(double u, double v, int em)	/* encode (u',v') coordinates */
    862 {
    863     register int	vi, ui;
    864 
    865     if (v < UV_VSTART)
    866         return oog_encode(u, v);
    867     vi = itrunc((v - UV_VSTART)*(1./UV_SQSIZ), em);
    868     if (vi >= UV_NVS)
    869         return oog_encode(u, v);
    870     if (u < uv_row[vi].ustart)
    871         return oog_encode(u, v);
    872     ui = itrunc((u - uv_row[vi].ustart)*(1./UV_SQSIZ), em);
    873     if (ui >= uv_row[vi].nus)
    874         return oog_encode(u, v);
    875 
    876     return (uv_row[vi].ncum + ui);
    877 }
    878 
    879 #if !LOGLUV_PUBLIC
    880 static
    881 #endif
    882 int
    883 uv_decode(double *up, double *vp, int c)	/* decode (u',v') index */
    884 {
    885     int	upper, lower;
    886     register int	ui, vi;
    887 
    888     if (c < 0 || c >= UV_NDIVS)
    889         return (-1);
    890     lower = 0;				/* binary search */
    891     upper = UV_NVS;
    892     while (upper - lower > 1) {
    893         vi = (lower + upper) >> 1;
    894         ui = c - uv_row[vi].ncum;
    895         if (ui > 0)
    896             lower = vi;
    897         else if (ui < 0)
    898             upper = vi;
    899         else {
    900             lower = vi;
    901             break;
    902         }
    903     }
    904     vi = lower;
    905     ui = c - uv_row[vi].ncum;
    906     *up = uv_row[vi].ustart + (ui+.5)*UV_SQSIZ;
    907     *vp = UV_VSTART + (vi+.5)*UV_SQSIZ;
    908     return (0);
    909 }
    910 
    911 #if !LOGLUV_PUBLIC
    912 static
    913 #endif
    914 void
    915 LogLuv24toXYZ(uint32 p, float XYZ[3])
    916 {
    917     int	Ce;
    918     double	L, u, v, s, x, y;
    919                     /* decode luminance */
    920     L = LogL10toY(p>>14 & 0x3ff);
    921     if (L <= 0.) {
    922         XYZ[0] = XYZ[1] = XYZ[2] = 0.;
    923         return;
    924     }
    925                     /* decode color */
    926     Ce = p & 0x3fff;
    927     if (uv_decode(&u, &v, Ce) < 0) {
    928         u = U_NEU; v = V_NEU;
    929     }
    930     s = 1./(6.*u - 16.*v + 12.);
    931     x = 9.*u * s;
    932     y = 4.*v * s;
    933                     /* convert to XYZ */
    934     XYZ[0] = (float)(x/y * L);
    935     XYZ[1] = (float)L;
    936     XYZ[2] = (float)((1.-x-y)/y * L);
    937 }
    938 
    939 #if !LOGLUV_PUBLIC
    940 static
    941 #endif
    942 uint32
    943 LogLuv24fromXYZ(float XYZ[3], int em)
    944 {
    945     int	Le, Ce;
    946     double	u, v, s;
    947                     /* encode luminance */
    948     Le = LogL10fromY(XYZ[1], em);
    949                     /* encode color */
    950     s = XYZ[0] + 15.*XYZ[1] + 3.*XYZ[2];
    951     if (!Le || s <= 0.) {
    952         u = U_NEU;
    953         v = V_NEU;
    954     } else {
    955         u = 4.*XYZ[0] / s;
    956         v = 9.*XYZ[1] / s;
    957     }
    958     Ce = uv_encode(u, v, em);
    959     if (Ce < 0)			/* never happens */
    960         Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER);
    961                     /* combine encodings */
    962     return (Le << 14 | Ce);
    963 }
    964 
    965 static void
    966 Luv24toXYZ(LogLuvState* sp, uint8* op, tmsize_t n)
    967 {
    968     uint32* luv = (uint32*) sp->tbuf;
    969     float* xyz = (float*) op;
    970 
    971     while (n-- > 0) {
    972         LogLuv24toXYZ(*luv, xyz);
    973         xyz += 3;
    974         luv++;
    975     }
    976 }
    977 
    978 static void
    979 Luv24toLuv48(LogLuvState* sp, uint8* op, tmsize_t n)
    980 {
    981     uint32* luv = (uint32*) sp->tbuf;
    982     int16* luv3 = (int16*) op;
    983 
    984     while (n-- > 0) {
    985         double u, v;
    986 
    987         *luv3++ = (int16)((*luv >> 12 & 0xffd) + 13314);
    988         if (uv_decode(&u, &v, *luv&0x3fff) < 0) {
    989             u = U_NEU;
    990             v = V_NEU;
    991         }
    992         *luv3++ = (int16)(u * (1L<<15));
    993         *luv3++ = (int16)(v * (1L<<15));
    994         luv++;
    995     }
    996 }
    997 
    998 static void
    999 Luv24toRGB(LogLuvState* sp, uint8* op, tmsize_t n)
   1000 {
   1001     uint32* luv = (uint32*) sp->tbuf;
   1002     uint8* rgb = (uint8*) op;
   1003 
   1004     while (n-- > 0) {
   1005         float xyz[3];
   1006 
   1007         LogLuv24toXYZ(*luv++, xyz);
   1008         XYZtoRGB24(xyz, rgb);
   1009         rgb += 3;
   1010     }
   1011 }
   1012 
   1013 static void
   1014 Luv24fromXYZ(LogLuvState* sp, uint8* op, tmsize_t n)
   1015 {
   1016     uint32* luv = (uint32*) sp->tbuf;
   1017     float* xyz = (float*) op;
   1018 
   1019     while (n-- > 0) {
   1020         *luv++ = LogLuv24fromXYZ(xyz, sp->encode_meth);
   1021         xyz += 3;
   1022     }
   1023 }
   1024 
   1025 static void
   1026 Luv24fromLuv48(LogLuvState* sp, uint8* op, tmsize_t n)
   1027 {
   1028     uint32* luv = (uint32*) sp->tbuf;
   1029     int16* luv3 = (int16*) op;
   1030 
   1031     while (n-- > 0) {
   1032         int Le, Ce;
   1033 
   1034         if (luv3[0] <= 0)
   1035             Le = 0;
   1036         else if (luv3[0] >= (1<<12)+3314)
   1037             Le = (1<<10) - 1;
   1038         else if (sp->encode_meth == SGILOGENCODE_NODITHER)
   1039             Le = (luv3[0]-3314) >> 2;
   1040         else
   1041             Le = itrunc(.25*(luv3[0]-3314.), sp->encode_meth);
   1042 
   1043         Ce = uv_encode((luv3[1]+.5)/(1<<15), (luv3[2]+.5)/(1<<15),
   1044                     sp->encode_meth);
   1045         if (Ce < 0)	/* never happens */
   1046             Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER);
   1047         *luv++ = (uint32)Le << 14 | Ce;
   1048         luv3 += 3;
   1049     }
   1050 }
   1051 
   1052 #if !LOGLUV_PUBLIC
   1053 static
   1054 #endif
   1055 void
   1056 LogLuv32toXYZ(uint32 p, float XYZ[3])
   1057 {
   1058     double	L, u, v, s, x, y;
   1059                     /* decode luminance */
   1060     L = LogL16toY((int)p >> 16);
   1061     if (L <= 0.) {
   1062         XYZ[0] = XYZ[1] = XYZ[2] = 0.;
   1063         return;
   1064     }
   1065                     /* decode color */
   1066     u = 1./UVSCALE * ((p>>8 & 0xff) + .5);
   1067     v = 1./UVSCALE * ((p & 0xff) + .5);
   1068     s = 1./(6.*u - 16.*v + 12.);
   1069     x = 9.*u * s;
   1070     y = 4.*v * s;
   1071                     /* convert to XYZ */
   1072     XYZ[0] = (float)(x/y * L);
   1073     XYZ[1] = (float)L;
   1074     XYZ[2] = (float)((1.-x-y)/y * L);
   1075 }
   1076 
   1077 #if !LOGLUV_PUBLIC
   1078 static
   1079 #endif
   1080 uint32
   1081 LogLuv32fromXYZ(float XYZ[3], int em)
   1082 {
   1083     unsigned int	Le, ue, ve;
   1084     double	u, v, s;
   1085                     /* encode luminance */
   1086     Le = (unsigned int)LogL16fromY(XYZ[1], em);
   1087                     /* encode color */
   1088     s = XYZ[0] + 15.*XYZ[1] + 3.*XYZ[2];
   1089     if (!Le || s <= 0.) {
   1090         u = U_NEU;
   1091         v = V_NEU;
   1092     } else {
   1093         u = 4.*XYZ[0] / s;
   1094         v = 9.*XYZ[1] / s;
   1095     }
   1096     if (u <= 0.) ue = 0;
   1097     else ue = itrunc(UVSCALE*u, em);
   1098     if (ue > 255) ue = 255;
   1099     if (v <= 0.) ve = 0;
   1100     else ve = itrunc(UVSCALE*v, em);
   1101     if (ve > 255) ve = 255;
   1102                     /* combine encodings */
   1103     return (Le << 16 | ue << 8 | ve);
   1104 }
   1105 
   1106 static void
   1107 Luv32toXYZ(LogLuvState* sp, uint8* op, tmsize_t n)
   1108 {
   1109     uint32* luv = (uint32*) sp->tbuf;
   1110     float* xyz = (float*) op;
   1111 
   1112     while (n-- > 0) {
   1113         LogLuv32toXYZ(*luv++, xyz);
   1114         xyz += 3;
   1115     }
   1116 }
   1117 
   1118 static void
   1119 Luv32toLuv48(LogLuvState* sp, uint8* op, tmsize_t n)
   1120 {
   1121     uint32* luv = (uint32*) sp->tbuf;
   1122     int16* luv3 = (int16*) op;
   1123 
   1124     while (n-- > 0) {
   1125         double u, v;
   1126 
   1127         *luv3++ = (int16)(*luv >> 16);
   1128         u = 1./UVSCALE * ((*luv>>8 & 0xff) + .5);
   1129         v = 1./UVSCALE * ((*luv & 0xff) + .5);
   1130         *luv3++ = (int16)(u * (1L<<15));
   1131         *luv3++ = (int16)(v * (1L<<15));
   1132         luv++;
   1133     }
   1134 }
   1135 
   1136 static void
   1137 Luv32toRGB(LogLuvState* sp, uint8* op, tmsize_t n)
   1138 {
   1139     uint32* luv = (uint32*) sp->tbuf;
   1140     uint8* rgb = (uint8*) op;
   1141 
   1142     while (n-- > 0) {
   1143         float xyz[3];
   1144 
   1145         LogLuv32toXYZ(*luv++, xyz);
   1146         XYZtoRGB24(xyz, rgb);
   1147         rgb += 3;
   1148     }
   1149 }
   1150 
   1151 static void
   1152 Luv32fromXYZ(LogLuvState* sp, uint8* op, tmsize_t n)
   1153 {
   1154     uint32* luv = (uint32*) sp->tbuf;
   1155     float* xyz = (float*) op;
   1156 
   1157     while (n-- > 0) {
   1158         *luv++ = LogLuv32fromXYZ(xyz, sp->encode_meth);
   1159         xyz += 3;
   1160     }
   1161 }
   1162 
   1163 static void
   1164 Luv32fromLuv48(LogLuvState* sp, uint8* op, tmsize_t n)
   1165 {
   1166     uint32* luv = (uint32*) sp->tbuf;
   1167     int16* luv3 = (int16*) op;
   1168 
   1169     if (sp->encode_meth == SGILOGENCODE_NODITHER) {
   1170         while (n-- > 0) {
   1171             *luv++ = (uint32)luv3[0] << 16 |
   1172                 (luv3[1]*(uint32)(UVSCALE+.5) >> 7 & 0xff00) |
   1173                 (luv3[2]*(uint32)(UVSCALE+.5) >> 15 & 0xff);
   1174             luv3 += 3;
   1175         }
   1176         return;
   1177     }
   1178     while (n-- > 0) {
   1179         *luv++ = (uint32)luv3[0] << 16 |
   1180     (itrunc(luv3[1]*(UVSCALE/(1<<15)), sp->encode_meth) << 8 & 0xff00) |
   1181         (itrunc(luv3[2]*(UVSCALE/(1<<15)), sp->encode_meth) & 0xff);
   1182         luv3 += 3;
   1183     }
   1184 }
   1185 
   1186 static void
   1187 _logLuvNop(LogLuvState* sp, uint8* op, tmsize_t n)
   1188 {
   1189     (void) sp; (void) op; (void) n;
   1190 }
   1191 
   1192 static int
   1193 LogL16GuessDataFmt(TIFFDirectory *td)
   1194 {
   1195 #define	PACK(s,b,f)	(((b)<<6)|((s)<<3)|(f))
   1196     switch (PACK(td->td_samplesperpixel, td->td_bitspersample, td->td_sampleformat)) {
   1197     case PACK(1, 32, SAMPLEFORMAT_IEEEFP):
   1198         return (SGILOGDATAFMT_FLOAT);
   1199     case PACK(1, 16, SAMPLEFORMAT_VOID):
   1200     case PACK(1, 16, SAMPLEFORMAT_INT):
   1201     case PACK(1, 16, SAMPLEFORMAT_UINT):
   1202         return (SGILOGDATAFMT_16BIT);
   1203     case PACK(1,  8, SAMPLEFORMAT_VOID):
   1204     case PACK(1,  8, SAMPLEFORMAT_UINT):
   1205         return (SGILOGDATAFMT_8BIT);
   1206     }
   1207 #undef PACK
   1208     return (SGILOGDATAFMT_UNKNOWN);
   1209 }
   1210 
   1211 static tmsize_t
   1212 multiply_ms(tmsize_t m1, tmsize_t m2)
   1213 {
   1214     tmsize_t bytes = m1 * m2;
   1215 
   1216     if (m1 && bytes / m1 != m2)
   1217         bytes = 0;
   1218 
   1219     return bytes;
   1220 }
   1221 
   1222 static int
   1223 LogL16InitState(TIFF* tif)
   1224 {
   1225     static const char module[] = "LogL16InitState";
   1226     TIFFDirectory *td = &tif->tif_dir;
   1227     LogLuvState* sp = DecoderState(tif);
   1228 
   1229     assert(sp != NULL);
   1230     assert(td->td_photometric == PHOTOMETRIC_LOGL);
   1231 
   1232     /* for some reason, we can't do this in TIFFInitLogL16 */
   1233     if (sp->user_datafmt == SGILOGDATAFMT_UNKNOWN)
   1234         sp->user_datafmt = LogL16GuessDataFmt(td);
   1235     switch (sp->user_datafmt) {
   1236     case SGILOGDATAFMT_FLOAT:
   1237         sp->pixel_size = sizeof (float);
   1238         break;
   1239     case SGILOGDATAFMT_16BIT:
   1240         sp->pixel_size = sizeof (int16);
   1241         break;
   1242     case SGILOGDATAFMT_8BIT:
   1243         sp->pixel_size = sizeof (uint8);
   1244         break;
   1245     default:
   1246         TIFFErrorExt(tif->tif_clientdata, module,
   1247             "No support for converting user data format to LogL");
   1248         return (0);
   1249     }
   1250         if( isTiled(tif) )
   1251             sp->tbuflen = multiply_ms(td->td_tilewidth, td->td_tilelength);
   1252         else
   1253             sp->tbuflen = multiply_ms(td->td_imagewidth, td->td_rowsperstrip);
   1254     if (multiply_ms(sp->tbuflen, sizeof (int16)) == 0 ||
   1255         (sp->tbuf = (uint8*) _TIFFmalloc(sp->tbuflen * sizeof (int16))) == NULL) {
   1256         TIFFErrorExt(tif->tif_clientdata, module, "No space for SGILog translation buffer");
   1257         return (0);
   1258     }
   1259     return (1);
   1260 }
   1261 
   1262 static int
   1263 LogLuvGuessDataFmt(TIFFDirectory *td)
   1264 {
   1265     int guess;
   1266 
   1267     /*
   1268      * If the user didn't tell us their datafmt,
   1269      * take our best guess from the bitspersample.
   1270      */
   1271 #define	PACK(a,b)	(((a)<<3)|(b))
   1272     switch (PACK(td->td_bitspersample, td->td_sampleformat)) {
   1273     case PACK(32, SAMPLEFORMAT_IEEEFP):
   1274         guess = SGILOGDATAFMT_FLOAT;
   1275         break;
   1276     case PACK(32, SAMPLEFORMAT_VOID):
   1277     case PACK(32, SAMPLEFORMAT_UINT):
   1278     case PACK(32, SAMPLEFORMAT_INT):
   1279         guess = SGILOGDATAFMT_RAW;
   1280         break;
   1281     case PACK(16, SAMPLEFORMAT_VOID):
   1282     case PACK(16, SAMPLEFORMAT_INT):
   1283     case PACK(16, SAMPLEFORMAT_UINT):
   1284         guess = SGILOGDATAFMT_16BIT;
   1285         break;
   1286     case PACK( 8, SAMPLEFORMAT_VOID):
   1287     case PACK( 8, SAMPLEFORMAT_UINT):
   1288         guess = SGILOGDATAFMT_8BIT;
   1289         break;
   1290     default:
   1291         guess = SGILOGDATAFMT_UNKNOWN;
   1292         break;
   1293 #undef PACK
   1294     }
   1295     /*
   1296      * Double-check samples per pixel.
   1297      */
   1298     switch (td->td_samplesperpixel) {
   1299     case 1:
   1300         if (guess != SGILOGDATAFMT_RAW)
   1301             guess = SGILOGDATAFMT_UNKNOWN;
   1302         break;
   1303     case 3:
   1304         if (guess == SGILOGDATAFMT_RAW)
   1305             guess = SGILOGDATAFMT_UNKNOWN;
   1306         break;
   1307     default:
   1308         guess = SGILOGDATAFMT_UNKNOWN;
   1309         break;
   1310     }
   1311     return (guess);
   1312 }
   1313 
   1314 static int
   1315 LogLuvInitState(TIFF* tif)
   1316 {
   1317     static const char module[] = "LogLuvInitState";
   1318     TIFFDirectory* td = &tif->tif_dir;
   1319     LogLuvState* sp = DecoderState(tif);
   1320 
   1321     assert(sp != NULL);
   1322     assert(td->td_photometric == PHOTOMETRIC_LOGLUV);
   1323 
   1324     /* for some reason, we can't do this in TIFFInitLogLuv */
   1325     if (td->td_planarconfig != PLANARCONFIG_CONTIG) {
   1326         TIFFErrorExt(tif->tif_clientdata, module,
   1327             "SGILog compression cannot handle non-contiguous data");
   1328         return (0);
   1329     }
   1330     if (sp->user_datafmt == SGILOGDATAFMT_UNKNOWN)
   1331         sp->user_datafmt = LogLuvGuessDataFmt(td);
   1332     switch (sp->user_datafmt) {
   1333     case SGILOGDATAFMT_FLOAT:
   1334         sp->pixel_size = 3*sizeof (float);
   1335         break;
   1336     case SGILOGDATAFMT_16BIT:
   1337         sp->pixel_size = 3*sizeof (int16);
   1338         break;
   1339     case SGILOGDATAFMT_RAW:
   1340         sp->pixel_size = sizeof (uint32);
   1341         break;
   1342     case SGILOGDATAFMT_8BIT:
   1343         sp->pixel_size = 3*sizeof (uint8);
   1344         break;
   1345     default:
   1346         TIFFErrorExt(tif->tif_clientdata, module,
   1347             "No support for converting user data format to LogLuv");
   1348         return (0);
   1349     }
   1350         if( isTiled(tif) )
   1351             sp->tbuflen = multiply_ms(td->td_tilewidth, td->td_tilelength);
   1352         else
   1353             sp->tbuflen = multiply_ms(td->td_imagewidth, td->td_rowsperstrip);
   1354     if (multiply_ms(sp->tbuflen, sizeof (uint32)) == 0 ||
   1355         (sp->tbuf = (uint8*) _TIFFmalloc(sp->tbuflen * sizeof (uint32))) == NULL) {
   1356         TIFFErrorExt(tif->tif_clientdata, module, "No space for SGILog translation buffer");
   1357         return (0);
   1358     }
   1359     return (1);
   1360 }
   1361 
   1362 static int
   1363 LogLuvFixupTags(TIFF* tif)
   1364 {
   1365     (void) tif;
   1366     return (1);
   1367 }
   1368 
   1369 static int
   1370 LogLuvSetupDecode(TIFF* tif)
   1371 {
   1372     static const char module[] = "LogLuvSetupDecode";
   1373     LogLuvState* sp = DecoderState(tif);
   1374     TIFFDirectory* td = &tif->tif_dir;
   1375 
   1376     tif->tif_postdecode = _TIFFNoPostDecode;
   1377     switch (td->td_photometric) {
   1378     case PHOTOMETRIC_LOGLUV:
   1379         if (!LogLuvInitState(tif))
   1380             break;
   1381         if (td->td_compression == COMPRESSION_SGILOG24) {
   1382             tif->tif_decoderow = LogLuvDecode24;
   1383             switch (sp->user_datafmt) {
   1384             case SGILOGDATAFMT_FLOAT:
   1385                 sp->tfunc = Luv24toXYZ;
   1386                 break;
   1387             case SGILOGDATAFMT_16BIT:
   1388                 sp->tfunc = Luv24toLuv48;
   1389                 break;
   1390             case SGILOGDATAFMT_8BIT:
   1391                 sp->tfunc = Luv24toRGB;
   1392                 break;
   1393             }
   1394         } else {
   1395             tif->tif_decoderow = LogLuvDecode32;
   1396             switch (sp->user_datafmt) {
   1397             case SGILOGDATAFMT_FLOAT:
   1398                 sp->tfunc = Luv32toXYZ;
   1399                 break;
   1400             case SGILOGDATAFMT_16BIT:
   1401                 sp->tfunc = Luv32toLuv48;
   1402                 break;
   1403             case SGILOGDATAFMT_8BIT:
   1404                 sp->tfunc = Luv32toRGB;
   1405                 break;
   1406             }
   1407         }
   1408         return (1);
   1409     case PHOTOMETRIC_LOGL:
   1410         if (!LogL16InitState(tif))
   1411             break;
   1412         tif->tif_decoderow = LogL16Decode;
   1413         switch (sp->user_datafmt) {
   1414         case SGILOGDATAFMT_FLOAT:
   1415             sp->tfunc = L16toY;
   1416             break;
   1417         case SGILOGDATAFMT_8BIT:
   1418             sp->tfunc = L16toGry;
   1419             break;
   1420         }
   1421         return (1);
   1422     default:
   1423         TIFFErrorExt(tif->tif_clientdata, module,
   1424             "Inappropriate photometric interpretation %d for SGILog compression; %s",
   1425             td->td_photometric, "must be either LogLUV or LogL");
   1426         break;
   1427     }
   1428     return (0);
   1429 }
   1430 
   1431 static int
   1432 LogLuvSetupEncode(TIFF* tif)
   1433 {
   1434     static const char module[] = "LogLuvSetupEncode";
   1435     LogLuvState* sp = EncoderState(tif);
   1436     TIFFDirectory* td = &tif->tif_dir;
   1437 
   1438     switch (td->td_photometric) {
   1439     case PHOTOMETRIC_LOGLUV:
   1440         if (!LogLuvInitState(tif))
   1441             break;
   1442         if (td->td_compression == COMPRESSION_SGILOG24) {
   1443             tif->tif_encoderow = LogLuvEncode24;
   1444             switch (sp->user_datafmt) {
   1445             case SGILOGDATAFMT_FLOAT:
   1446                 sp->tfunc = Luv24fromXYZ;
   1447                 break;
   1448             case SGILOGDATAFMT_16BIT:
   1449                 sp->tfunc = Luv24fromLuv48;
   1450                 break;
   1451             case SGILOGDATAFMT_RAW:
   1452                 break;
   1453             default:
   1454                 goto notsupported;
   1455             }
   1456         } else {
   1457             tif->tif_encoderow = LogLuvEncode32;
   1458             switch (sp->user_datafmt) {
   1459             case SGILOGDATAFMT_FLOAT:
   1460                 sp->tfunc = Luv32fromXYZ;
   1461                 break;
   1462             case SGILOGDATAFMT_16BIT:
   1463                 sp->tfunc = Luv32fromLuv48;
   1464                 break;
   1465             case SGILOGDATAFMT_RAW:
   1466                 break;
   1467             default:
   1468                 goto notsupported;
   1469             }
   1470         }
   1471         break;
   1472     case PHOTOMETRIC_LOGL:
   1473         if (!LogL16InitState(tif))
   1474             break;
   1475         tif->tif_encoderow = LogL16Encode;
   1476         switch (sp->user_datafmt) {
   1477         case SGILOGDATAFMT_FLOAT:
   1478             sp->tfunc = L16fromY;
   1479             break;
   1480         case SGILOGDATAFMT_16BIT:
   1481             break;
   1482         default:
   1483             goto notsupported;
   1484         }
   1485         break;
   1486     default:
   1487         TIFFErrorExt(tif->tif_clientdata, module,
   1488             "Inappropriate photometric interpretation %d for SGILog compression; %s",
   1489             td->td_photometric, "must be either LogLUV or LogL");
   1490         break;
   1491     }
   1492     return (1);
   1493 notsupported:
   1494     TIFFErrorExt(tif->tif_clientdata, module,
   1495         "SGILog compression supported only for %s, or raw data",
   1496         td->td_photometric == PHOTOMETRIC_LOGL ? "Y, L" : "XYZ, Luv");
   1497     return (0);
   1498 }
   1499 
   1500 static void
   1501 LogLuvClose(TIFF* tif)
   1502 {
   1503     TIFFDirectory *td = &tif->tif_dir;
   1504 
   1505     /*
   1506      * For consistency, we always want to write out the same
   1507      * bitspersample and sampleformat for our TIFF file,
   1508      * regardless of the data format being used by the application.
   1509      * Since this routine is called after tags have been set but
   1510      * before they have been recorded in the file, we reset them here.
   1511      */
   1512     td->td_samplesperpixel =
   1513         (td->td_photometric == PHOTOMETRIC_LOGL) ? 1 : 3;
   1514     td->td_bitspersample = 16;
   1515     td->td_sampleformat = SAMPLEFORMAT_INT;
   1516 }
   1517 
   1518 static void
   1519 LogLuvCleanup(TIFF* tif)
   1520 {
   1521     LogLuvState* sp = (LogLuvState *)tif->tif_data;
   1522 
   1523     assert(sp != 0);
   1524 
   1525     tif->tif_tagmethods.vgetfield = sp->vgetparent;
   1526     tif->tif_tagmethods.vsetfield = sp->vsetparent;
   1527 
   1528     if (sp->tbuf)
   1529         _TIFFfree(sp->tbuf);
   1530     _TIFFfree(sp);
   1531     tif->tif_data = NULL;
   1532 
   1533     _TIFFSetDefaultCompressionState(tif);
   1534 }
   1535 
   1536 static int
   1537 LogLuvVSetField(TIFF* tif, uint32 tag, va_list ap)
   1538 {
   1539     static const char module[] = "LogLuvVSetField";
   1540     LogLuvState* sp = DecoderState(tif);
   1541     int bps, fmt;
   1542 
   1543     switch (tag) {
   1544     case TIFFTAG_SGILOGDATAFMT:
   1545         sp->user_datafmt = (int) va_arg(ap, int);
   1546         /*
   1547          * Tweak the TIFF header so that the rest of libtiff knows what
   1548          * size of data will be passed between app and library, and
   1549          * assume that the app knows what it is doing and is not
   1550          * confused by these header manipulations...
   1551          */
   1552         switch (sp->user_datafmt) {
   1553         case SGILOGDATAFMT_FLOAT:
   1554             bps = 32, fmt = SAMPLEFORMAT_IEEEFP;
   1555             break;
   1556         case SGILOGDATAFMT_16BIT:
   1557             bps = 16, fmt = SAMPLEFORMAT_INT;
   1558             break;
   1559         case SGILOGDATAFMT_RAW:
   1560             bps = 32, fmt = SAMPLEFORMAT_UINT;
   1561             TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
   1562             break;
   1563         case SGILOGDATAFMT_8BIT:
   1564             bps = 8, fmt = SAMPLEFORMAT_UINT;
   1565             break;
   1566         default:
   1567             TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
   1568                 "Unknown data format %d for LogLuv compression",
   1569                 sp->user_datafmt);
   1570             return (0);
   1571         }
   1572         TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps);
   1573         TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, fmt);
   1574         /*
   1575          * Must recalculate sizes should bits/sample change.
   1576          */
   1577         tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tmsize_t) -1;
   1578         tif->tif_scanlinesize = TIFFScanlineSize(tif);
   1579         return (1);
   1580     case TIFFTAG_SGILOGENCODE:
   1581         sp->encode_meth = (int) va_arg(ap, int);
   1582         if (sp->encode_meth != SGILOGENCODE_NODITHER &&
   1583             sp->encode_meth != SGILOGENCODE_RANDITHER) {
   1584             TIFFErrorExt(tif->tif_clientdata, module,
   1585                 "Unknown encoding %d for LogLuv compression",
   1586                 sp->encode_meth);
   1587             return (0);
   1588         }
   1589         return (1);
   1590     default:
   1591         return (*sp->vsetparent)(tif, tag, ap);
   1592     }
   1593 }
   1594 
   1595 static int
   1596 LogLuvVGetField(TIFF* tif, uint32 tag, va_list ap)
   1597 {
   1598     LogLuvState *sp = (LogLuvState *)tif->tif_data;
   1599 
   1600     switch (tag) {
   1601     case TIFFTAG_SGILOGDATAFMT:
   1602         *va_arg(ap, int*) = sp->user_datafmt;
   1603         return (1);
   1604     default:
   1605         return (*sp->vgetparent)(tif, tag, ap);
   1606     }
   1607 }
   1608 
   1609 static const TIFFField LogLuvFields[] = {
   1610     { TIFFTAG_SGILOGDATAFMT, 0, 0, TIFF_SHORT, 0, TIFF_SETGET_INT, TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "SGILogDataFmt", NULL},
   1611     { TIFFTAG_SGILOGENCODE, 0, 0, TIFF_SHORT, 0, TIFF_SETGET_INT, TIFF_SETGET_UNDEFINED, FIELD_PSEUDO, TRUE, FALSE, "SGILogEncode", NULL}
   1612 };
   1613 
   1614 int
   1615 TIFFInitSGILog(TIFF* tif, int scheme)
   1616 {
   1617     static const char module[] = "TIFFInitSGILog";
   1618     LogLuvState* sp;
   1619 
   1620     assert(scheme == COMPRESSION_SGILOG24 || scheme == COMPRESSION_SGILOG);
   1621 
   1622     /*
   1623      * Merge codec-specific tag information.
   1624      */
   1625     if (!_TIFFMergeFields(tif, LogLuvFields,
   1626                   TIFFArrayCount(LogLuvFields))) {
   1627         TIFFErrorExt(tif->tif_clientdata, module,
   1628             "Merging SGILog codec-specific tags failed");
   1629         return 0;
   1630     }
   1631 
   1632     /*
   1633      * Allocate state block so tag methods have storage to record values.
   1634      */
   1635     tif->tif_data = (uint8*) _TIFFmalloc(sizeof (LogLuvState));
   1636     if (tif->tif_data == NULL)
   1637         goto bad;
   1638     sp = (LogLuvState*) tif->tif_data;
   1639     _TIFFmemset((void*)sp, 0, sizeof (*sp));
   1640     sp->user_datafmt = SGILOGDATAFMT_UNKNOWN;
   1641     sp->encode_meth = (scheme == COMPRESSION_SGILOG24) ?
   1642         SGILOGENCODE_RANDITHER : SGILOGENCODE_NODITHER;
   1643     sp->tfunc = _logLuvNop;
   1644 
   1645     /*
   1646      * Install codec methods.
   1647      * NB: tif_decoderow & tif_encoderow are filled
   1648      *     in at setup time.
   1649      */
   1650     tif->tif_fixuptags = LogLuvFixupTags;
   1651     tif->tif_setupdecode = LogLuvSetupDecode;
   1652     tif->tif_decodestrip = LogLuvDecodeStrip;
   1653     tif->tif_decodetile = LogLuvDecodeTile;
   1654     tif->tif_setupencode = LogLuvSetupEncode;
   1655     tif->tif_encodestrip = LogLuvEncodeStrip;
   1656     tif->tif_encodetile = LogLuvEncodeTile;
   1657     tif->tif_close = LogLuvClose;
   1658     tif->tif_cleanup = LogLuvCleanup;
   1659 
   1660     /*
   1661      * Override parent get/set field methods.
   1662      */
   1663     sp->vgetparent = tif->tif_tagmethods.vgetfield;
   1664     tif->tif_tagmethods.vgetfield = LogLuvVGetField;   /* hook for codec tags */
   1665     sp->vsetparent = tif->tif_tagmethods.vsetfield;
   1666     tif->tif_tagmethods.vsetfield = LogLuvVSetField;   /* hook for codec tags */
   1667 
   1668     return (1);
   1669 bad:
   1670     TIFFErrorExt(tif->tif_clientdata, module,
   1671              "%s: No space for LogLuv state block", tif->tif_name);
   1672     return (0);
   1673 }
   1674 #endif /* LOGLUV_SUPPORT */
   1675 
   1676 /* vim: set ts=8 sts=8 sw=8 noet: */
   1677 /*
   1678  * Local Variables:
   1679  * mode: c
   1680  * c-basic-offset: 8
   1681  * fill-column: 78
   1682  * End:
   1683  */
   1684