ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

tif_luv.c
Go to the documentation of this file.
00001 /* $Id: tif_luv.c,v 1.17.2.4 2010-06-08 18:50:42 bfriesen Exp $ */
00002 
00003 /*
00004  * Copyright (c) 1997 Greg Ward Larson
00005  * Copyright (c) 1997 Silicon Graphics, Inc.
00006  *
00007  * Permission to use, copy, modify, distribute, and sell this software and 
00008  * its documentation for any purpose is hereby granted without fee, provided
00009  * that (i) the above copyright notices and this permission notice appear in
00010  * all copies of the software and related documentation, and (ii) the names of
00011  * Sam Leffler, Greg Larson and Silicon Graphics may not be used in any
00012  * advertising or publicity relating to the software without the specific,
00013  * prior written permission of Sam Leffler, Greg Larson and Silicon Graphics.
00014  * 
00015  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
00016  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
00017  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
00018  * 
00019  * IN NO EVENT SHALL SAM LEFFLER, GREG LARSON OR SILICON GRAPHICS BE LIABLE
00020  * FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
00021  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
00022  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
00023  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
00024  * OF THIS SOFTWARE.
00025  */
00026 
00027 #include "tiffiop.h"
00028 #ifdef LOGLUV_SUPPORT
00029 
00030 /*
00031  * TIFF Library.
00032  * LogLuv compression support for high dynamic range images.
00033  *
00034  * Contributed by Greg Larson.
00035  *
00036  * LogLuv image support uses the TIFF library to store 16 or 10-bit
00037  * log luminance values with 8 bits each of u and v or a 14-bit index.
00038  *
00039  * The codec can take as input and produce as output 32-bit IEEE float values 
00040  * as well as 16-bit integer values.  A 16-bit luminance is interpreted
00041  * as a sign bit followed by a 15-bit integer that is converted
00042  * to and from a linear magnitude using the transformation:
00043  *
00044  *  L = 2^( (Le+.5)/256 - 64 )      # real from 15-bit
00045  *
00046  *  Le = floor( 256*(log2(L) + 64) )    # 15-bit from real
00047  *
00048  * The actual conversion to world luminance units in candelas per sq. meter
00049  * requires an additional multiplier, which is stored in the TIFFTAG_STONITS.
00050  * This value is usually set such that a reasonable exposure comes from
00051  * clamping decoded luminances above 1 to 1 in the displayed image.
00052  *
00053  * The 16-bit values for u and v may be converted to real values by dividing
00054  * each by 32768.  (This allows for negative values, which aren't useful as
00055  * far as we know, but are left in case of future improvements in human
00056  * color vision.)
00057  *
00058  * Conversion from (u,v), which is actually the CIE (u',v') system for
00059  * you color scientists, is accomplished by the following transformation:
00060  *
00061  *  u = 4*x / (-2*x + 12*y + 3)
00062  *  v = 9*y / (-2*x + 12*y + 3)
00063  *
00064  *  x = 9*u / (6*u - 16*v + 12)
00065  *  y = 4*v / (6*u - 16*v + 12)
00066  *
00067  * This process is greatly simplified by passing 32-bit IEEE floats
00068  * for each of three CIE XYZ coordinates.  The codec then takes care
00069  * of conversion to and from LogLuv, though the application is still
00070  * responsible for interpreting the TIFFTAG_STONITS calibration factor.
00071  *
00072  * By definition, a CIE XYZ vector of [1 1 1] corresponds to a neutral white
00073  * point of (x,y)=(1/3,1/3).  However, most color systems assume some other
00074  * white point, such as D65, and an absolute color conversion to XYZ then
00075  * to another color space with a different white point may introduce an
00076  * unwanted color cast to the image.  It is often desirable, therefore, to
00077  * perform a white point conversion that maps the input white to [1 1 1]
00078  * in XYZ, then record the original white point using the TIFFTAG_WHITEPOINT
00079  * tag value.  A decoder that demands absolute color calibration may use
00080  * this white point tag to get back the original colors, but usually it
00081  * will be ignored and the new white point will be used instead that
00082  * matches the output color space.
00083  *
00084  * Pixel information is compressed into one of two basic encodings, depending
00085  * on the setting of the compression tag, which is one of COMPRESSION_SGILOG
00086  * or COMPRESSION_SGILOG24.  For COMPRESSION_SGILOG, greyscale data is
00087  * stored as:
00088  *
00089  *   1       15
00090  *  |-+---------------|
00091  *
00092  * COMPRESSION_SGILOG color data is stored as:
00093  *
00094  *   1       15           8        8
00095  *  |-+---------------|--------+--------|
00096  *   S       Le           ue       ve
00097  *
00098  * For the 24-bit COMPRESSION_SGILOG24 color format, the data is stored as:
00099  *
00100  *       10           14
00101  *  |----------|--------------|
00102  *       Le'          Ce
00103  *
00104  * There is no sign bit in the 24-bit case, and the (u,v) chromaticity is
00105  * encoded as an index for optimal color resolution.  The 10 log bits are
00106  * defined by the following conversions:
00107  *
00108  *  L = 2^((Le'+.5)/64 - 12)        # real from 10-bit
00109  *
00110  *  Le' = floor( 64*(log2(L) + 12) )    # 10-bit from real
00111  *
00112  * The 10 bits of the smaller format may be converted into the 15 bits of
00113  * the larger format by multiplying by 4 and adding 13314.  Obviously,
00114  * a smaller range of magnitudes is covered (about 5 orders of magnitude
00115  * instead of 38), and the lack of a sign bit means that negative luminances
00116  * are not allowed.  (Well, they aren't allowed in the real world, either,
00117  * but they are useful for certain types of image processing.)
00118  *
00119  * The desired user format is controlled by the setting the internal
00120  * pseudo tag TIFFTAG_SGILOGDATAFMT to one of:
00121  *  SGILOGDATAFMT_FLOAT       = IEEE 32-bit float XYZ values
00122  *  SGILOGDATAFMT_16BIT       = 16-bit integer encodings of logL, u and v
00123  * Raw data i/o is also possible using:
00124  *  SGILOGDATAFMT_RAW         = 32-bit unsigned integer with encoded pixel
00125  * In addition, the following decoding is provided for ease of display:
00126  *  SGILOGDATAFMT_8BIT        = 8-bit default RGB gamma-corrected values
00127  *
00128  * For grayscale images, we provide the following data formats:
00129  *  SGILOGDATAFMT_FLOAT       = IEEE 32-bit float Y values
00130  *  SGILOGDATAFMT_16BIT       = 16-bit integer w/ encoded luminance
00131  *  SGILOGDATAFMT_8BIT        = 8-bit gray monitor values
00132  *
00133  * Note that the COMPRESSION_SGILOG applies a simple run-length encoding
00134  * scheme by separating the logL, u and v bytes for each row and applying
00135  * a PackBits type of compression.  Since the 24-bit encoding is not
00136  * adaptive, the 32-bit color format takes less space in many cases.
00137  *
00138  * Further control is provided over the conversion from higher-resolution
00139  * formats to final encoded values through the pseudo tag
00140  * TIFFTAG_SGILOGENCODE:
00141  *  SGILOGENCODE_NODITHER     = do not dither encoded values
00142  *  SGILOGENCODE_RANDITHER    = apply random dithering during encoding
00143  *
00144  * The default value of this tag is SGILOGENCODE_NODITHER for
00145  * COMPRESSION_SGILOG to maximize run-length encoding and
00146  * SGILOGENCODE_RANDITHER for COMPRESSION_SGILOG24 to turn
00147  * quantization errors into noise.
00148  */
00149 
00150 #include <stdio.h>
00151 #include <stdlib.h>
00152 #include <math.h>
00153 
00154 /*
00155  * State block for each open TIFF
00156  * file using LogLuv compression/decompression.
00157  */
00158 typedef struct logLuvState LogLuvState;
00159 
00160 struct logLuvState {
00161     int         user_datafmt;   /* user data format */
00162     int         encode_meth;    /* encoding method */
00163     int         pixel_size; /* bytes per pixel */
00164 
00165     tidata_t*       tbuf;       /* translation buffer */
00166     int         tbuflen;    /* buffer length */
00167     void (*tfunc)(LogLuvState*, tidata_t, int);
00168 
00169     TIFFVSetMethod      vgetparent; /* super-class method */
00170     TIFFVSetMethod      vsetparent; /* super-class method */
00171 };
00172 
00173 #define DecoderState(tif)   ((LogLuvState*) (tif)->tif_data)
00174 #define EncoderState(tif)   ((LogLuvState*) (tif)->tif_data)
00175 
00176 #define SGILOGDATAFMT_UNKNOWN   -1
00177 
00178 #define MINRUN      4   /* minimum run length */
00179 
00180 /*
00181  * Decode a string of 16-bit gray pixels.
00182  */
00183 static int
00184 LogL16Decode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
00185 {
00186     LogLuvState* sp = DecoderState(tif);
00187     int shft, i, npixels;
00188     unsigned char* bp;
00189     int16* tp;
00190     int16 b;
00191     int cc, rc;
00192 
00193     assert(s == 0);
00194     assert(sp != NULL);
00195 
00196     npixels = occ / sp->pixel_size;
00197 
00198     if (sp->user_datafmt == SGILOGDATAFMT_16BIT)
00199         tp = (int16*) op;
00200     else {
00201         assert(sp->tbuflen >= npixels);
00202         tp = (int16*) sp->tbuf;
00203     }
00204     _TIFFmemset((tdata_t) tp, 0, npixels*sizeof (tp[0]));
00205 
00206     bp = (unsigned char*) tif->tif_rawcp;
00207     cc = tif->tif_rawcc;
00208                     /* get each byte string */
00209     for (shft = 2*8; (shft -= 8) >= 0; ) {
00210         for (i = 0; i < npixels && cc > 0; )
00211             if (*bp >= 128) {       /* run */
00212                 rc = *bp++ + (2-128);
00213                 b = (int16)(*bp++ << shft);
00214                 cc -= 2;
00215                 while (rc-- && i < npixels)
00216                     tp[i++] |= b;
00217             } else {            /* non-run */
00218                 rc = *bp++;     /* nul is noop */
00219                 while (--cc && rc-- && i < npixels)
00220                     tp[i++] |= (int16)*bp++ << shft;
00221             }
00222         if (i != npixels) {
00223             TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
00224         "LogL16Decode: Not enough data at row %d (short %d pixels)",
00225                 tif->tif_row, npixels - i);
00226             tif->tif_rawcp = (tidata_t) bp;
00227             tif->tif_rawcc = cc;
00228             return (0);
00229         }
00230     }
00231     (*sp->tfunc)(sp, op, npixels);
00232     tif->tif_rawcp = (tidata_t) bp;
00233     tif->tif_rawcc = cc;
00234     return (1);
00235 }
00236 
00237 /*
00238  * Decode a string of 24-bit pixels.
00239  */
00240 static int
00241 LogLuvDecode24(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
00242 {
00243     LogLuvState* sp = DecoderState(tif);
00244     int cc, i, npixels;
00245     unsigned char* bp;
00246     uint32* tp;
00247 
00248     assert(s == 0);
00249     assert(sp != NULL);
00250 
00251     npixels = occ / sp->pixel_size;
00252 
00253     if (sp->user_datafmt == SGILOGDATAFMT_RAW)
00254         tp = (uint32 *)op;
00255     else {
00256         assert(sp->tbuflen >= npixels);
00257         tp = (uint32 *) sp->tbuf;
00258     }
00259                     /* copy to array of uint32 */
00260     bp = (unsigned char*) tif->tif_rawcp;
00261     cc = tif->tif_rawcc;
00262     for (i = 0; i < npixels && cc > 0; i++) {
00263         tp[i] = bp[0] << 16 | bp[1] << 8 | bp[2];
00264         bp += 3;
00265         cc -= 3;
00266     }
00267     tif->tif_rawcp = (tidata_t) bp;
00268     tif->tif_rawcc = cc;
00269     if (i != npixels) {
00270         TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
00271         "LogLuvDecode24: Not enough data at row %d (short %d pixels)",
00272             tif->tif_row, npixels - i);
00273         return (0);
00274     }
00275     (*sp->tfunc)(sp, op, npixels);
00276     return (1);
00277 }
00278 
00279 /*
00280  * Decode a string of 32-bit pixels.
00281  */
00282 static int
00283 LogLuvDecode32(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s)
00284 {
00285     LogLuvState* sp;
00286     int shft, i, npixels;
00287     unsigned char* bp;
00288     uint32* tp;
00289     uint32 b;
00290     int cc, rc;
00291 
00292     assert(s == 0);
00293     sp = DecoderState(tif);
00294     assert(sp != NULL);
00295 
00296     npixels = occ / sp->pixel_size;
00297 
00298     if (sp->user_datafmt == SGILOGDATAFMT_RAW)
00299         tp = (uint32*) op;
00300     else {
00301         assert(sp->tbuflen >= npixels);
00302         tp = (uint32*) sp->tbuf;
00303     }
00304     _TIFFmemset((tdata_t) tp, 0, npixels*sizeof (tp[0]));
00305 
00306     bp = (unsigned char*) tif->tif_rawcp;
00307     cc = tif->tif_rawcc;
00308                     /* get each byte string */
00309     for (shft = 4*8; (shft -= 8) >= 0; ) {
00310         for (i = 0; i < npixels && cc > 0; )
00311             if (*bp >= 128) {       /* run */
00312                 rc = *bp++ + (2-128);
00313                 b = (uint32)*bp++ << shft;
00314                 cc -= 2;
00315                 while (rc-- && i < npixels)
00316                     tp[i++] |= b;
00317             } else {            /* non-run */
00318                 rc = *bp++;     /* nul is noop */
00319                 while (--cc && rc-- && i < npixels)
00320                     tp[i++] |= (uint32)*bp++ << shft;
00321             }
00322         if (i != npixels) {
00323             TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
00324         "LogLuvDecode32: Not enough data at row %d (short %d pixels)",
00325                 tif->tif_row, npixels - i);
00326             tif->tif_rawcp = (tidata_t) bp;
00327             tif->tif_rawcc = cc;
00328             return (0);
00329         }
00330     }
00331     (*sp->tfunc)(sp, op, npixels);
00332     tif->tif_rawcp = (tidata_t) bp;
00333     tif->tif_rawcc = cc;
00334     return (1);
00335 }
00336 
00337 /*
00338  * Decode a strip of pixels.  We break it into rows to
00339  * maintain synchrony with the encode algorithm, which
00340  * is row by row.
00341  */
00342 static int
00343 LogLuvDecodeStrip(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
00344 {
00345     tsize_t rowlen = TIFFScanlineSize(tif);
00346 
00347     assert(cc%rowlen == 0);
00348     while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s))
00349         bp += rowlen, cc -= rowlen;
00350     return (cc == 0);
00351 }
00352 
00353 /*
00354  * Decode a tile of pixels.  We break it into rows to
00355  * maintain synchrony with the encode algorithm, which
00356  * is row by row.
00357  */
00358 static int
00359 LogLuvDecodeTile(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
00360 {
00361     tsize_t rowlen = TIFFTileRowSize(tif);
00362 
00363     assert(cc%rowlen == 0);
00364     while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s))
00365         bp += rowlen, cc -= rowlen;
00366     return (cc == 0);
00367 }
00368 
00369 /*
00370  * Encode a row of 16-bit pixels.
00371  */
00372 static int
00373 LogL16Encode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
00374 {
00375     LogLuvState* sp = EncoderState(tif);
00376     int shft, i, j, npixels;
00377     tidata_t op;
00378     int16* tp;
00379     int16 b;
00380     int occ, rc=0, mask, beg;
00381 
00382     assert(s == 0);
00383     assert(sp != NULL);
00384     npixels = cc / sp->pixel_size;
00385 
00386     if (sp->user_datafmt == SGILOGDATAFMT_16BIT)
00387         tp = (int16*) bp;
00388     else {
00389         tp = (int16*) sp->tbuf;
00390         assert(sp->tbuflen >= npixels);
00391         (*sp->tfunc)(sp, bp, npixels);
00392     }
00393                     /* compress each byte string */
00394     op = tif->tif_rawcp;
00395     occ = tif->tif_rawdatasize - tif->tif_rawcc;
00396     for (shft = 2*8; (shft -= 8) >= 0; )
00397         for (i = 0; i < npixels; i += rc) {
00398             if (occ < 4) {
00399                 tif->tif_rawcp = op;
00400                 tif->tif_rawcc = tif->tif_rawdatasize - occ;
00401                 if (!TIFFFlushData1(tif))
00402                     return (-1);
00403                 op = tif->tif_rawcp;
00404                 occ = tif->tif_rawdatasize - tif->tif_rawcc;
00405             }
00406             mask = 0xff << shft;        /* find next run */
00407             for (beg = i; beg < npixels; beg += rc) {
00408                 b = (int16) (tp[beg] & mask);
00409                 rc = 1;
00410                 while (rc < 127+2 && beg+rc < npixels &&
00411                         (tp[beg+rc] & mask) == b)
00412                     rc++;
00413                 if (rc >= MINRUN)
00414                     break;      /* long enough */
00415             }
00416             if (beg-i > 1 && beg-i < MINRUN) {
00417                 b = (int16) (tp[i] & mask);/*check short run */
00418                 j = i+1;
00419                 while ((tp[j++] & mask) == b)
00420                                     if (j == beg) {
00421                                         *op++ = (tidataval_t)(128-2+j-i);
00422                                         *op++ = (tidataval_t) (b >> shft);
00423                                         occ -= 2;
00424                                         i = beg;
00425                                         break;
00426                                     }
00427             }
00428             while (i < beg) {       /* write out non-run */
00429                 if ((j = beg-i) > 127) j = 127;
00430                 if (occ < j+3) {
00431                                     tif->tif_rawcp = op;
00432                                     tif->tif_rawcc = tif->tif_rawdatasize - occ;
00433                                     if (!TIFFFlushData1(tif))
00434                                         return (-1);
00435                                     op = tif->tif_rawcp;
00436                                     occ = tif->tif_rawdatasize - tif->tif_rawcc;
00437                 }
00438                 *op++ = (tidataval_t) j; occ--;
00439                 while (j--) {
00440                     *op++ = (tidataval_t) (tp[i++] >> shft & 0xff);
00441                     occ--;
00442                 }
00443             }
00444             if (rc >= MINRUN) {     /* write out run */
00445                 *op++ = (tidataval_t) (128-2+rc);
00446                 *op++ = (tidataval_t) (tp[beg] >> shft & 0xff);
00447                 occ -= 2;
00448             } else
00449                 rc = 0;
00450         }
00451     tif->tif_rawcp = op;
00452     tif->tif_rawcc = tif->tif_rawdatasize - occ;
00453 
00454     return (1);
00455 }
00456 
00457 /*
00458  * Encode a row of 24-bit pixels.
00459  */
00460 static int
00461 LogLuvEncode24(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
00462 {
00463     LogLuvState* sp = EncoderState(tif);
00464     int i, npixels, occ;
00465     tidata_t op;
00466     uint32* tp;
00467 
00468     assert(s == 0);
00469     assert(sp != NULL);
00470     npixels = cc / sp->pixel_size;
00471 
00472     if (sp->user_datafmt == SGILOGDATAFMT_RAW)
00473         tp = (uint32*) bp;
00474     else {
00475         tp = (uint32*) sp->tbuf;
00476         assert(sp->tbuflen >= npixels);
00477         (*sp->tfunc)(sp, bp, npixels);
00478     }
00479                     /* write out encoded pixels */
00480     op = tif->tif_rawcp;
00481     occ = tif->tif_rawdatasize - tif->tif_rawcc;
00482     for (i = npixels; i--; ) {
00483         if (occ < 3) {
00484             tif->tif_rawcp = op;
00485             tif->tif_rawcc = tif->tif_rawdatasize - occ;
00486             if (!TIFFFlushData1(tif))
00487                 return (-1);
00488             op = tif->tif_rawcp;
00489             occ = tif->tif_rawdatasize - tif->tif_rawcc;
00490         }
00491         *op++ = (tidataval_t)(*tp >> 16);
00492         *op++ = (tidataval_t)(*tp >> 8 & 0xff);
00493         *op++ = (tidataval_t)(*tp++ & 0xff);
00494         occ -= 3;
00495     }
00496     tif->tif_rawcp = op;
00497     tif->tif_rawcc = tif->tif_rawdatasize - occ;
00498 
00499     return (1);
00500 }
00501 
00502 /*
00503  * Encode a row of 32-bit pixels.
00504  */
00505 static int
00506 LogLuvEncode32(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
00507 {
00508     LogLuvState* sp = EncoderState(tif);
00509     int shft, i, j, npixels;
00510     tidata_t op;
00511     uint32* tp;
00512     uint32 b;
00513     int occ, rc=0, mask, beg;
00514 
00515     assert(s == 0);
00516     assert(sp != NULL);
00517 
00518     npixels = cc / sp->pixel_size;
00519 
00520     if (sp->user_datafmt == SGILOGDATAFMT_RAW)
00521         tp = (uint32*) bp;
00522     else {
00523         tp = (uint32*) sp->tbuf;
00524         assert(sp->tbuflen >= npixels);
00525         (*sp->tfunc)(sp, bp, npixels);
00526     }
00527                     /* compress each byte string */
00528     op = tif->tif_rawcp;
00529     occ = tif->tif_rawdatasize - tif->tif_rawcc;
00530     for (shft = 4*8; (shft -= 8) >= 0; )
00531         for (i = 0; i < npixels; i += rc) {
00532             if (occ < 4) {
00533                 tif->tif_rawcp = op;
00534                 tif->tif_rawcc = tif->tif_rawdatasize - occ;
00535                 if (!TIFFFlushData1(tif))
00536                     return (-1);
00537                 op = tif->tif_rawcp;
00538                 occ = tif->tif_rawdatasize - tif->tif_rawcc;
00539             }
00540             mask = 0xff << shft;        /* find next run */
00541             for (beg = i; beg < npixels; beg += rc) {
00542                 b = tp[beg] & mask;
00543                 rc = 1;
00544                 while (rc < 127+2 && beg+rc < npixels &&
00545                         (tp[beg+rc] & mask) == b)
00546                     rc++;
00547                 if (rc >= MINRUN)
00548                     break;      /* long enough */
00549             }
00550             if (beg-i > 1 && beg-i < MINRUN) {
00551                 b = tp[i] & mask;   /* check short run */
00552                 j = i+1;
00553                 while ((tp[j++] & mask) == b)
00554                     if (j == beg) {
00555                         *op++ = (tidataval_t)(128-2+j-i);
00556                         *op++ = (tidataval_t)(b >> shft);
00557                         occ -= 2;
00558                         i = beg;
00559                         break;
00560                     }
00561             }
00562             while (i < beg) {       /* write out non-run */
00563                 if ((j = beg-i) > 127) j = 127;
00564                 if (occ < j+3) {
00565                     tif->tif_rawcp = op;
00566                     tif->tif_rawcc = tif->tif_rawdatasize - occ;
00567                     if (!TIFFFlushData1(tif))
00568                         return (-1);
00569                     op = tif->tif_rawcp;
00570                     occ = tif->tif_rawdatasize - tif->tif_rawcc;
00571                 }
00572                 *op++ = (tidataval_t) j; occ--;
00573                 while (j--) {
00574                     *op++ = (tidataval_t)(tp[i++] >> shft & 0xff);
00575                     occ--;
00576                 }
00577             }
00578             if (rc >= MINRUN) {     /* write out run */
00579                 *op++ = (tidataval_t) (128-2+rc);
00580                 *op++ = (tidataval_t)(tp[beg] >> shft & 0xff);
00581                 occ -= 2;
00582             } else
00583                 rc = 0;
00584         }
00585     tif->tif_rawcp = op;
00586     tif->tif_rawcc = tif->tif_rawdatasize - occ;
00587 
00588     return (1);
00589 }
00590 
00591 /*
00592  * Encode a strip of pixels.  We break it into rows to
00593  * avoid encoding runs across row boundaries.
00594  */
00595 static int
00596 LogLuvEncodeStrip(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
00597 {
00598     tsize_t rowlen = TIFFScanlineSize(tif);
00599 
00600     assert(cc%rowlen == 0);
00601     while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 1)
00602         bp += rowlen, cc -= rowlen;
00603     return (cc == 0);
00604 }
00605 
00606 /*
00607  * Encode a tile of pixels.  We break it into rows to
00608  * avoid encoding runs across row boundaries.
00609  */
00610 static int
00611 LogLuvEncodeTile(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
00612 {
00613     tsize_t rowlen = TIFFTileRowSize(tif);
00614 
00615     assert(cc%rowlen == 0);
00616     while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 1)
00617         bp += rowlen, cc -= rowlen;
00618     return (cc == 0);
00619 }
00620 
00621 /*
00622  * Encode/Decode functions for converting to and from user formats.
00623  */
00624 
00625 #include "uvcode.h"
00626 
00627 #ifndef UVSCALE
00628 #define U_NEU       0.210526316
00629 #define V_NEU       0.473684211
00630 #define UVSCALE     410.
00631 #endif
00632 
00633 #ifndef M_LN2
00634 #define M_LN2       0.69314718055994530942
00635 #endif
00636 #ifndef M_PI
00637 #define M_PI        3.14159265358979323846
00638 #endif
00639 #define log2(x)     ((1./M_LN2)*log(x))
00640 #define exp2(x)     exp(M_LN2*(x))
00641 
00642 #define itrunc(x,m) ((m)==SGILOGENCODE_NODITHER ? \
00643                 (int)(x) : \
00644                 (int)((x) + rand()*(1./RAND_MAX) - .5))
00645 
00646 #if !LOGLUV_PUBLIC
00647 static
00648 #endif
00649 double
00650 LogL16toY(int p16)      /* compute luminance from 16-bit LogL */
00651 {
00652     int Le = p16 & 0x7fff;
00653     double  Y;
00654 
00655     if (!Le)
00656         return (0.);
00657     Y = exp(M_LN2/256.*(Le+.5) - M_LN2*64.);
00658     return (!(p16 & 0x8000) ? Y : -Y);
00659 }
00660 
00661 #if !LOGLUV_PUBLIC
00662 static
00663 #endif
00664 int
00665 LogL16fromY(double Y, int em)   /* get 16-bit LogL from Y */
00666 {
00667     if (Y >= 1.8371976e19)
00668         return (0x7fff);
00669     if (Y <= -1.8371976e19)
00670         return (0xffff);
00671     if (Y > 5.4136769e-20)
00672         return itrunc(256.*(log2(Y) + 64.), em);
00673     if (Y < -5.4136769e-20)
00674         return (~0x7fff | itrunc(256.*(log2(-Y) + 64.), em));
00675     return (0);
00676 }
00677 
00678 static void
00679 L16toY(LogLuvState* sp, tidata_t op, int n)
00680 {
00681     int16* l16 = (int16*) sp->tbuf;
00682     float* yp = (float*) op;
00683 
00684     while (n-- > 0)
00685         *yp++ = (float)LogL16toY(*l16++);
00686 }
00687 
00688 static void
00689 L16toGry(LogLuvState* sp, tidata_t op, int n)
00690 {
00691     int16* l16 = (int16*) sp->tbuf;
00692     uint8* gp = (uint8*) op;
00693 
00694     while (n-- > 0) {
00695         double Y = LogL16toY(*l16++);
00696         *gp++ = (uint8) ((Y <= 0.) ? 0 : (Y >= 1.) ? 255 : (int)(256.*sqrt(Y)));
00697     }
00698 }
00699 
00700 static void
00701 L16fromY(LogLuvState* sp, tidata_t op, int n)
00702 {
00703     int16* l16 = (int16*) sp->tbuf;
00704     float* yp = (float*) op;
00705 
00706     while (n-- > 0)
00707         *l16++ = (int16) (LogL16fromY(*yp++, sp->encode_meth));
00708 }
00709 
00710 #if !LOGLUV_PUBLIC
00711 static
00712 #endif
00713 void
00714 XYZtoRGB24(float xyz[3], uint8 rgb[3])
00715 {
00716     double  r, g, b;
00717                     /* assume CCIR-709 primaries */
00718     r =  2.690*xyz[0] + -1.276*xyz[1] + -0.414*xyz[2];
00719     g = -1.022*xyz[0] +  1.978*xyz[1] +  0.044*xyz[2];
00720     b =  0.061*xyz[0] + -0.224*xyz[1] +  1.163*xyz[2];
00721                     /* assume 2.0 gamma for speed */
00722     /* could use integer sqrt approx., but this is probably faster */
00723     rgb[0] = (uint8)((r<=0.) ? 0 : (r >= 1.) ? 255 : (int)(256.*sqrt(r)));
00724     rgb[1] = (uint8)((g<=0.) ? 0 : (g >= 1.) ? 255 : (int)(256.*sqrt(g)));
00725     rgb[2] = (uint8)((b<=0.) ? 0 : (b >= 1.) ? 255 : (int)(256.*sqrt(b)));
00726 }
00727 
00728 #if !LOGLUV_PUBLIC
00729 static
00730 #endif
00731 double
00732 LogL10toY(int p10)      /* compute luminance from 10-bit LogL */
00733 {
00734     if (p10 == 0)
00735         return (0.);
00736     return (exp(M_LN2/64.*(p10+.5) - M_LN2*12.));
00737 }
00738 
00739 #if !LOGLUV_PUBLIC
00740 static
00741 #endif
00742 int
00743 LogL10fromY(double Y, int em)   /* get 10-bit LogL from Y */
00744 {
00745     if (Y >= 15.742)
00746         return (0x3ff);
00747     else if (Y <= .00024283)
00748         return (0);
00749     else
00750         return itrunc(64.*(log2(Y) + 12.), em);
00751 }
00752 
00753 #define NANGLES     100
00754 #define uv2ang(u, v)    ( (NANGLES*.499999999/M_PI) \
00755                 * atan2((v)-V_NEU,(u)-U_NEU) + .5*NANGLES )
00756 
00757 static int
00758 oog_encode(double u, double v)      /* encode out-of-gamut chroma */
00759 {
00760     static int  oog_table[NANGLES];
00761     static int  initialized = 0;
00762     register int    i;
00763     
00764     if (!initialized) {     /* set up perimeter table */
00765         double  eps[NANGLES], ua, va, ang, epsa;
00766         int ui, vi, ustep;
00767         for (i = NANGLES; i--; )
00768             eps[i] = 2.;
00769         for (vi = UV_NVS; vi--; ) {
00770             va = UV_VSTART + (vi+.5)*UV_SQSIZ;
00771             ustep = uv_row[vi].nus-1;
00772             if (vi == UV_NVS-1 || vi == 0 || ustep <= 0)
00773                 ustep = 1;
00774             for (ui = uv_row[vi].nus-1; ui >= 0; ui -= ustep) {
00775                 ua = uv_row[vi].ustart + (ui+.5)*UV_SQSIZ;
00776                 ang = uv2ang(ua, va);
00777                                 i = (int) ang;
00778                 epsa = fabs(ang - (i+.5));
00779                 if (epsa < eps[i]) {
00780                     oog_table[i] = uv_row[vi].ncum + ui;
00781                     eps[i] = epsa;
00782                 }
00783             }
00784         }
00785         for (i = NANGLES; i--; )    /* fill any holes */
00786             if (eps[i] > 1.5) {
00787                 int i1, i2;
00788                 for (i1 = 1; i1 < NANGLES/2; i1++)
00789                     if (eps[(i+i1)%NANGLES] < 1.5)
00790                         break;
00791                 for (i2 = 1; i2 < NANGLES/2; i2++)
00792                     if (eps[(i+NANGLES-i2)%NANGLES] < 1.5)
00793                         break;
00794                 if (i1 < i2)
00795                     oog_table[i] =
00796                         oog_table[(i+i1)%NANGLES];
00797                 else
00798                     oog_table[i] =
00799                         oog_table[(i+NANGLES-i2)%NANGLES];
00800             }
00801         initialized = 1;
00802     }
00803     i = (int) uv2ang(u, v);     /* look up hue angle */
00804     return (oog_table[i]);
00805 }
00806 
00807 #undef uv2ang
00808 #undef NANGLES
00809 
00810 #if !LOGLUV_PUBLIC
00811 static
00812 #endif
00813 int
00814 uv_encode(double u, double v, int em)   /* encode (u',v') coordinates */
00815 {
00816     register int    vi, ui;
00817 
00818     if (v < UV_VSTART)
00819         return oog_encode(u, v);
00820     vi = itrunc((v - UV_VSTART)*(1./UV_SQSIZ), em);
00821     if (vi >= UV_NVS)
00822         return oog_encode(u, v);
00823     if (u < uv_row[vi].ustart)
00824         return oog_encode(u, v);
00825     ui = itrunc((u - uv_row[vi].ustart)*(1./UV_SQSIZ), em);
00826     if (ui >= uv_row[vi].nus)
00827         return oog_encode(u, v);
00828 
00829     return (uv_row[vi].ncum + ui);
00830 }
00831 
00832 #if !LOGLUV_PUBLIC
00833 static
00834 #endif
00835 int
00836 uv_decode(double *up, double *vp, int c)    /* decode (u',v') index */
00837 {
00838     int upper, lower;
00839     register int    ui, vi;
00840 
00841     if (c < 0 || c >= UV_NDIVS)
00842         return (-1);
00843     lower = 0;              /* binary search */
00844     upper = UV_NVS;
00845     while (upper - lower > 1) {
00846         vi = (lower + upper) >> 1;
00847         ui = c - uv_row[vi].ncum;
00848         if (ui > 0)
00849             lower = vi;
00850         else if (ui < 0)
00851             upper = vi;
00852         else {
00853             lower = vi;
00854             break;
00855         }
00856     }
00857     vi = lower;
00858     ui = c - uv_row[vi].ncum;
00859     *up = uv_row[vi].ustart + (ui+.5)*UV_SQSIZ;
00860     *vp = UV_VSTART + (vi+.5)*UV_SQSIZ;
00861     return (0);
00862 }
00863 
00864 #if !LOGLUV_PUBLIC
00865 static
00866 #endif
00867 void
00868 LogLuv24toXYZ(uint32 p, float XYZ[3])
00869 {
00870     int Ce;
00871     double  L, u, v, s, x, y;
00872                     /* decode luminance */
00873     L = LogL10toY(p>>14 & 0x3ff);
00874     if (L <= 0.) {
00875         XYZ[0] = XYZ[1] = XYZ[2] = 0.;
00876         return;
00877     }
00878                     /* decode color */
00879     Ce = p & 0x3fff;
00880     if (uv_decode(&u, &v, Ce) < 0) {
00881         u = U_NEU; v = V_NEU;
00882     }
00883     s = 1./(6.*u - 16.*v + 12.);
00884     x = 9.*u * s;
00885     y = 4.*v * s;
00886                     /* convert to XYZ */
00887     XYZ[0] = (float)(x/y * L);
00888     XYZ[1] = (float)L;
00889     XYZ[2] = (float)((1.-x-y)/y * L);
00890 }
00891 
00892 #if !LOGLUV_PUBLIC
00893 static
00894 #endif
00895 uint32
00896 LogLuv24fromXYZ(float XYZ[3], int em)
00897 {
00898     int Le, Ce;
00899     double  u, v, s;
00900                     /* encode luminance */
00901     Le = LogL10fromY(XYZ[1], em);
00902                     /* encode color */
00903     s = XYZ[0] + 15.*XYZ[1] + 3.*XYZ[2];
00904     if (!Le || s <= 0.) {
00905         u = U_NEU;
00906         v = V_NEU;
00907     } else {
00908         u = 4.*XYZ[0] / s;
00909         v = 9.*XYZ[1] / s;
00910     }
00911     Ce = uv_encode(u, v, em);
00912     if (Ce < 0)         /* never happens */
00913         Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER);
00914                     /* combine encodings */
00915     return (Le << 14 | Ce);
00916 }
00917 
00918 static void
00919 Luv24toXYZ(LogLuvState* sp, tidata_t op, int n)
00920 {
00921     uint32* luv = (uint32*) sp->tbuf;
00922     float* xyz = (float*) op;
00923 
00924     while (n-- > 0) {
00925         LogLuv24toXYZ(*luv, xyz);
00926         xyz += 3;
00927         luv++;
00928     }
00929 }
00930 
00931 static void
00932 Luv24toLuv48(LogLuvState* sp, tidata_t op, int n)
00933 {
00934     uint32* luv = (uint32*) sp->tbuf;
00935     int16* luv3 = (int16*) op;
00936 
00937     while (n-- > 0) {
00938         double u, v;
00939 
00940         *luv3++ = (int16)((*luv >> 12 & 0xffd) + 13314);
00941         if (uv_decode(&u, &v, *luv&0x3fff) < 0) {
00942             u = U_NEU;
00943             v = V_NEU;
00944         }
00945         *luv3++ = (int16)(u * (1L<<15));
00946         *luv3++ = (int16)(v * (1L<<15));
00947         luv++;
00948     }
00949 }
00950 
00951 static void
00952 Luv24toRGB(LogLuvState* sp, tidata_t op, int n)
00953 {
00954     uint32* luv = (uint32*) sp->tbuf;
00955     uint8* rgb = (uint8*) op;
00956 
00957     while (n-- > 0) {
00958         float xyz[3];
00959 
00960         LogLuv24toXYZ(*luv++, xyz);
00961         XYZtoRGB24(xyz, rgb);
00962         rgb += 3;
00963     }
00964 }
00965 
00966 static void
00967 Luv24fromXYZ(LogLuvState* sp, tidata_t op, int n)
00968 {
00969     uint32* luv = (uint32*) sp->tbuf;
00970     float* xyz = (float*) op;
00971 
00972     while (n-- > 0) {
00973         *luv++ = LogLuv24fromXYZ(xyz, sp->encode_meth);
00974         xyz += 3;
00975     }
00976 }
00977 
00978 static void
00979 Luv24fromLuv48(LogLuvState* sp, tidata_t op, int n)
00980 {
00981     uint32* luv = (uint32*) sp->tbuf;
00982     int16* luv3 = (int16*) op;
00983 
00984     while (n-- > 0) {
00985         int Le, Ce;
00986 
00987         if (luv3[0] <= 0)
00988             Le = 0;
00989         else if (luv3[0] >= (1<<12)+3314)
00990             Le = (1<<10) - 1;
00991         else if (sp->encode_meth == SGILOGENCODE_NODITHER)
00992             Le = (luv3[0]-3314) >> 2;
00993         else
00994             Le = itrunc(.25*(luv3[0]-3314.), sp->encode_meth);
00995 
00996         Ce = uv_encode((luv3[1]+.5)/(1<<15), (luv3[2]+.5)/(1<<15),
00997                     sp->encode_meth);
00998         if (Ce < 0) /* never happens */
00999             Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER);
01000         *luv++ = (uint32)Le << 14 | Ce;
01001         luv3 += 3;
01002     }
01003 }
01004 
01005 #if !LOGLUV_PUBLIC
01006 static
01007 #endif
01008 void
01009 LogLuv32toXYZ(uint32 p, float XYZ[3])
01010 {
01011     double  L, u, v, s, x, y;
01012                     /* decode luminance */
01013     L = LogL16toY((int)p >> 16);
01014     if (L <= 0.) {
01015         XYZ[0] = XYZ[1] = XYZ[2] = 0.;
01016         return;
01017     }
01018                     /* decode color */
01019     u = 1./UVSCALE * ((p>>8 & 0xff) + .5);
01020     v = 1./UVSCALE * ((p & 0xff) + .5);
01021     s = 1./(6.*u - 16.*v + 12.);
01022     x = 9.*u * s;
01023     y = 4.*v * s;
01024                     /* convert to XYZ */
01025     XYZ[0] = (float)(x/y * L);
01026     XYZ[1] = (float)L;
01027     XYZ[2] = (float)((1.-x-y)/y * L);
01028 }
01029 
01030 #if !LOGLUV_PUBLIC
01031 static
01032 #endif
01033 uint32
01034 LogLuv32fromXYZ(float XYZ[3], int em)
01035 {
01036     unsigned int    Le, ue, ve;
01037     double  u, v, s;
01038                     /* encode luminance */
01039     Le = (unsigned int)LogL16fromY(XYZ[1], em);
01040                     /* encode color */
01041     s = XYZ[0] + 15.*XYZ[1] + 3.*XYZ[2];
01042     if (!Le || s <= 0.) {
01043         u = U_NEU;
01044         v = V_NEU;
01045     } else {
01046         u = 4.*XYZ[0] / s;
01047         v = 9.*XYZ[1] / s;
01048     }
01049     if (u <= 0.) ue = 0;
01050     else ue = itrunc(UVSCALE*u, em);
01051     if (ue > 255) ue = 255;
01052     if (v <= 0.) ve = 0;
01053     else ve = itrunc(UVSCALE*v, em);
01054     if (ve > 255) ve = 255;
01055                     /* combine encodings */
01056     return (Le << 16 | ue << 8 | ve);
01057 }
01058 
01059 static void
01060 Luv32toXYZ(LogLuvState* sp, tidata_t op, int n)
01061 {
01062     uint32* luv = (uint32*) sp->tbuf;
01063     float* xyz = (float*) op;
01064 
01065     while (n-- > 0) {
01066         LogLuv32toXYZ(*luv++, xyz);
01067         xyz += 3;
01068     }
01069 }
01070 
01071 static void
01072 Luv32toLuv48(LogLuvState* sp, tidata_t op, int n)
01073 {
01074     uint32* luv = (uint32*) sp->tbuf;
01075     int16* luv3 = (int16*) op;
01076 
01077     while (n-- > 0) {
01078         double u, v;
01079 
01080         *luv3++ = (int16)(*luv >> 16);
01081         u = 1./UVSCALE * ((*luv>>8 & 0xff) + .5);
01082         v = 1./UVSCALE * ((*luv & 0xff) + .5);
01083         *luv3++ = (int16)(u * (1L<<15));
01084         *luv3++ = (int16)(v * (1L<<15));
01085         luv++;
01086     }
01087 }
01088 
01089 static void
01090 Luv32toRGB(LogLuvState* sp, tidata_t op, int n)
01091 {
01092     uint32* luv = (uint32*) sp->tbuf;
01093     uint8* rgb = (uint8*) op;
01094 
01095     while (n-- > 0) {
01096         float xyz[3];
01097 
01098         LogLuv32toXYZ(*luv++, xyz);
01099         XYZtoRGB24(xyz, rgb);
01100         rgb += 3;
01101     }
01102 }
01103 
01104 static void
01105 Luv32fromXYZ(LogLuvState* sp, tidata_t op, int n)
01106 {
01107     uint32* luv = (uint32*) sp->tbuf;
01108     float* xyz = (float*) op;
01109 
01110     while (n-- > 0) {
01111         *luv++ = LogLuv32fromXYZ(xyz, sp->encode_meth);
01112         xyz += 3;
01113     }
01114 }
01115 
01116 static void
01117 Luv32fromLuv48(LogLuvState* sp, tidata_t op, int n)
01118 {
01119     uint32* luv = (uint32*) sp->tbuf;
01120     int16* luv3 = (int16*) op;
01121 
01122     if (sp->encode_meth == SGILOGENCODE_NODITHER) {
01123         while (n-- > 0) {
01124             *luv++ = (uint32)luv3[0] << 16 |
01125                 (luv3[1]*(uint32)(UVSCALE+.5) >> 7 & 0xff00) |
01126                 (luv3[2]*(uint32)(UVSCALE+.5) >> 15 & 0xff);
01127             luv3 += 3;
01128         }
01129         return;
01130     }
01131     while (n-- > 0) {
01132         *luv++ = (uint32)luv3[0] << 16 |
01133     (itrunc(luv3[1]*(UVSCALE/(1<<15)), sp->encode_meth) << 8 & 0xff00) |
01134         (itrunc(luv3[2]*(UVSCALE/(1<<15)), sp->encode_meth) & 0xff);
01135         luv3 += 3;
01136     }
01137 }
01138 
01139 static void
01140 _logLuvNop(LogLuvState* sp, tidata_t op, int n)
01141 {
01142     (void) sp; (void) op; (void) n;
01143 }
01144 
01145 static int
01146 LogL16GuessDataFmt(TIFFDirectory *td)
01147 {
01148 #define PACK(s,b,f) (((b)<<6)|((s)<<3)|(f))
01149     switch (PACK(td->td_samplesperpixel, td->td_bitspersample, td->td_sampleformat)) {
01150     case PACK(1, 32, SAMPLEFORMAT_IEEEFP):
01151         return (SGILOGDATAFMT_FLOAT);
01152     case PACK(1, 16, SAMPLEFORMAT_VOID):
01153     case PACK(1, 16, SAMPLEFORMAT_INT):
01154     case PACK(1, 16, SAMPLEFORMAT_UINT):
01155         return (SGILOGDATAFMT_16BIT);
01156     case PACK(1,  8, SAMPLEFORMAT_VOID):
01157     case PACK(1,  8, SAMPLEFORMAT_UINT):
01158         return (SGILOGDATAFMT_8BIT);
01159     }
01160 #undef PACK
01161     return (SGILOGDATAFMT_UNKNOWN);
01162 }
01163 
01164 static uint32
01165 multiply(size_t m1, size_t m2)
01166 {
01167     uint32  bytes = m1 * m2;
01168 
01169     if (m1 && bytes / m1 != m2)
01170         bytes = 0;
01171 
01172     return bytes;
01173 }
01174 
01175 static int
01176 LogL16InitState(TIFF* tif)
01177 {
01178     TIFFDirectory *td = &tif->tif_dir;
01179     LogLuvState* sp = DecoderState(tif);
01180     static const char module[] = "LogL16InitState";
01181 
01182     assert(sp != NULL);
01183     assert(td->td_photometric == PHOTOMETRIC_LOGL);
01184 
01185     /* for some reason, we can't do this in TIFFInitLogL16 */
01186     if (sp->user_datafmt == SGILOGDATAFMT_UNKNOWN)
01187         sp->user_datafmt = LogL16GuessDataFmt(td);
01188     switch (sp->user_datafmt) {
01189     case SGILOGDATAFMT_FLOAT:
01190         sp->pixel_size = sizeof (float);
01191         break;
01192     case SGILOGDATAFMT_16BIT:
01193         sp->pixel_size = sizeof (int16);
01194         break;
01195     case SGILOGDATAFMT_8BIT:
01196         sp->pixel_size = sizeof (uint8);
01197         break;
01198     default:
01199         TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
01200             "No support for converting user data format to LogL");
01201         return (0);
01202     }
01203         if( isTiled(tif) )
01204             sp->tbuflen = multiply(td->td_tilewidth, td->td_tilelength);
01205         else
01206             sp->tbuflen = multiply(td->td_imagewidth, td->td_rowsperstrip);
01207     if (multiply(sp->tbuflen, sizeof (int16)) == 0 ||
01208         (sp->tbuf = (tidata_t*) _TIFFmalloc(sp->tbuflen * sizeof (int16))) == NULL) {
01209         TIFFErrorExt(tif->tif_clientdata, module, "%s: No space for SGILog translation buffer",
01210             tif->tif_name);
01211         return (0);
01212     }
01213     return (1);
01214 }
01215 
01216 static int
01217 LogLuvGuessDataFmt(TIFFDirectory *td)
01218 {
01219     int guess;
01220 
01221     /*
01222      * If the user didn't tell us their datafmt,
01223      * take our best guess from the bitspersample.
01224      */
01225 #define PACK(a,b)   (((a)<<3)|(b))
01226     switch (PACK(td->td_bitspersample, td->td_sampleformat)) {
01227     case PACK(32, SAMPLEFORMAT_IEEEFP):
01228         guess = SGILOGDATAFMT_FLOAT;
01229         break;
01230     case PACK(32, SAMPLEFORMAT_VOID):
01231     case PACK(32, SAMPLEFORMAT_UINT):
01232     case PACK(32, SAMPLEFORMAT_INT):
01233         guess = SGILOGDATAFMT_RAW;
01234         break;
01235     case PACK(16, SAMPLEFORMAT_VOID):
01236     case PACK(16, SAMPLEFORMAT_INT):
01237     case PACK(16, SAMPLEFORMAT_UINT):
01238         guess = SGILOGDATAFMT_16BIT;
01239         break;
01240     case PACK( 8, SAMPLEFORMAT_VOID):
01241     case PACK( 8, SAMPLEFORMAT_UINT):
01242         guess = SGILOGDATAFMT_8BIT;
01243         break;
01244     default:
01245         guess = SGILOGDATAFMT_UNKNOWN;
01246         break;
01247 #undef PACK
01248     }
01249     /*
01250      * Double-check samples per pixel.
01251      */
01252     switch (td->td_samplesperpixel) {
01253     case 1:
01254         if (guess != SGILOGDATAFMT_RAW)
01255             guess = SGILOGDATAFMT_UNKNOWN;
01256         break;
01257     case 3:
01258         if (guess == SGILOGDATAFMT_RAW)
01259             guess = SGILOGDATAFMT_UNKNOWN;
01260         break;
01261     default:
01262         guess = SGILOGDATAFMT_UNKNOWN;
01263         break;
01264     }
01265     return (guess);
01266 }
01267 
01268 static int
01269 LogLuvInitState(TIFF* tif)
01270 {
01271     TIFFDirectory* td = &tif->tif_dir;
01272     LogLuvState* sp = DecoderState(tif);
01273     static const char module[] = "LogLuvInitState";
01274 
01275     assert(sp != NULL);
01276     assert(td->td_photometric == PHOTOMETRIC_LOGLUV);
01277 
01278     /* for some reason, we can't do this in TIFFInitLogLuv */
01279     if (td->td_planarconfig != PLANARCONFIG_CONTIG) {
01280         TIFFErrorExt(tif->tif_clientdata, module,
01281             "SGILog compression cannot handle non-contiguous data");
01282         return (0);
01283     }
01284     if (sp->user_datafmt == SGILOGDATAFMT_UNKNOWN)
01285         sp->user_datafmt = LogLuvGuessDataFmt(td);
01286     switch (sp->user_datafmt) {
01287     case SGILOGDATAFMT_FLOAT:
01288         sp->pixel_size = 3*sizeof (float);
01289         break;
01290     case SGILOGDATAFMT_16BIT:
01291         sp->pixel_size = 3*sizeof (int16);
01292         break;
01293     case SGILOGDATAFMT_RAW:
01294         sp->pixel_size = sizeof (uint32);
01295         break;
01296     case SGILOGDATAFMT_8BIT:
01297         sp->pixel_size = 3*sizeof (uint8);
01298         break;
01299     default:
01300         TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
01301             "No support for converting user data format to LogLuv");
01302         return (0);
01303     }
01304         if( isTiled(tif) )
01305             sp->tbuflen = multiply(td->td_tilewidth, td->td_tilelength);
01306         else
01307             sp->tbuflen = multiply(td->td_imagewidth, td->td_rowsperstrip);
01308     if (multiply(sp->tbuflen, sizeof (uint32)) == 0 ||
01309         (sp->tbuf = (tidata_t*) _TIFFmalloc(sp->tbuflen * sizeof (uint32))) == NULL) {
01310         TIFFErrorExt(tif->tif_clientdata, module, "%s: No space for SGILog translation buffer",
01311             tif->tif_name);
01312         return (0);
01313     }
01314     return (1);
01315 }
01316 
01317 static int
01318 LogLuvSetupDecode(TIFF* tif)
01319 {
01320     LogLuvState* sp = DecoderState(tif);
01321     TIFFDirectory* td = &tif->tif_dir;
01322 
01323     tif->tif_postdecode = _TIFFNoPostDecode;
01324     switch (td->td_photometric) {
01325     case PHOTOMETRIC_LOGLUV:
01326         if (!LogLuvInitState(tif))
01327             break;
01328         if (td->td_compression == COMPRESSION_SGILOG24) {
01329             tif->tif_decoderow = LogLuvDecode24;
01330             switch (sp->user_datafmt) {
01331             case SGILOGDATAFMT_FLOAT:
01332                 sp->tfunc = Luv24toXYZ;
01333                 break;
01334             case SGILOGDATAFMT_16BIT:
01335                 sp->tfunc = Luv24toLuv48;
01336                 break;
01337             case SGILOGDATAFMT_8BIT:
01338                 sp->tfunc = Luv24toRGB;
01339                 break;
01340             }
01341         } else {
01342             tif->tif_decoderow = LogLuvDecode32;
01343             switch (sp->user_datafmt) {
01344             case SGILOGDATAFMT_FLOAT:
01345                 sp->tfunc = Luv32toXYZ;
01346                 break;
01347             case SGILOGDATAFMT_16BIT:
01348                 sp->tfunc = Luv32toLuv48;
01349                 break;
01350             case SGILOGDATAFMT_8BIT:
01351                 sp->tfunc = Luv32toRGB;
01352                 break;
01353             }
01354         }
01355         return (1);
01356     case PHOTOMETRIC_LOGL:
01357         if (!LogL16InitState(tif))
01358             break;
01359         tif->tif_decoderow = LogL16Decode;
01360         switch (sp->user_datafmt) {
01361         case SGILOGDATAFMT_FLOAT:
01362             sp->tfunc = L16toY;
01363             break;
01364         case SGILOGDATAFMT_8BIT:
01365             sp->tfunc = L16toGry;
01366             break;
01367         }
01368         return (1);
01369     default:
01370         TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
01371     "Inappropriate photometric interpretation %d for SGILog compression; %s",
01372             td->td_photometric, "must be either LogLUV or LogL");
01373         break;
01374     }
01375     return (0);
01376 }
01377 
01378 static int
01379 LogLuvSetupEncode(TIFF* tif)
01380 {
01381     LogLuvState* sp = EncoderState(tif);
01382     TIFFDirectory* td = &tif->tif_dir;
01383 
01384     switch (td->td_photometric) {
01385     case PHOTOMETRIC_LOGLUV:
01386         if (!LogLuvInitState(tif))
01387             break;
01388         if (td->td_compression == COMPRESSION_SGILOG24) {
01389             tif->tif_encoderow = LogLuvEncode24;
01390             switch (sp->user_datafmt) {
01391             case SGILOGDATAFMT_FLOAT:
01392                 sp->tfunc = Luv24fromXYZ;
01393                 break;
01394             case SGILOGDATAFMT_16BIT:
01395                 sp->tfunc = Luv24fromLuv48;
01396                 break;
01397             case SGILOGDATAFMT_RAW:
01398                 break;
01399             default:
01400                 goto notsupported;
01401             }
01402         } else {
01403             tif->tif_encoderow = LogLuvEncode32;
01404             switch (sp->user_datafmt) {
01405             case SGILOGDATAFMT_FLOAT:
01406                 sp->tfunc = Luv32fromXYZ;
01407                 break;
01408             case SGILOGDATAFMT_16BIT:
01409                 sp->tfunc = Luv32fromLuv48;
01410                 break;
01411             case SGILOGDATAFMT_RAW:
01412                 break;
01413             default:
01414                 goto notsupported;
01415             }
01416         }
01417         break;
01418     case PHOTOMETRIC_LOGL:
01419         if (!LogL16InitState(tif))
01420             break;
01421         tif->tif_encoderow = LogL16Encode;
01422         switch (sp->user_datafmt) {
01423         case SGILOGDATAFMT_FLOAT:
01424             sp->tfunc = L16fromY;
01425             break;
01426         case SGILOGDATAFMT_16BIT:
01427             break;
01428         default:
01429             goto notsupported;
01430         }
01431         break;
01432     default:
01433         TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
01434     "Inappropriate photometric interpretation %d for SGILog compression; %s",
01435                 td->td_photometric, "must be either LogLUV or LogL");
01436         break;
01437     }
01438     return (1);
01439 notsupported:
01440     TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
01441         "SGILog compression supported only for %s, or raw data",
01442         td->td_photometric == PHOTOMETRIC_LOGL ? "Y, L" : "XYZ, Luv");
01443     return (0);
01444 }
01445 
01446 static void
01447 LogLuvClose(TIFF* tif)
01448 {
01449     TIFFDirectory *td = &tif->tif_dir;
01450 
01451     /*
01452      * For consistency, we always want to write out the same
01453      * bitspersample and sampleformat for our TIFF file,
01454      * regardless of the data format being used by the application.
01455      * Since this routine is called after tags have been set but
01456      * before they have been recorded in the file, we reset them here.
01457      */
01458     td->td_samplesperpixel =
01459         (td->td_photometric == PHOTOMETRIC_LOGL) ? 1 : 3;
01460     td->td_bitspersample = 16;
01461     td->td_sampleformat = SAMPLEFORMAT_INT;
01462 }
01463 
01464 static void
01465 LogLuvCleanup(TIFF* tif)
01466 {
01467     LogLuvState* sp = (LogLuvState *)tif->tif_data;
01468 
01469     assert(sp != 0);
01470 
01471     tif->tif_tagmethods.vgetfield = sp->vgetparent;
01472     tif->tif_tagmethods.vsetfield = sp->vsetparent;
01473 
01474     if (sp->tbuf)
01475         _TIFFfree(sp->tbuf);
01476     _TIFFfree(sp);
01477     tif->tif_data = NULL;
01478 
01479     _TIFFSetDefaultCompressionState(tif);
01480 }
01481 
01482 static int
01483 LogLuvVSetField(TIFF* tif, ttag_t tag, va_list ap)
01484 {
01485     LogLuvState* sp = DecoderState(tif);
01486     int bps, fmt;
01487 
01488     switch (tag) {
01489     case TIFFTAG_SGILOGDATAFMT:
01490         sp->user_datafmt = va_arg(ap, int);
01491         /*
01492          * Tweak the TIFF header so that the rest of libtiff knows what
01493          * size of data will be passed between app and library, and
01494          * assume that the app knows what it is doing and is not
01495          * confused by these header manipulations...
01496          */
01497         switch (sp->user_datafmt) {
01498         case SGILOGDATAFMT_FLOAT:
01499             bps = 32, fmt = SAMPLEFORMAT_IEEEFP;
01500             break;
01501         case SGILOGDATAFMT_16BIT:
01502             bps = 16, fmt = SAMPLEFORMAT_INT;
01503             break;
01504         case SGILOGDATAFMT_RAW:
01505             bps = 32, fmt = SAMPLEFORMAT_UINT;
01506             TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
01507             break;
01508         case SGILOGDATAFMT_8BIT:
01509             bps = 8, fmt = SAMPLEFORMAT_UINT;
01510             break;
01511         default:
01512             TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
01513                 "Unknown data format %d for LogLuv compression",
01514                 sp->user_datafmt);
01515             return (0);
01516         }
01517         TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps);
01518         TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, fmt);
01519         /*
01520          * Must recalculate sizes should bits/sample change.
01521          */
01522         tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1;
01523         tif->tif_scanlinesize = TIFFScanlineSize(tif);
01524         return (1);
01525     case TIFFTAG_SGILOGENCODE:
01526         sp->encode_meth = va_arg(ap, int);
01527         if (sp->encode_meth != SGILOGENCODE_NODITHER &&
01528                 sp->encode_meth != SGILOGENCODE_RANDITHER) {
01529             TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
01530                 "Unknown encoding %d for LogLuv compression",
01531                 sp->encode_meth);
01532             return (0);
01533         }
01534         return (1);
01535     default:
01536         return (*sp->vsetparent)(tif, tag, ap);
01537     }
01538 }
01539 
01540 static int
01541 LogLuvVGetField(TIFF* tif, ttag_t tag, va_list ap)
01542 {
01543     LogLuvState *sp = (LogLuvState *)tif->tif_data;
01544 
01545     switch (tag) {
01546     case TIFFTAG_SGILOGDATAFMT:
01547         *va_arg(ap, int*) = sp->user_datafmt;
01548         return (1);
01549     default:
01550         return (*sp->vgetparent)(tif, tag, ap);
01551     }
01552 }
01553 
01554 static const TIFFFieldInfo LogLuvFieldInfo[] = {
01555     { TIFFTAG_SGILOGDATAFMT,      0, 0, TIFF_SHORT, FIELD_PSEUDO,
01556       TRUE, FALSE,  "SGILogDataFmt"},
01557     { TIFFTAG_SGILOGENCODE,   0, 0, TIFF_SHORT, FIELD_PSEUDO,
01558       TRUE, FALSE,  "SGILogEncode"}
01559 };
01560 
01561 int
01562 TIFFInitSGILog(TIFF* tif, int scheme)
01563 {
01564     static const char module[] = "TIFFInitSGILog";
01565     LogLuvState* sp;
01566 
01567     assert(scheme == COMPRESSION_SGILOG24 || scheme == COMPRESSION_SGILOG);
01568 
01569     /*
01570      * Merge codec-specific tag information.
01571      */
01572     if (!_TIFFMergeFieldInfo(tif, LogLuvFieldInfo,
01573                  TIFFArrayCount(LogLuvFieldInfo))) {
01574         TIFFErrorExt(tif->tif_clientdata, module,
01575                  "Merging SGILog codec-specific tags failed");
01576         return 0;
01577     }
01578 
01579     /*
01580      * Allocate state block so tag methods have storage to record values.
01581      */
01582     tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (LogLuvState));
01583     if (tif->tif_data == NULL)
01584         goto bad;
01585     sp = (LogLuvState*) tif->tif_data;
01586     _TIFFmemset((tdata_t)sp, 0, sizeof (*sp));
01587     sp->user_datafmt = SGILOGDATAFMT_UNKNOWN;
01588     sp->encode_meth = (scheme == COMPRESSION_SGILOG24) ?
01589                 SGILOGENCODE_RANDITHER : SGILOGENCODE_NODITHER;
01590     sp->tfunc = _logLuvNop;
01591 
01592     /*
01593      * Install codec methods.
01594      * NB: tif_decoderow & tif_encoderow are filled
01595      *     in at setup time.
01596      */
01597     tif->tif_setupdecode = LogLuvSetupDecode;
01598     tif->tif_decodestrip = LogLuvDecodeStrip;
01599     tif->tif_decodetile = LogLuvDecodeTile;
01600     tif->tif_setupencode = LogLuvSetupEncode;
01601     tif->tif_encodestrip = LogLuvEncodeStrip;
01602     tif->tif_encodetile = LogLuvEncodeTile;
01603     tif->tif_close = LogLuvClose;
01604     tif->tif_cleanup = LogLuvCleanup;
01605 
01606     /* 
01607      * Override parent get/set field methods.
01608      */
01609     sp->vgetparent = tif->tif_tagmethods.vgetfield;
01610     tif->tif_tagmethods.vgetfield = LogLuvVGetField;   /* hook for codec tags */
01611     sp->vsetparent = tif->tif_tagmethods.vsetfield;
01612     tif->tif_tagmethods.vsetfield = LogLuvVSetField;   /* hook for codec tags */
01613 
01614     return (1);
01615 bad:
01616     TIFFErrorExt(tif->tif_clientdata, module,
01617              "%s: No space for LogLuv state block", tif->tif_name);
01618     return (0);
01619 }
01620 #endif /* LOGLUV_SUPPORT */
01621 
01622 /* vim: set ts=8 sts=8 sw=8 noet: */
01623 /*
01624  * Local Variables:
01625  * mode: c
01626  * c-basic-offset: 8
01627  * fill-column: 78
01628  * End:
01629  */

Generated on Sat May 26 2012 04:18:24 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.