LCOV - code coverage report
Current view: directory - frmts/gtiff/libtiff - tif_luv.c (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 777 0 0.0 %
Date: 2011-12-18 Functions: 49 0 0.0 %

       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               0 : LogL16Decode(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
     185                 : {
     186                 :   static const char module[] = "LogL16Decode";
     187               0 :   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               0 :   assert(s == 0);
     198               0 :   assert(sp != NULL);
     199                 : 
     200               0 :   npixels = occ / sp->pixel_size;
     201                 : 
     202               0 :   if (sp->user_datafmt == SGILOGDATAFMT_16BIT)
     203               0 :     tp = (int16*) op;
     204                 :   else {
     205               0 :     assert(sp->tbuflen >= npixels);
     206               0 :     tp = (int16*) sp->tbuf;
     207                 :   }
     208               0 :   _TIFFmemset((void*) tp, 0, npixels*sizeof (tp[0]));
     209                 : 
     210               0 :   bp = (unsigned char*) tif->tif_rawcp;
     211               0 :   cc = tif->tif_rawcc;
     212                 :   /* get each byte string */
     213               0 :   for (shft = 2*8; (shft -= 8) >= 0; ) {
     214               0 :     for (i = 0; i < npixels && cc > 0; )
     215               0 :       if (*bp >= 128) {    /* run */
     216               0 :         rc = *bp++ + (2-128);   /* TODO: potential input buffer overrun when decoding corrupt or truncated data */
     217               0 :         b = (int16)(*bp++ << shft);
     218               0 :         cc -= 2;
     219               0 :         while (rc-- && i < npixels)
     220               0 :           tp[i++] |= b;
     221                 :       } else {      /* non-run */
     222               0 :         rc = *bp++;   /* nul is noop */
     223               0 :         while (--cc && rc-- && i < npixels)
     224               0 :           tp[i++] |= (int16)*bp++ << shft;
     225                 :       }
     226               0 :     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               0 :       TIFFErrorExt(tif->tif_clientdata, module,
     234                 :           "Not enough data at row %lu (short %llu pixels)",
     235                 :              (unsigned long) tif->tif_row,
     236               0 :              (unsigned long long) (npixels - i));
     237                 : #endif
     238               0 :       tif->tif_rawcp = (uint8*) bp;
     239               0 :       tif->tif_rawcc = cc;
     240               0 :       return (0);
     241                 :     }
     242                 :   }
     243               0 :   (*sp->tfunc)(sp, op, npixels);
     244               0 :   tif->tif_rawcp = (uint8*) bp;
     245               0 :   tif->tif_rawcc = cc;
     246               0 :   return (1);
     247                 : }
     248                 : 
     249                 : /*
     250                 :  * Decode a string of 24-bit pixels.
     251                 :  */
     252                 : static int
     253               0 : LogLuvDecode24(TIFF* tif, uint8* op, tmsize_t occ, uint16 s)
     254                 : {
     255                 :   static const char module[] = "LogLuvDecode24";
     256               0 :   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               0 :   assert(s == 0);
     264               0 :   assert(sp != NULL);
     265                 : 
     266               0 :   npixels = occ / sp->pixel_size;
     267                 : 
     268               0 :   if (sp->user_datafmt == SGILOGDATAFMT_RAW)
     269               0 :     tp = (uint32 *)op;
     270                 :   else {
     271               0 :     assert(sp->tbuflen >= npixels);
     272               0 :     tp = (uint32 *) sp->tbuf;
     273                 :   }
     274                 :   /* copy to array of uint32 */
     275               0 :   bp = (unsigned char*) tif->tif_rawcp;
     276               0 :   cc = tif->tif_rawcc;
     277               0 :   for (i = 0; i < npixels && cc > 0; i++) {
     278               0 :     tp[i] = bp[0] << 16 | bp[1] << 8 | bp[2];
     279               0 :     bp += 3;
     280               0 :     cc -= 3;
     281                 :   }
     282               0 :   tif->tif_rawcp = (uint8*) bp;
     283               0 :   tif->tif_rawcc = cc;
     284               0 :   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               0 :     TIFFErrorExt(tif->tif_clientdata, module,
     292                 :       "Not enough data at row %lu (short %llu pixels)",
     293                 :            (unsigned long) tif->tif_row,
     294               0 :            (unsigned long long) (npixels - i));
     295                 : #endif
     296               0 :     return (0);
     297                 :   }
     298               0 :   (*sp->tfunc)(sp, op, npixels);
     299               0 :   return (1);
     300                 : }
     301                 : 
     302                 : /*
     303                 :  * Decode a string of 32-bit pixels.
     304                 :  */
     305                 : static int
     306               0 : 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               0 :   assert(s == 0);
     320               0 :   sp = DecoderState(tif);
     321               0 :   assert(sp != NULL);
     322                 : 
     323               0 :   npixels = occ / sp->pixel_size;
     324                 : 
     325               0 :   if (sp->user_datafmt == SGILOGDATAFMT_RAW)
     326               0 :     tp = (uint32*) op;
     327                 :   else {
     328               0 :     assert(sp->tbuflen >= npixels);
     329               0 :     tp = (uint32*) sp->tbuf;
     330                 :   }
     331               0 :   _TIFFmemset((void*) tp, 0, npixels*sizeof (tp[0]));
     332                 : 
     333               0 :   bp = (unsigned char*) tif->tif_rawcp;
     334               0 :   cc = tif->tif_rawcc;
     335                 :   /* get each byte string */
     336               0 :   for (shft = 4*8; (shft -= 8) >= 0; ) {
     337               0 :     for (i = 0; i < npixels && cc > 0; )
     338               0 :       if (*bp >= 128) {    /* run */
     339               0 :         rc = *bp++ + (2-128);
     340               0 :         b = (uint32)*bp++ << shft;
     341               0 :         cc -= 2;                /* TODO: potential input buffer overrun when decoding corrupt or truncated data */
     342               0 :         while (rc-- && i < npixels)
     343               0 :           tp[i++] |= b;
     344                 :       } else {      /* non-run */
     345               0 :         rc = *bp++;   /* nul is noop */
     346               0 :         while (--cc && rc-- && i < npixels)
     347               0 :           tp[i++] |= (uint32)*bp++ << shft;
     348                 :       }
     349               0 :     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               0 :       TIFFErrorExt(tif->tif_clientdata, module,
     357                 :       "Not enough data at row %lu (short %llu pixels)",
     358                 :              (unsigned long) tif->tif_row,
     359               0 :              (unsigned long long) (npixels - i));
     360                 : #endif
     361               0 :       tif->tif_rawcp = (uint8*) bp;
     362               0 :       tif->tif_rawcc = cc;
     363               0 :       return (0);
     364                 :     }
     365                 :   }
     366               0 :   (*sp->tfunc)(sp, op, npixels);
     367               0 :   tif->tif_rawcp = (uint8*) bp;
     368               0 :   tif->tif_rawcc = cc;
     369               0 :   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               0 : LogLuvDecodeStrip(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
     379                 : {
     380               0 :   tmsize_t rowlen = TIFFScanlineSize(tif);
     381                 : 
     382               0 :   assert(cc%rowlen == 0);
     383               0 :   while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s))
     384               0 :     bp += rowlen, cc -= rowlen;
     385               0 :   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               0 : LogLuvDecodeTile(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
     395                 : {
     396               0 :   tmsize_t rowlen = TIFFTileRowSize(tif);
     397                 : 
     398               0 :   assert(cc%rowlen == 0);
     399               0 :   while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s))
     400               0 :     bp += rowlen, cc -= rowlen;
     401               0 :   return (cc == 0);
     402                 : }
     403                 : 
     404                 : /*
     405                 :  * Encode a row of 16-bit pixels.
     406                 :  */
     407                 : static int
     408               0 : LogL16Encode(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
     409                 : {
     410               0 :   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               0 :   int rc=0, mask;
     420                 :   tmsize_t beg;
     421                 : 
     422               0 :   assert(s == 0);
     423               0 :   assert(sp != NULL);
     424               0 :   npixels = cc / sp->pixel_size;
     425                 : 
     426               0 :   if (sp->user_datafmt == SGILOGDATAFMT_16BIT)
     427               0 :     tp = (int16*) bp;
     428                 :   else {
     429               0 :     tp = (int16*) sp->tbuf;
     430               0 :     assert(sp->tbuflen >= npixels);
     431               0 :     (*sp->tfunc)(sp, bp, npixels);
     432                 :   }
     433                 :   /* compress each byte string */
     434               0 :   op = tif->tif_rawcp;
     435               0 :   occ = tif->tif_rawdatasize - tif->tif_rawcc;
     436               0 :   for (shft = 2*8; (shft -= 8) >= 0; )
     437               0 :     for (i = 0; i < npixels; i += rc) {
     438               0 :       if (occ < 4) {
     439               0 :         tif->tif_rawcp = op;
     440               0 :         tif->tif_rawcc = tif->tif_rawdatasize - occ;
     441               0 :         if (!TIFFFlushData1(tif))
     442               0 :           return (-1);
     443               0 :         op = tif->tif_rawcp;
     444               0 :         occ = tif->tif_rawdatasize - tif->tif_rawcc;
     445                 :       }
     446               0 :       mask = 0xff << shft;    /* find next run */
     447               0 :       for (beg = i; beg < npixels; beg += rc) {
     448               0 :         b = (int16) (tp[beg] & mask);
     449               0 :         rc = 1;
     450               0 :         while (rc < 127+2 && beg+rc < npixels &&
     451               0 :             (tp[beg+rc] & mask) == b)
     452               0 :           rc++;
     453               0 :         if (rc >= MINRUN)
     454               0 :           break;    /* long enough */
     455                 :       }
     456               0 :       if (beg-i > 1 && beg-i < MINRUN) {
     457               0 :         b = (int16) (tp[i] & mask);/*check short run */
     458               0 :         j = i+1;
     459               0 :         while ((tp[j++] & mask) == b)
     460               0 :           if (j == beg) {
     461               0 :             *op++ = (uint8)(128-2+j-i);
     462               0 :             *op++ = (uint8)(b >> shft);
     463               0 :             occ -= 2;
     464               0 :             i = beg;
     465               0 :             break;
     466                 :           }
     467                 :       }
     468               0 :       while (i < beg) {    /* write out non-run */
     469               0 :         if ((j = beg-i) > 127) j = 127;
     470               0 :         if (occ < j+3) {
     471               0 :           tif->tif_rawcp = op;
     472               0 :           tif->tif_rawcc = tif->tif_rawdatasize - occ;
     473               0 :           if (!TIFFFlushData1(tif))
     474               0 :             return (-1);
     475               0 :           op = tif->tif_rawcp;
     476               0 :           occ = tif->tif_rawdatasize - tif->tif_rawcc;
     477                 :         }
     478               0 :         *op++ = (uint8) j; occ--;
     479               0 :         while (j--) {
     480               0 :           *op++ = (uint8) (tp[i++] >> shft & 0xff);
     481               0 :           occ--;
     482                 :         }
     483                 :       }
     484               0 :       if (rc >= MINRUN) {    /* write out run */
     485               0 :         *op++ = (uint8) (128-2+rc);
     486               0 :         *op++ = (uint8) (tp[beg] >> shft & 0xff);
     487               0 :         occ -= 2;
     488                 :       } else
     489               0 :         rc = 0;
     490                 :     }
     491               0 :   tif->tif_rawcp = op;
     492               0 :   tif->tif_rawcc = tif->tif_rawdatasize - occ;
     493                 : 
     494               0 :   return (1);
     495                 : }
     496                 : 
     497                 : /*
     498                 :  * Encode a row of 24-bit pixels.
     499                 :  */
     500                 : static int
     501               0 : LogLuvEncode24(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
     502                 : {
     503               0 :   LogLuvState* sp = EncoderState(tif);
     504                 :   tmsize_t i;
     505                 :   tmsize_t npixels;
     506                 :   tmsize_t occ;
     507                 :   uint8* op;
     508                 :   uint32* tp;
     509                 : 
     510               0 :   assert(s == 0);
     511               0 :   assert(sp != NULL);
     512               0 :   npixels = cc / sp->pixel_size;
     513                 : 
     514               0 :   if (sp->user_datafmt == SGILOGDATAFMT_RAW)
     515               0 :     tp = (uint32*) bp;
     516                 :   else {
     517               0 :     tp = (uint32*) sp->tbuf;
     518               0 :     assert(sp->tbuflen >= npixels);
     519               0 :     (*sp->tfunc)(sp, bp, npixels);
     520                 :   }
     521                 :   /* write out encoded pixels */
     522               0 :   op = tif->tif_rawcp;
     523               0 :   occ = tif->tif_rawdatasize - tif->tif_rawcc;
     524               0 :   for (i = npixels; i--; ) {
     525               0 :     if (occ < 3) {
     526               0 :       tif->tif_rawcp = op;
     527               0 :       tif->tif_rawcc = tif->tif_rawdatasize - occ;
     528               0 :       if (!TIFFFlushData1(tif))
     529               0 :         return (-1);
     530               0 :       op = tif->tif_rawcp;
     531               0 :       occ = tif->tif_rawdatasize - tif->tif_rawcc;
     532                 :     }
     533               0 :     *op++ = (uint8)(*tp >> 16);
     534               0 :     *op++ = (uint8)(*tp >> 8 & 0xff);
     535               0 :     *op++ = (uint8)(*tp++ & 0xff);
     536               0 :     occ -= 3;
     537                 :   }
     538               0 :   tif->tif_rawcp = op;
     539               0 :   tif->tif_rawcc = tif->tif_rawdatasize - occ;
     540                 : 
     541               0 :   return (1);
     542                 : }
     543                 : 
     544                 : /*
     545                 :  * Encode a row of 32-bit pixels.
     546                 :  */
     547                 : static int
     548               0 : LogLuvEncode32(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
     549                 : {
     550               0 :   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               0 :   int rc=0, mask;
     560                 :   tmsize_t beg;
     561                 : 
     562               0 :   assert(s == 0);
     563               0 :   assert(sp != NULL);
     564                 : 
     565               0 :   npixels = cc / sp->pixel_size;
     566                 : 
     567               0 :   if (sp->user_datafmt == SGILOGDATAFMT_RAW)
     568               0 :     tp = (uint32*) bp;
     569                 :   else {
     570               0 :     tp = (uint32*) sp->tbuf;
     571               0 :     assert(sp->tbuflen >= npixels);
     572               0 :     (*sp->tfunc)(sp, bp, npixels);
     573                 :   }
     574                 :   /* compress each byte string */
     575               0 :   op = tif->tif_rawcp;
     576               0 :   occ = tif->tif_rawdatasize - tif->tif_rawcc;
     577               0 :   for (shft = 4*8; (shft -= 8) >= 0; )
     578               0 :     for (i = 0; i < npixels; i += rc) {
     579               0 :       if (occ < 4) {
     580               0 :         tif->tif_rawcp = op;
     581               0 :         tif->tif_rawcc = tif->tif_rawdatasize - occ;
     582               0 :         if (!TIFFFlushData1(tif))
     583               0 :           return (-1);
     584               0 :         op = tif->tif_rawcp;
     585               0 :         occ = tif->tif_rawdatasize - tif->tif_rawcc;
     586                 :       }
     587               0 :       mask = 0xff << shft;    /* find next run */
     588               0 :       for (beg = i; beg < npixels; beg += rc) {
     589               0 :         b = tp[beg] & mask;
     590               0 :         rc = 1;
     591               0 :         while (rc < 127+2 && beg+rc < npixels &&
     592               0 :             (tp[beg+rc] & mask) == b)
     593               0 :           rc++;
     594               0 :         if (rc >= MINRUN)
     595               0 :           break;    /* long enough */
     596                 :       }
     597               0 :       if (beg-i > 1 && beg-i < MINRUN) {
     598               0 :         b = tp[i] & mask; /* check short run */
     599               0 :         j = i+1;
     600               0 :         while ((tp[j++] & mask) == b)
     601               0 :           if (j == beg) {
     602               0 :             *op++ = (uint8)(128-2+j-i);
     603               0 :             *op++ = (uint8)(b >> shft);
     604               0 :             occ -= 2;
     605               0 :             i = beg;
     606               0 :             break;
     607                 :           }
     608                 :       }
     609               0 :       while (i < beg) {    /* write out non-run */
     610               0 :         if ((j = beg-i) > 127) j = 127;
     611               0 :         if (occ < j+3) {
     612               0 :           tif->tif_rawcp = op;
     613               0 :           tif->tif_rawcc = tif->tif_rawdatasize - occ;
     614               0 :           if (!TIFFFlushData1(tif))
     615               0 :             return (-1);
     616               0 :           op = tif->tif_rawcp;
     617               0 :           occ = tif->tif_rawdatasize - tif->tif_rawcc;
     618                 :         }
     619               0 :         *op++ = (uint8) j; occ--;
     620               0 :         while (j--) {
     621               0 :           *op++ = (uint8)(tp[i++] >> shft & 0xff);
     622               0 :           occ--;
     623                 :         }
     624                 :       }
     625               0 :       if (rc >= MINRUN) {    /* write out run */
     626               0 :         *op++ = (uint8) (128-2+rc);
     627               0 :         *op++ = (uint8)(tp[beg] >> shft & 0xff);
     628               0 :         occ -= 2;
     629                 :       } else
     630               0 :         rc = 0;
     631                 :     }
     632               0 :   tif->tif_rawcp = op;
     633               0 :   tif->tif_rawcc = tif->tif_rawdatasize - occ;
     634                 : 
     635               0 :   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               0 : LogLuvEncodeStrip(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
     644                 : {
     645               0 :   tmsize_t rowlen = TIFFScanlineSize(tif);
     646                 : 
     647               0 :   assert(cc%rowlen == 0);
     648               0 :   while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 1)
     649               0 :     bp += rowlen, cc -= rowlen;
     650               0 :   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               0 : LogLuvEncodeTile(TIFF* tif, uint8* bp, tmsize_t cc, uint16 s)
     659                 : {
     660               0 :   tmsize_t rowlen = TIFFTileRowSize(tif);
     661                 : 
     662               0 :   assert(cc%rowlen == 0);
     663               0 :   while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 1)
     664               0 :     bp += rowlen, cc -= rowlen;
     665               0 :   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               0 : LogL16toY(int p16)    /* compute luminance from 16-bit LogL */
     698                 : {
     699               0 :   int Le = p16 & 0x7fff;
     700                 :   double  Y;
     701                 : 
     702               0 :   if (!Le)
     703               0 :     return (0.);
     704               0 :   Y = exp(M_LN2/256.*(Le+.5) - M_LN2*64.);
     705               0 :   return (!(p16 & 0x8000) ? Y : -Y);
     706                 : }
     707                 : 
     708                 : #if !LOGLUV_PUBLIC
     709                 : static
     710                 : #endif
     711                 : int
     712               0 : LogL16fromY(double Y, int em) /* get 16-bit LogL from Y */
     713                 : {
     714               0 :   if (Y >= 1.8371976e19)
     715               0 :     return (0x7fff);
     716               0 :   if (Y <= -1.8371976e19)
     717               0 :     return (0xffff);
     718               0 :   if (Y > 5.4136769e-20)
     719               0 :     return itrunc(256.*(log2(Y) + 64.), em);
     720               0 :   if (Y < -5.4136769e-20)
     721               0 :     return (~0x7fff | itrunc(256.*(log2(-Y) + 64.), em));
     722               0 :   return (0);
     723                 : }
     724                 : 
     725                 : static void
     726               0 : L16toY(LogLuvState* sp, uint8* op, tmsize_t n)
     727                 : {
     728               0 :   int16* l16 = (int16*) sp->tbuf;
     729               0 :   float* yp = (float*) op;
     730                 : 
     731               0 :   while (n-- > 0)
     732               0 :     *yp++ = (float)LogL16toY(*l16++);
     733               0 : }
     734                 : 
     735                 : static void
     736               0 : L16toGry(LogLuvState* sp, uint8* op, tmsize_t n)
     737                 : {
     738               0 :   int16* l16 = (int16*) sp->tbuf;
     739               0 :   uint8* gp = (uint8*) op;
     740                 : 
     741               0 :   while (n-- > 0) {
     742               0 :     double Y = LogL16toY(*l16++);
     743               0 :     *gp++ = (uint8) ((Y <= 0.) ? 0 : (Y >= 1.) ? 255 : (int)(256.*sqrt(Y)));
     744                 :   }
     745               0 : }
     746                 : 
     747                 : static void
     748               0 : L16fromY(LogLuvState* sp, uint8* op, tmsize_t n)
     749                 : {
     750               0 :   int16* l16 = (int16*) sp->tbuf;
     751               0 :   float* yp = (float*) op;
     752                 : 
     753               0 :   while (n-- > 0)
     754               0 :     *l16++ = (int16) (LogL16fromY(*yp++, sp->encode_meth));
     755               0 : }
     756                 : 
     757                 : #if !LOGLUV_PUBLIC
     758                 : static
     759                 : #endif
     760                 : void
     761               0 : XYZtoRGB24(float xyz[3], uint8 rgb[3])
     762                 : {
     763                 :   double  r, g, b;
     764                 :           /* assume CCIR-709 primaries */
     765               0 :   r =  2.690*xyz[0] + -1.276*xyz[1] + -0.414*xyz[2];
     766               0 :   g = -1.022*xyz[0] +  1.978*xyz[1] +  0.044*xyz[2];
     767               0 :   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               0 :   rgb[0] = (uint8)((r<=0.) ? 0 : (r >= 1.) ? 255 : (int)(256.*sqrt(r)));
     771               0 :   rgb[1] = (uint8)((g<=0.) ? 0 : (g >= 1.) ? 255 : (int)(256.*sqrt(g)));
     772               0 :   rgb[2] = (uint8)((b<=0.) ? 0 : (b >= 1.) ? 255 : (int)(256.*sqrt(b)));
     773               0 : }
     774                 : 
     775                 : #if !LOGLUV_PUBLIC
     776                 : static
     777                 : #endif
     778                 : double
     779               0 : LogL10toY(int p10)    /* compute luminance from 10-bit LogL */
     780                 : {
     781               0 :   if (p10 == 0)
     782               0 :     return (0.);
     783               0 :   return (exp(M_LN2/64.*(p10+.5) - M_LN2*12.));
     784                 : }
     785                 : 
     786                 : #if !LOGLUV_PUBLIC
     787                 : static
     788                 : #endif
     789                 : int
     790               0 : LogL10fromY(double Y, int em) /* get 10-bit LogL from Y */
     791                 : {
     792               0 :   if (Y >= 15.742)
     793               0 :     return (0x3ff);
     794               0 :   else if (Y <= .00024283)
     795               0 :     return (0);
     796                 :   else
     797               0 :     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               0 : 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               0 :   if (!initialized) {   /* set up perimeter table */
     812                 :     double  eps[NANGLES], ua, va, ang, epsa;
     813                 :     int ui, vi, ustep;
     814               0 :     for (i = NANGLES; i--; )
     815               0 :       eps[i] = 2.;
     816               0 :     for (vi = UV_NVS; vi--; ) {
     817               0 :       va = UV_VSTART + (vi+.5)*UV_SQSIZ;
     818               0 :       ustep = uv_row[vi].nus-1;
     819               0 :       if (vi == UV_NVS-1 || vi == 0 || ustep <= 0)
     820               0 :         ustep = 1;
     821               0 :       for (ui = uv_row[vi].nus-1; ui >= 0; ui -= ustep) {
     822               0 :         ua = uv_row[vi].ustart + (ui+.5)*UV_SQSIZ;
     823               0 :         ang = uv2ang(ua, va);
     824               0 :         i = (int) ang;
     825               0 :         epsa = fabs(ang - (i+.5));
     826               0 :         if (epsa < eps[i]) {
     827               0 :           oog_table[i] = uv_row[vi].ncum + ui;
     828               0 :           eps[i] = epsa;
     829                 :         }
     830                 :       }
     831                 :     }
     832               0 :     for (i = NANGLES; i--; )  /* fill any holes */
     833               0 :       if (eps[i] > 1.5) {
     834                 :         int i1, i2;
     835               0 :         for (i1 = 1; i1 < NANGLES/2; i1++)
     836               0 :           if (eps[(i+i1)%NANGLES] < 1.5)
     837               0 :             break;
     838               0 :         for (i2 = 1; i2 < NANGLES/2; i2++)
     839               0 :           if (eps[(i+NANGLES-i2)%NANGLES] < 1.5)
     840               0 :             break;
     841               0 :         if (i1 < i2)
     842               0 :           oog_table[i] =
     843               0 :             oog_table[(i+i1)%NANGLES];
     844                 :         else
     845               0 :           oog_table[i] =
     846               0 :             oog_table[(i+NANGLES-i2)%NANGLES];
     847                 :       }
     848               0 :     initialized = 1;
     849                 :   }
     850               0 :   i = (int) uv2ang(u, v);   /* look up hue angle */
     851               0 :   return (oog_table[i]);
     852                 : }
     853                 : 
     854                 : #undef uv2ang
     855                 : #undef NANGLES
     856                 : 
     857                 : #if !LOGLUV_PUBLIC
     858                 : static
     859                 : #endif
     860                 : int
     861               0 : uv_encode(double u, double v, int em) /* encode (u',v') coordinates */
     862                 : {
     863                 :   register int  vi, ui;
     864                 : 
     865               0 :   if (v < UV_VSTART)
     866               0 :     return oog_encode(u, v);
     867               0 :   vi = itrunc((v - UV_VSTART)*(1./UV_SQSIZ), em);
     868               0 :   if (vi >= UV_NVS)
     869               0 :     return oog_encode(u, v);
     870               0 :   if (u < uv_row[vi].ustart)
     871               0 :     return oog_encode(u, v);
     872               0 :   ui = itrunc((u - uv_row[vi].ustart)*(1./UV_SQSIZ), em);
     873               0 :   if (ui >= uv_row[vi].nus)
     874               0 :     return oog_encode(u, v);
     875                 : 
     876               0 :   return (uv_row[vi].ncum + ui);
     877                 : }
     878                 : 
     879                 : #if !LOGLUV_PUBLIC
     880                 : static
     881                 : #endif
     882                 : int
     883               0 : uv_decode(double *up, double *vp, int c)  /* decode (u',v') index */
     884                 : {
     885                 :   int upper, lower;
     886                 :   register int  ui, vi;
     887                 : 
     888               0 :   if (c < 0 || c >= UV_NDIVS)
     889               0 :     return (-1);
     890               0 :   lower = 0;        /* binary search */
     891               0 :   upper = UV_NVS;
     892               0 :   while (upper - lower > 1) {
     893               0 :     vi = (lower + upper) >> 1;
     894               0 :     ui = c - uv_row[vi].ncum;
     895               0 :     if (ui > 0)
     896               0 :       lower = vi;
     897               0 :     else if (ui < 0)
     898               0 :       upper = vi;
     899                 :     else {
     900               0 :       lower = vi;
     901               0 :       break;
     902                 :     }
     903                 :   }
     904               0 :   vi = lower;
     905               0 :   ui = c - uv_row[vi].ncum;
     906               0 :   *up = uv_row[vi].ustart + (ui+.5)*UV_SQSIZ;
     907               0 :   *vp = UV_VSTART + (vi+.5)*UV_SQSIZ;
     908               0 :   return (0);
     909                 : }
     910                 : 
     911                 : #if !LOGLUV_PUBLIC
     912                 : static
     913                 : #endif
     914                 : void
     915               0 : LogLuv24toXYZ(uint32 p, float XYZ[3])
     916                 : {
     917                 :   int Ce;
     918                 :   double  L, u, v, s, x, y;
     919                 :           /* decode luminance */
     920               0 :   L = LogL10toY(p>>14 & 0x3ff);
     921               0 :   if (L <= 0.) {
     922               0 :     XYZ[0] = XYZ[1] = XYZ[2] = 0.;
     923               0 :     return;
     924                 :   }
     925                 :           /* decode color */
     926               0 :   Ce = p & 0x3fff;
     927               0 :   if (uv_decode(&u, &v, Ce) < 0) {
     928               0 :     u = U_NEU; v = V_NEU;
     929                 :   }
     930               0 :   s = 1./(6.*u - 16.*v + 12.);
     931               0 :   x = 9.*u * s;
     932               0 :   y = 4.*v * s;
     933                 :           /* convert to XYZ */
     934               0 :   XYZ[0] = (float)(x/y * L);
     935               0 :   XYZ[1] = (float)L;
     936               0 :   XYZ[2] = (float)((1.-x-y)/y * L);
     937                 : }
     938                 : 
     939                 : #if !LOGLUV_PUBLIC
     940                 : static
     941                 : #endif
     942                 : uint32
     943               0 : LogLuv24fromXYZ(float XYZ[3], int em)
     944                 : {
     945                 :   int Le, Ce;
     946                 :   double  u, v, s;
     947                 :           /* encode luminance */
     948               0 :   Le = LogL10fromY(XYZ[1], em);
     949                 :           /* encode color */
     950               0 :   s = XYZ[0] + 15.*XYZ[1] + 3.*XYZ[2];
     951               0 :   if (!Le || s <= 0.) {
     952               0 :     u = U_NEU;
     953               0 :     v = V_NEU;
     954                 :   } else {
     955               0 :     u = 4.*XYZ[0] / s;
     956               0 :     v = 9.*XYZ[1] / s;
     957                 :   }
     958               0 :   Ce = uv_encode(u, v, em);
     959               0 :   if (Ce < 0)      /* never happens */
     960               0 :     Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER);
     961                 :           /* combine encodings */
     962               0 :   return (Le << 14 | Ce);
     963                 : }
     964                 : 
     965                 : static void
     966               0 : Luv24toXYZ(LogLuvState* sp, uint8* op, tmsize_t n)
     967                 : {
     968               0 :   uint32* luv = (uint32*) sp->tbuf;  
     969               0 :   float* xyz = (float*) op;
     970                 : 
     971               0 :   while (n-- > 0) {
     972               0 :     LogLuv24toXYZ(*luv, xyz);
     973               0 :     xyz += 3;
     974               0 :     luv++;
     975                 :   }
     976               0 : }
     977                 : 
     978                 : static void
     979               0 : Luv24toLuv48(LogLuvState* sp, uint8* op, tmsize_t n)
     980                 : {
     981               0 :   uint32* luv = (uint32*) sp->tbuf;  
     982               0 :   int16* luv3 = (int16*) op;
     983                 : 
     984               0 :   while (n-- > 0) {
     985                 :     double u, v;
     986                 : 
     987               0 :     *luv3++ = (int16)((*luv >> 12 & 0xffd) + 13314);
     988               0 :     if (uv_decode(&u, &v, *luv&0x3fff) < 0) {
     989               0 :       u = U_NEU;
     990               0 :       v = V_NEU;
     991                 :     }
     992               0 :     *luv3++ = (int16)(u * (1L<<15));
     993               0 :     *luv3++ = (int16)(v * (1L<<15));
     994               0 :     luv++;
     995                 :   }
     996               0 : }
     997                 : 
     998                 : static void
     999               0 : Luv24toRGB(LogLuvState* sp, uint8* op, tmsize_t n)
    1000                 : {
    1001               0 :   uint32* luv = (uint32*) sp->tbuf;  
    1002               0 :   uint8* rgb = (uint8*) op;
    1003                 : 
    1004               0 :   while (n-- > 0) {
    1005                 :     float xyz[3];
    1006                 : 
    1007               0 :     LogLuv24toXYZ(*luv++, xyz);
    1008               0 :     XYZtoRGB24(xyz, rgb);
    1009               0 :     rgb += 3;
    1010                 :   }
    1011               0 : }
    1012                 : 
    1013                 : static void
    1014               0 : Luv24fromXYZ(LogLuvState* sp, uint8* op, tmsize_t n)
    1015                 : {
    1016               0 :   uint32* luv = (uint32*) sp->tbuf;  
    1017               0 :   float* xyz = (float*) op;
    1018                 : 
    1019               0 :   while (n-- > 0) {
    1020               0 :     *luv++ = LogLuv24fromXYZ(xyz, sp->encode_meth);
    1021               0 :     xyz += 3;
    1022                 :   }
    1023               0 : }
    1024                 : 
    1025                 : static void
    1026               0 : Luv24fromLuv48(LogLuvState* sp, uint8* op, tmsize_t n)
    1027                 : {
    1028               0 :   uint32* luv = (uint32*) sp->tbuf;  
    1029               0 :   int16* luv3 = (int16*) op;
    1030                 : 
    1031               0 :   while (n-- > 0) {
    1032                 :     int Le, Ce;
    1033                 : 
    1034               0 :     if (luv3[0] <= 0)
    1035               0 :       Le = 0;
    1036               0 :     else if (luv3[0] >= (1<<12)+3314)
    1037               0 :       Le = (1<<10) - 1;
    1038               0 :     else if (sp->encode_meth == SGILOGENCODE_NODITHER)
    1039               0 :       Le = (luv3[0]-3314) >> 2;
    1040                 :     else
    1041               0 :       Le = itrunc(.25*(luv3[0]-3314.), sp->encode_meth);
    1042                 : 
    1043               0 :     Ce = uv_encode((luv3[1]+.5)/(1<<15), (luv3[2]+.5)/(1<<15),
    1044                 :           sp->encode_meth);
    1045               0 :     if (Ce < 0)  /* never happens */
    1046               0 :       Ce = uv_encode(U_NEU, V_NEU, SGILOGENCODE_NODITHER);
    1047               0 :     *luv++ = (uint32)Le << 14 | Ce;
    1048               0 :     luv3 += 3;
    1049                 :   }
    1050               0 : }
    1051                 : 
    1052                 : #if !LOGLUV_PUBLIC
    1053                 : static
    1054                 : #endif
    1055                 : void
    1056               0 : LogLuv32toXYZ(uint32 p, float XYZ[3])
    1057                 : {
    1058                 :   double  L, u, v, s, x, y;
    1059                 :           /* decode luminance */
    1060               0 :   L = LogL16toY((int)p >> 16);
    1061               0 :   if (L <= 0.) {
    1062               0 :     XYZ[0] = XYZ[1] = XYZ[2] = 0.;
    1063               0 :     return;
    1064                 :   }
    1065                 :           /* decode color */
    1066               0 :   u = 1./UVSCALE * ((p>>8 & 0xff) + .5);
    1067               0 :   v = 1./UVSCALE * ((p & 0xff) + .5);
    1068               0 :   s = 1./(6.*u - 16.*v + 12.);
    1069               0 :   x = 9.*u * s;
    1070               0 :   y = 4.*v * s;
    1071                 :           /* convert to XYZ */
    1072               0 :   XYZ[0] = (float)(x/y * L);
    1073               0 :   XYZ[1] = (float)L;
    1074               0 :   XYZ[2] = (float)((1.-x-y)/y * L);
    1075                 : }
    1076                 : 
    1077                 : #if !LOGLUV_PUBLIC
    1078                 : static
    1079                 : #endif
    1080                 : uint32
    1081               0 : LogLuv32fromXYZ(float XYZ[3], int em)
    1082                 : {
    1083                 :   unsigned int  Le, ue, ve;
    1084                 :   double  u, v, s;
    1085                 :           /* encode luminance */
    1086               0 :   Le = (unsigned int)LogL16fromY(XYZ[1], em);
    1087                 :           /* encode color */
    1088               0 :   s = XYZ[0] + 15.*XYZ[1] + 3.*XYZ[2];
    1089               0 :   if (!Le || s <= 0.) {
    1090               0 :     u = U_NEU;
    1091               0 :     v = V_NEU;
    1092                 :   } else {
    1093               0 :     u = 4.*XYZ[0] / s;
    1094               0 :     v = 9.*XYZ[1] / s;
    1095                 :   }
    1096               0 :   if (u <= 0.) ue = 0;
    1097               0 :   else ue = itrunc(UVSCALE*u, em);
    1098               0 :   if (ue > 255) ue = 255;
    1099               0 :   if (v <= 0.) ve = 0;
    1100               0 :   else ve = itrunc(UVSCALE*v, em);
    1101               0 :   if (ve > 255) ve = 255;
    1102                 :           /* combine encodings */
    1103               0 :   return (Le << 16 | ue << 8 | ve);
    1104                 : }
    1105                 : 
    1106                 : static void
    1107               0 : Luv32toXYZ(LogLuvState* sp, uint8* op, tmsize_t n)
    1108                 : {
    1109               0 :   uint32* luv = (uint32*) sp->tbuf;  
    1110               0 :   float* xyz = (float*) op;
    1111                 : 
    1112               0 :   while (n-- > 0) {
    1113               0 :     LogLuv32toXYZ(*luv++, xyz);
    1114               0 :     xyz += 3;
    1115                 :   }
    1116               0 : }
    1117                 : 
    1118                 : static void
    1119               0 : Luv32toLuv48(LogLuvState* sp, uint8* op, tmsize_t n)
    1120                 : {
    1121               0 :   uint32* luv = (uint32*) sp->tbuf;  
    1122               0 :   int16* luv3 = (int16*) op;
    1123                 : 
    1124               0 :   while (n-- > 0) {
    1125                 :     double u, v;
    1126                 : 
    1127               0 :     *luv3++ = (int16)(*luv >> 16);
    1128               0 :     u = 1./UVSCALE * ((*luv>>8 & 0xff) + .5);
    1129               0 :     v = 1./UVSCALE * ((*luv & 0xff) + .5);
    1130               0 :     *luv3++ = (int16)(u * (1L<<15));
    1131               0 :     *luv3++ = (int16)(v * (1L<<15));
    1132               0 :     luv++;
    1133                 :   }
    1134               0 : }
    1135                 : 
    1136                 : static void
    1137               0 : Luv32toRGB(LogLuvState* sp, uint8* op, tmsize_t n)
    1138                 : {
    1139               0 :   uint32* luv = (uint32*) sp->tbuf;  
    1140               0 :   uint8* rgb = (uint8*) op;
    1141                 : 
    1142               0 :   while (n-- > 0) {
    1143                 :     float xyz[3];
    1144                 : 
    1145               0 :     LogLuv32toXYZ(*luv++, xyz);
    1146               0 :     XYZtoRGB24(xyz, rgb);
    1147               0 :     rgb += 3;
    1148                 :   }
    1149               0 : }
    1150                 : 
    1151                 : static void
    1152               0 : Luv32fromXYZ(LogLuvState* sp, uint8* op, tmsize_t n)
    1153                 : {
    1154               0 :   uint32* luv = (uint32*) sp->tbuf;  
    1155               0 :   float* xyz = (float*) op;
    1156                 : 
    1157               0 :   while (n-- > 0) {
    1158               0 :     *luv++ = LogLuv32fromXYZ(xyz, sp->encode_meth);
    1159               0 :     xyz += 3;
    1160                 :   }
    1161               0 : }
    1162                 : 
    1163                 : static void
    1164               0 : Luv32fromLuv48(LogLuvState* sp, uint8* op, tmsize_t n)
    1165                 : {
    1166               0 :   uint32* luv = (uint32*) sp->tbuf;
    1167               0 :   int16* luv3 = (int16*) op;
    1168                 : 
    1169               0 :   if (sp->encode_meth == SGILOGENCODE_NODITHER) {
    1170               0 :     while (n-- > 0) {
    1171               0 :       *luv++ = (uint32)luv3[0] << 16 |
    1172               0 :         (luv3[1]*(uint32)(UVSCALE+.5) >> 7 & 0xff00) |
    1173               0 :         (luv3[2]*(uint32)(UVSCALE+.5) >> 15 & 0xff);
    1174               0 :       luv3 += 3;
    1175                 :     }
    1176               0 :     return;
    1177                 :   }
    1178               0 :   while (n-- > 0) {
    1179               0 :     *luv++ = (uint32)luv3[0] << 16 |
    1180               0 :   (itrunc(luv3[1]*(UVSCALE/(1<<15)), sp->encode_meth) << 8 & 0xff00) |
    1181               0 :     (itrunc(luv3[2]*(UVSCALE/(1<<15)), sp->encode_meth) & 0xff);
    1182               0 :     luv3 += 3;
    1183                 :   }
    1184                 : }
    1185                 : 
    1186                 : static void
    1187               0 : _logLuvNop(LogLuvState* sp, uint8* op, tmsize_t n)
    1188                 : {
    1189                 :   (void) sp; (void) op; (void) n;
    1190               0 : }
    1191                 : 
    1192                 : static int
    1193               0 : LogL16GuessDataFmt(TIFFDirectory *td)
    1194                 : {
    1195                 : #define PACK(s,b,f) (((b)<<6)|((s)<<3)|(f))
    1196               0 :   switch (PACK(td->td_samplesperpixel, td->td_bitspersample, td->td_sampleformat)) {
    1197                 :   case PACK(1, 32, SAMPLEFORMAT_IEEEFP):
    1198               0 :     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               0 :     return (SGILOGDATAFMT_16BIT);
    1203                 :   case PACK(1,  8, SAMPLEFORMAT_VOID):
    1204                 :   case PACK(1,  8, SAMPLEFORMAT_UINT):
    1205               0 :     return (SGILOGDATAFMT_8BIT);
    1206                 :   }
    1207                 : #undef PACK
    1208               0 :   return (SGILOGDATAFMT_UNKNOWN);
    1209                 : }
    1210                 : 
    1211                 : static tmsize_t
    1212               0 : multiply_ms(tmsize_t m1, tmsize_t m2)
    1213                 : {
    1214               0 :   tmsize_t bytes = m1 * m2;
    1215                 : 
    1216               0 :   if (m1 && bytes / m1 != m2)
    1217               0 :     bytes = 0;
    1218                 : 
    1219               0 :   return bytes;
    1220                 : }
    1221                 : 
    1222                 : static int
    1223               0 : LogL16InitState(TIFF* tif)
    1224                 : {
    1225                 :   static const char module[] = "LogL16InitState";
    1226               0 :   TIFFDirectory *td = &tif->tif_dir;
    1227               0 :   LogLuvState* sp = DecoderState(tif);
    1228                 : 
    1229               0 :   assert(sp != NULL);
    1230               0 :   assert(td->td_photometric == PHOTOMETRIC_LOGL);
    1231                 : 
    1232                 :   /* for some reason, we can't do this in TIFFInitLogL16 */
    1233               0 :   if (sp->user_datafmt == SGILOGDATAFMT_UNKNOWN)
    1234               0 :     sp->user_datafmt = LogL16GuessDataFmt(td);
    1235               0 :   switch (sp->user_datafmt) {
    1236                 :   case SGILOGDATAFMT_FLOAT:
    1237               0 :     sp->pixel_size = sizeof (float);
    1238               0 :     break;
    1239                 :   case SGILOGDATAFMT_16BIT:
    1240               0 :     sp->pixel_size = sizeof (int16);
    1241               0 :     break;
    1242                 :   case SGILOGDATAFMT_8BIT:
    1243               0 :     sp->pixel_size = sizeof (uint8);
    1244               0 :     break;
    1245                 :   default:
    1246               0 :     TIFFErrorExt(tif->tif_clientdata, module,
    1247                 :         "No support for converting user data format to LogL");
    1248               0 :     return (0);
    1249                 :   }
    1250               0 :         if( isTiled(tif) )
    1251               0 :             sp->tbuflen = multiply_ms(td->td_tilewidth, td->td_tilelength);
    1252                 :         else
    1253               0 :             sp->tbuflen = multiply_ms(td->td_imagewidth, td->td_rowsperstrip);
    1254               0 :   if (multiply_ms(sp->tbuflen, sizeof (int16)) == 0 ||
    1255               0 :       (sp->tbuf = (uint8*) _TIFFmalloc(sp->tbuflen * sizeof (int16))) == NULL) {
    1256               0 :     TIFFErrorExt(tif->tif_clientdata, module, "No space for SGILog translation buffer");
    1257               0 :     return (0);
    1258                 :   }
    1259               0 :   return (1);
    1260                 : }
    1261                 : 
    1262                 : static int
    1263               0 : 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               0 :   switch (PACK(td->td_bitspersample, td->td_sampleformat)) {
    1273                 :   case PACK(32, SAMPLEFORMAT_IEEEFP):
    1274               0 :     guess = SGILOGDATAFMT_FLOAT;
    1275               0 :     break;
    1276                 :   case PACK(32, SAMPLEFORMAT_VOID):
    1277                 :   case PACK(32, SAMPLEFORMAT_UINT):
    1278                 :   case PACK(32, SAMPLEFORMAT_INT):
    1279               0 :     guess = SGILOGDATAFMT_RAW;
    1280               0 :     break;
    1281                 :   case PACK(16, SAMPLEFORMAT_VOID):
    1282                 :   case PACK(16, SAMPLEFORMAT_INT):
    1283                 :   case PACK(16, SAMPLEFORMAT_UINT):
    1284               0 :     guess = SGILOGDATAFMT_16BIT;
    1285               0 :     break;
    1286                 :   case PACK( 8, SAMPLEFORMAT_VOID):
    1287                 :   case PACK( 8, SAMPLEFORMAT_UINT):
    1288               0 :     guess = SGILOGDATAFMT_8BIT;
    1289               0 :     break;
    1290                 :   default:
    1291               0 :     guess = SGILOGDATAFMT_UNKNOWN;
    1292                 :     break;
    1293                 : #undef PACK
    1294                 :   }
    1295                 :   /*
    1296                 :    * Double-check samples per pixel.
    1297                 :    */
    1298               0 :   switch (td->td_samplesperpixel) {
    1299                 :   case 1:
    1300               0 :     if (guess != SGILOGDATAFMT_RAW)
    1301               0 :       guess = SGILOGDATAFMT_UNKNOWN;
    1302               0 :     break;
    1303                 :   case 3:
    1304               0 :     if (guess == SGILOGDATAFMT_RAW)
    1305               0 :       guess = SGILOGDATAFMT_UNKNOWN;
    1306               0 :     break;
    1307                 :   default:
    1308               0 :     guess = SGILOGDATAFMT_UNKNOWN;
    1309                 :     break;
    1310                 :   }
    1311               0 :   return (guess);
    1312                 : }
    1313                 : 
    1314                 : static int
    1315               0 : LogLuvInitState(TIFF* tif)
    1316                 : {
    1317                 :   static const char module[] = "LogLuvInitState";
    1318               0 :   TIFFDirectory* td = &tif->tif_dir;
    1319               0 :   LogLuvState* sp = DecoderState(tif);
    1320                 : 
    1321               0 :   assert(sp != NULL);
    1322               0 :   assert(td->td_photometric == PHOTOMETRIC_LOGLUV);
    1323                 : 
    1324                 :   /* for some reason, we can't do this in TIFFInitLogLuv */
    1325               0 :   if (td->td_planarconfig != PLANARCONFIG_CONTIG) {
    1326               0 :     TIFFErrorExt(tif->tif_clientdata, module,
    1327                 :         "SGILog compression cannot handle non-contiguous data");
    1328               0 :     return (0);
    1329                 :   }
    1330               0 :   if (sp->user_datafmt == SGILOGDATAFMT_UNKNOWN)
    1331               0 :     sp->user_datafmt = LogLuvGuessDataFmt(td);
    1332               0 :   switch (sp->user_datafmt) {
    1333                 :   case SGILOGDATAFMT_FLOAT:
    1334               0 :     sp->pixel_size = 3*sizeof (float);
    1335               0 :     break;
    1336                 :   case SGILOGDATAFMT_16BIT:
    1337               0 :     sp->pixel_size = 3*sizeof (int16);
    1338               0 :     break;
    1339                 :   case SGILOGDATAFMT_RAW:
    1340               0 :     sp->pixel_size = sizeof (uint32);
    1341               0 :     break;
    1342                 :   case SGILOGDATAFMT_8BIT:
    1343               0 :     sp->pixel_size = 3*sizeof (uint8);
    1344               0 :     break;
    1345                 :   default:
    1346               0 :     TIFFErrorExt(tif->tif_clientdata, module,
    1347                 :         "No support for converting user data format to LogLuv");
    1348               0 :     return (0);
    1349                 :   }
    1350               0 :         if( isTiled(tif) )
    1351               0 :             sp->tbuflen = multiply_ms(td->td_tilewidth, td->td_tilelength);
    1352                 :         else
    1353               0 :             sp->tbuflen = multiply_ms(td->td_imagewidth, td->td_rowsperstrip);
    1354               0 :   if (multiply_ms(sp->tbuflen, sizeof (uint32)) == 0 ||
    1355               0 :       (sp->tbuf = (uint8*) _TIFFmalloc(sp->tbuflen * sizeof (uint32))) == NULL) {
    1356               0 :     TIFFErrorExt(tif->tif_clientdata, module, "No space for SGILog translation buffer");
    1357               0 :     return (0);
    1358                 :   }
    1359               0 :   return (1);
    1360                 : }
    1361                 : 
    1362                 : static int
    1363               0 : LogLuvFixupTags(TIFF* tif)
    1364                 : {
    1365                 :   (void) tif;
    1366               0 :   return (1);
    1367                 : }
    1368                 : 
    1369                 : static int
    1370               0 : LogLuvSetupDecode(TIFF* tif)
    1371                 : {
    1372                 :   static const char module[] = "LogLuvSetupDecode";
    1373               0 :   LogLuvState* sp = DecoderState(tif);
    1374               0 :   TIFFDirectory* td = &tif->tif_dir;
    1375                 : 
    1376               0 :   tif->tif_postdecode = _TIFFNoPostDecode;
    1377               0 :   switch (td->td_photometric) {
    1378                 :   case PHOTOMETRIC_LOGLUV:
    1379               0 :     if (!LogLuvInitState(tif))
    1380               0 :       break;
    1381               0 :     if (td->td_compression == COMPRESSION_SGILOG24) {
    1382               0 :       tif->tif_decoderow = LogLuvDecode24;
    1383               0 :       switch (sp->user_datafmt) {
    1384                 :       case SGILOGDATAFMT_FLOAT:
    1385               0 :         sp->tfunc = Luv24toXYZ;  
    1386               0 :         break;
    1387                 :       case SGILOGDATAFMT_16BIT:
    1388               0 :         sp->tfunc = Luv24toLuv48;  
    1389               0 :         break;
    1390                 :       case SGILOGDATAFMT_8BIT:
    1391               0 :         sp->tfunc = Luv24toRGB;
    1392                 :         break;
    1393                 :       }
    1394                 :     } else {
    1395               0 :       tif->tif_decoderow = LogLuvDecode32;
    1396               0 :       switch (sp->user_datafmt) {
    1397                 :       case SGILOGDATAFMT_FLOAT:
    1398               0 :         sp->tfunc = Luv32toXYZ;
    1399               0 :         break;
    1400                 :       case SGILOGDATAFMT_16BIT:
    1401               0 :         sp->tfunc = Luv32toLuv48;
    1402               0 :         break;
    1403                 :       case SGILOGDATAFMT_8BIT:
    1404               0 :         sp->tfunc = Luv32toRGB;
    1405                 :         break;
    1406                 :       }
    1407                 :     }
    1408               0 :     return (1);
    1409                 :   case PHOTOMETRIC_LOGL:
    1410               0 :     if (!LogL16InitState(tif))
    1411               0 :       break;
    1412               0 :     tif->tif_decoderow = LogL16Decode;
    1413               0 :     switch (sp->user_datafmt) {
    1414                 :     case SGILOGDATAFMT_FLOAT:
    1415               0 :       sp->tfunc = L16toY;
    1416               0 :       break;
    1417                 :     case SGILOGDATAFMT_8BIT:
    1418               0 :       sp->tfunc = L16toGry;
    1419                 :       break;
    1420                 :     }
    1421               0 :     return (1);
    1422                 :   default:
    1423               0 :     TIFFErrorExt(tif->tif_clientdata, module,
    1424                 :         "Inappropriate photometric interpretation %d for SGILog compression; %s",
    1425               0 :         td->td_photometric, "must be either LogLUV or LogL");
    1426                 :     break;
    1427                 :   }
    1428               0 :   return (0);
    1429                 : }
    1430                 : 
    1431                 : static int
    1432               0 : LogLuvSetupEncode(TIFF* tif)
    1433                 : {
    1434                 :   static const char module[] = "LogLuvSetupEncode";
    1435               0 :   LogLuvState* sp = EncoderState(tif);
    1436               0 :   TIFFDirectory* td = &tif->tif_dir;
    1437                 : 
    1438               0 :   switch (td->td_photometric) {
    1439                 :   case PHOTOMETRIC_LOGLUV:
    1440               0 :     if (!LogLuvInitState(tif))
    1441               0 :       break;
    1442               0 :     if (td->td_compression == COMPRESSION_SGILOG24) {
    1443               0 :       tif->tif_encoderow = LogLuvEncode24;
    1444               0 :       switch (sp->user_datafmt) {
    1445                 :       case SGILOGDATAFMT_FLOAT:
    1446               0 :         sp->tfunc = Luv24fromXYZ;
    1447               0 :         break;
    1448                 :       case SGILOGDATAFMT_16BIT:
    1449               0 :         sp->tfunc = Luv24fromLuv48;  
    1450               0 :         break;
    1451                 :       case SGILOGDATAFMT_RAW:
    1452               0 :         break;
    1453                 :       default:
    1454               0 :         goto notsupported;
    1455                 :       }
    1456                 :     } else {
    1457               0 :       tif->tif_encoderow = LogLuvEncode32;  
    1458               0 :       switch (sp->user_datafmt) {
    1459                 :       case SGILOGDATAFMT_FLOAT:
    1460               0 :         sp->tfunc = Luv32fromXYZ;  
    1461               0 :         break;
    1462                 :       case SGILOGDATAFMT_16BIT:
    1463               0 :         sp->tfunc = Luv32fromLuv48;  
    1464               0 :         break;
    1465                 :       case SGILOGDATAFMT_RAW:
    1466               0 :         break;
    1467                 :       default:
    1468               0 :         goto notsupported;
    1469                 :       }
    1470                 :     }
    1471               0 :     break;
    1472                 :   case PHOTOMETRIC_LOGL:
    1473               0 :     if (!LogL16InitState(tif))
    1474               0 :       break;
    1475               0 :     tif->tif_encoderow = LogL16Encode;  
    1476               0 :     switch (sp->user_datafmt) {
    1477                 :     case SGILOGDATAFMT_FLOAT:
    1478               0 :       sp->tfunc = L16fromY;
    1479               0 :       break;
    1480                 :     case SGILOGDATAFMT_16BIT:
    1481               0 :       break;
    1482                 :     default:
    1483               0 :       goto notsupported;
    1484                 :     }
    1485               0 :     break;
    1486                 :   default:
    1487               0 :     TIFFErrorExt(tif->tif_clientdata, module,
    1488                 :         "Inappropriate photometric interpretation %d for SGILog compression; %s",
    1489               0 :         td->td_photometric, "must be either LogLUV or LogL");
    1490                 :     break;
    1491                 :   }
    1492               0 :   return (1);
    1493                 : notsupported:
    1494               0 :   TIFFErrorExt(tif->tif_clientdata, module,
    1495                 :       "SGILog compression supported only for %s, or raw data",
    1496               0 :       td->td_photometric == PHOTOMETRIC_LOGL ? "Y, L" : "XYZ, Luv");
    1497               0 :   return (0);
    1498                 : }
    1499                 : 
    1500                 : static void
    1501               0 : LogLuvClose(TIFF* tif)
    1502                 : {
    1503               0 :   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               0 :   td->td_samplesperpixel =
    1513               0 :       (td->td_photometric == PHOTOMETRIC_LOGL) ? 1 : 3;
    1514               0 :   td->td_bitspersample = 16;
    1515               0 :   td->td_sampleformat = SAMPLEFORMAT_INT;
    1516               0 : }
    1517                 : 
    1518                 : static void
    1519               0 : LogLuvCleanup(TIFF* tif)
    1520                 : {
    1521               0 :   LogLuvState* sp = (LogLuvState *)tif->tif_data;
    1522                 : 
    1523               0 :   assert(sp != 0);
    1524                 : 
    1525               0 :   tif->tif_tagmethods.vgetfield = sp->vgetparent;
    1526               0 :   tif->tif_tagmethods.vsetfield = sp->vsetparent;
    1527                 : 
    1528               0 :   if (sp->tbuf)
    1529               0 :     _TIFFfree(sp->tbuf);
    1530               0 :   _TIFFfree(sp);
    1531               0 :   tif->tif_data = NULL;
    1532                 : 
    1533               0 :   _TIFFSetDefaultCompressionState(tif);
    1534               0 : }
    1535                 : 
    1536                 : static int
    1537               0 : LogLuvVSetField(TIFF* tif, uint32 tag, va_list ap)
    1538                 : {
    1539                 :   static const char module[] = "LogLuvVSetField";
    1540               0 :   LogLuvState* sp = DecoderState(tif);
    1541                 :   int bps, fmt;
    1542                 : 
    1543               0 :   switch (tag) {
    1544                 :   case TIFFTAG_SGILOGDATAFMT:
    1545               0 :     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               0 :     switch (sp->user_datafmt) {
    1553                 :     case SGILOGDATAFMT_FLOAT:
    1554               0 :       bps = 32, fmt = SAMPLEFORMAT_IEEEFP;
    1555               0 :       break;
    1556                 :     case SGILOGDATAFMT_16BIT:
    1557               0 :       bps = 16, fmt = SAMPLEFORMAT_INT;
    1558               0 :       break;
    1559                 :     case SGILOGDATAFMT_RAW:
    1560               0 :       bps = 32, fmt = SAMPLEFORMAT_UINT;
    1561               0 :       TIFFSetField(tif, TIFFTAG_SAMPLESPERPIXEL, 1);
    1562               0 :       break;
    1563                 :     case SGILOGDATAFMT_8BIT:
    1564               0 :       bps = 8, fmt = SAMPLEFORMAT_UINT;
    1565               0 :       break;
    1566                 :     default:
    1567               0 :       TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
    1568                 :           "Unknown data format %d for LogLuv compression",
    1569                 :           sp->user_datafmt);
    1570               0 :       return (0);
    1571                 :     }
    1572               0 :     TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps);
    1573               0 :     TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, fmt);
    1574                 :     /*
    1575                 :      * Must recalculate sizes should bits/sample change.
    1576                 :      */
    1577               0 :     tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tmsize_t) -1;
    1578               0 :     tif->tif_scanlinesize = TIFFScanlineSize(tif);
    1579               0 :     return (1);
    1580                 :   case TIFFTAG_SGILOGENCODE:
    1581               0 :     sp->encode_meth = (int) va_arg(ap, int);
    1582               0 :     if (sp->encode_meth != SGILOGENCODE_NODITHER &&
    1583               0 :         sp->encode_meth != SGILOGENCODE_RANDITHER) {
    1584               0 :       TIFFErrorExt(tif->tif_clientdata, module,
    1585                 :           "Unknown encoding %d for LogLuv compression",
    1586                 :           sp->encode_meth);
    1587               0 :       return (0);
    1588                 :     }
    1589               0 :     return (1);
    1590                 :   default:
    1591               0 :     return (*sp->vsetparent)(tif, tag, ap);
    1592                 :   }
    1593                 : }
    1594                 : 
    1595                 : static int
    1596               0 : LogLuvVGetField(TIFF* tif, uint32 tag, va_list ap)
    1597                 : {
    1598               0 :   LogLuvState *sp = (LogLuvState *)tif->tif_data;
    1599                 : 
    1600               0 :   switch (tag) {
    1601                 :   case TIFFTAG_SGILOGDATAFMT:
    1602               0 :     *va_arg(ap, int*) = sp->user_datafmt;
    1603               0 :     return (1);
    1604                 :   default:
    1605               0 :     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               0 : TIFFInitSGILog(TIFF* tif, int scheme)
    1616                 : {
    1617                 :   static const char module[] = "TIFFInitSGILog";
    1618                 :   LogLuvState* sp;
    1619                 : 
    1620               0 :   assert(scheme == COMPRESSION_SGILOG24 || scheme == COMPRESSION_SGILOG);
    1621                 : 
    1622                 :   /*
    1623                 :    * Merge codec-specific tag information.
    1624                 :    */
    1625               0 :   if (!_TIFFMergeFields(tif, LogLuvFields,
    1626                 :             TIFFArrayCount(LogLuvFields))) {
    1627               0 :     TIFFErrorExt(tif->tif_clientdata, module,
    1628                 :         "Merging SGILog codec-specific tags failed");
    1629               0 :     return 0;
    1630                 :   }
    1631                 : 
    1632                 :   /*
    1633                 :    * Allocate state block so tag methods have storage to record values.
    1634                 :    */
    1635               0 :   tif->tif_data = (uint8*) _TIFFmalloc(sizeof (LogLuvState));
    1636               0 :   if (tif->tif_data == NULL)
    1637               0 :     goto bad;
    1638               0 :   sp = (LogLuvState*) tif->tif_data;
    1639               0 :   _TIFFmemset((void*)sp, 0, sizeof (*sp));
    1640               0 :   sp->user_datafmt = SGILOGDATAFMT_UNKNOWN;
    1641               0 :   sp->encode_meth = (scheme == COMPRESSION_SGILOG24) ?
    1642                 :       SGILOGENCODE_RANDITHER : SGILOGENCODE_NODITHER;
    1643               0 :   sp->tfunc = _logLuvNop;
    1644                 : 
    1645                 :   /*
    1646                 :    * Install codec methods.
    1647                 :    * NB: tif_decoderow & tif_encoderow are filled
    1648                 :    *     in at setup time.
    1649                 :    */
    1650               0 :   tif->tif_fixuptags = LogLuvFixupTags;  
    1651               0 :   tif->tif_setupdecode = LogLuvSetupDecode;
    1652               0 :   tif->tif_decodestrip = LogLuvDecodeStrip;
    1653               0 :   tif->tif_decodetile = LogLuvDecodeTile;
    1654               0 :   tif->tif_setupencode = LogLuvSetupEncode;
    1655               0 :   tif->tif_encodestrip = LogLuvEncodeStrip;  
    1656               0 :   tif->tif_encodetile = LogLuvEncodeTile;
    1657               0 :   tif->tif_close = LogLuvClose;
    1658               0 :   tif->tif_cleanup = LogLuvCleanup;
    1659                 : 
    1660                 :   /*
    1661                 :    * Override parent get/set field methods.
    1662                 :    */
    1663               0 :   sp->vgetparent = tif->tif_tagmethods.vgetfield;
    1664               0 :   tif->tif_tagmethods.vgetfield = LogLuvVGetField;   /* hook for codec tags */
    1665               0 :   sp->vsetparent = tif->tif_tagmethods.vsetfield;
    1666               0 :   tif->tif_tagmethods.vsetfield = LogLuvVSetField;   /* hook for codec tags */
    1667                 : 
    1668               0 :   return (1);
    1669                 : bad:
    1670               0 :   TIFFErrorExt(tif->tif_clientdata, module,
    1671                 :          "%s: No space for LogLuv state block", tif->tif_name);
    1672               0 :   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                 :  */

Generated by: LCOV version 1.7