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