| 1 | /* |
| 2 | * Copyright (c) 1997 Greg Ward Larson |
| 3 | * Copyright (c) 1997 Silicon Graphics, Inc. |
| 4 | * |
| 5 | * Permission to use, copy, modify, distribute, and sell this software and |
| 6 | * its documentation for any purpose is hereby granted without fee, provided |
| 7 | * that (i) the above copyright notices and this permission notice appear in |
| 8 | * all copies of the software and related documentation, and (ii) the names of |
| 9 | * Sam Leffler, Greg Larson and Silicon Graphics may not be used in any |
| 10 | * advertising or publicity relating to the software without the specific, |
| 11 | * prior written permission of Sam Leffler, Greg Larson and Silicon Graphics. |
| 12 | * |
| 13 | * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, |
| 14 | * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY |
| 15 | * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. |
| 16 | * |
| 17 | * IN NO EVENT SHALL SAM LEFFLER, GREG LARSON OR SILICON GRAPHICS BE LIABLE |
| 18 | * FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, |
| 19 | * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, |
| 20 | * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF |
| 21 | * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE |
| 22 | * OF THIS SOFTWARE. |
| 23 | */ |
| 24 | |
| 25 | #include "tiffiop.h" |
| 26 | #ifdef LOGLUV_SUPPORT |
| 27 | |
| 28 | /* |
| 29 | * TIFF Library. |
| 30 | * LogLuv compression support for high dynamic range images. |
| 31 | * |
| 32 | * Contributed by Greg Larson. |
| 33 | * |
| 34 | * LogLuv image support uses the TIFF library to store 16 or 10-bit |
| 35 | * log luminance values with 8 bits each of u and v or a 14-bit index. |
| 36 | * |
| 37 | * The codec can take as input and produce as output 32-bit IEEE float values |
| 38 | * as well as 16-bit integer values. A 16-bit luminance is interpreted |
| 39 | * as a sign bit followed by a 15-bit integer that is converted |
| 40 | * to and from a linear magnitude using the transformation: |
| 41 | * |
| 42 | * L = 2^( (Le+.5)/256 - 64 ) # real from 15-bit |
| 43 | * |
| 44 | * Le = floor( 256*(log2(L) + 64) ) # 15-bit from real |
| 45 | * |
| 46 | * The actual conversion to world luminance units in candelas per sq. meter |
| 47 | * requires an additional multiplier, which is stored in the TIFFTAG_STONITS. |
| 48 | * This value is usually set such that a reasonable exposure comes from |
| 49 | * clamping decoded luminances above 1 to 1 in the displayed image. |
| 50 | * |
| 51 | * The 16-bit values for u and v may be converted to real values by dividing |
| 52 | * each by 32768. (This allows for negative values, which aren't useful as |
| 53 | * far as we know, but are left in case of future improvements in human |
| 54 | * color vision.) |
| 55 | * |
| 56 | * Conversion from (u,v), which is actually the CIE (u',v') system for |
| 57 | * you color scientists, is accomplished by the following transformation: |
| 58 | * |
| 59 | * u = 4*x / (-2*x + 12*y + 3) |
| 60 | * v = 9*y / (-2*x + 12*y + 3) |
| 61 | * |
| 62 | * x = 9*u / (6*u - 16*v + 12) |
| 63 | * y = 4*v / (6*u - 16*v + 12) |
| 64 | * |
| 65 | * This process is greatly simplified by passing 32-bit IEEE floats |
| 66 | * for each of three CIE XYZ coordinates. The codec then takes care |
| 67 | * of conversion to and from LogLuv, though the application is still |
| 68 | * responsible for interpreting the TIFFTAG_STONITS calibration factor. |
| 69 | * |
| 70 | * The information is compressed into one of two basic encodings, depending on |
| 71 | * the setting of the compression tag, which is one of COMPRESSION_SGILOG |
| 72 | * or COMPRESSION_SGILOG24. For COMPRESSION_SGILOG, greyscale data is |
| 73 | * stored as: |
| 74 | * |
| 75 | * 1 15 |
| 76 | * |-+---------------| |
| 77 | * |
| 78 | * COMPRESSION_SGILOG color data is stored as: |
| 79 | * |
| 80 | * 1 15 8 8 |
| 81 | * |-+---------------|--------+--------| |
| 82 | * S Le ue ve |
| 83 | * |
| 84 | * For the 24-bit COMPRESSION_SGILOG24 color format, the data is stored as: |
| 85 | * |
| 86 | * 10 14 |
| 87 | * |----------|--------------| |
| 88 | * Le' Ce |
| 89 | * |
| 90 | * There is no sign bit in the 24-bit case, and the (u,v) chromaticity is |
| 91 | * encoded as an index for optimal color resolution. The 10 log bits are |
| 92 | * defined by the following conversions: |
| 93 | * |
| 94 | * L = 2^((Le'+.5)/64 - 12) # real from 10-bit |
| 95 | * |
| 96 | * Le' = floor( 64*(log2(L) + 12) ) # 10-bit from real |
| 97 | * |
| 98 | * The 10 bits of the smaller format may be converted into the 15 bits of |
| 99 | * the larger format by multiplying by 4 and adding 13314. Obviously, |
| 100 | * a smaller range of magnitudes is covered (about 5 orders of magnitude |
| 101 | * instead of 38), and the lack of a sign bit means that negative luminances |
| 102 | * are not allowed. (Well, they aren't allowed in the real world, either, |
| 103 | * but they are useful for certain types of image processing.) |
| 104 | * |
| 105 | * The desired user format is controlled by the setting the internal |
| 106 | * pseudo tag TIFFTAG_SGILOGDATAFMT to one of: |
| 107 | * SGILOGDATAFMT_FLOAT = IEEE 32-bit float XYZ values |
| 108 | * SGILOGDATAFMT_16BIT = 16-bit integer encodings of logL, u and v |
| 109 | * Raw data i/o is also possible using: |
| 110 | * SGILOGDATAFMT_RAW = 32-bit unsigned integer with encoded pixel |
| 111 | * In addition, the following decoding is provided for ease of display: |
| 112 | * SGILOGDATAFMT_8BIT = 8-bit default RGB gamma-corrected values |
| 113 | * |
| 114 | * For grayscale images, we provide the following data formats: |
| 115 | * SGILOGDATAFMT_FLOAT = IEEE 32-bit float Y values |
| 116 | * SGILOGDATAFMT_16BIT = 16-bit integer w/ encoded luminance |
| 117 | * SGILOGDATAFMT_8BIT = 8-bit gray monitor values |
| 118 | * |
| 119 | * Note that the COMPRESSION_SGILOG applies a simple run-length encoding |
| 120 | * scheme by separating the logL, u and v bytes for each row and applying |
| 121 | * a PackBits type of compression. Since the 24-bit encoding is not |
| 122 | * adaptive, the 32-bit color format takes less space in many cases. |
| 123 | */ |
| 124 | |
| 125 | #include <stdio.h> |
| 126 | #include <assert.h> |
| 127 | #include <stdlib.h> |
| 128 | #include <math.h> |
| 129 | |
| 130 | /* |
| 131 | * State block for each open TIFF |
| 132 | * file using LogLuv compression/decompression. |
| 133 | */ |
| 134 | typedef struct logLuvState LogLuvState; |
| 135 | |
| 136 | struct logLuvState { |
| 137 | int user_datafmt; /* user data format */ |
| 138 | int pixel_size; /* bytes per pixel */ |
| 139 | |
| 140 | tidata_t* tbuf; /* translation buffer */ |
| 141 | short tbuflen; /* buffer length */ |
| 142 | void (*tfunc)(LogLuvState*, tidata_t, int); |
| 143 | |
| 144 | TIFFVSetMethod vgetparent; /* super-class method */ |
| 145 | TIFFVSetMethod vsetparent; /* super-class method */ |
| 146 | }; |
| 147 | |
| 148 | #define DecoderState(tif) ((LogLuvState*) (tif)->tif_data) |
| 149 | #define EncoderState(tif) ((LogLuvState*) (tif)->tif_data) |
| 150 | |
| 151 | #define N(a) (sizeof(a)/sizeof(a[0])) |
| 152 | #define SGILOGDATAFMT_UNKNOWN -1 |
| 153 | |
| 154 | #define MINRUN 4 /* minimum run length */ |
| 155 | |
| 156 | /* |
| 157 | * Decode a string of 16-bit gray pixels. |
| 158 | */ |
| 159 | static int LINKAGEMODE |
| 160 | LogL16Decode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s) |
| 161 | { |
| 162 | LogLuvState* sp = DecoderState(tif); |
| 163 | int shft, i, npixels; |
| 164 | u_char* bp; |
| 165 | int16* tp; |
| 166 | int16 b; |
| 167 | int cc, rc; |
| 168 | |
| 169 | assert(s == 0); |
| 170 | assert(sp != NULL); |
| 171 | |
| 172 | npixels = occ / sp->pixel_size; |
| 173 | |
| 174 | if (sp->user_datafmt == SGILOGDATAFMT_16BIT) |
| 175 | tp = (int16*) op; |
| 176 | else { |
| 177 | assert(sp->tbuflen >= npixels); |
| 178 | tp = (int16*) sp->tbuf; |
| 179 | } |
| 180 | _TIFFmemset((tdata_t) tp, 0, npixels*sizeof (tp[0])); |
| 181 | |
| 182 | bp = (u_char*) tif->tif_rawcp; |
| 183 | cc = tif->tif_rawcc; |
| 184 | /* get each byte string */ |
| 185 | for (shft = 2*8; (shft -= 8) >= 0; ) { |
| 186 | for (i = 0; i < npixels && cc > 0; ) |
| 187 | if (*bp >= 128) { /* run */ |
| 188 | rc = *bp++ + (2-128); |
| 189 | b = (int16)*bp++ << shft; |
| 190 | cc -= 2; |
| 191 | while (rc--) |
| 192 | tp[i++] |= b; |
| 193 | } else { /* non-run */ |
| 194 | rc = *bp++; /* nul is noop */ |
| 195 | while (--cc && rc--) |
| 196 | tp[i++] |= (int16)*bp++ << shft; |
| 197 | } |
| 198 | if (i != npixels) { |
| 199 | TIFFError(tif->tif_name, |
| 200 | "LogL16Decode: Not enough data at row %d (short %d pixels)", |
| 201 | tif->tif_row, npixels - i); |
| 202 | tif->tif_rawcp = (tidata_t) bp; |
| 203 | tif->tif_rawcc = cc; |
| 204 | return (0); |
| 205 | } |
| 206 | } |
| 207 | (*sp->tfunc)(sp, op, npixels); |
| 208 | tif->tif_rawcp = (tidata_t) bp; |
| 209 | tif->tif_rawcc = cc; |
| 210 | return (1); |
| 211 | } |
| 212 | |
| 213 | /* |
| 214 | * Decode a string of 24-bit pixels. |
| 215 | */ |
| 216 | static int LINKAGEMODE |
| 217 | LogLuvDecode24(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s) |
| 218 | { |
| 219 | LogLuvState* sp = DecoderState(tif); |
| 220 | int cc, i, npixels; |
| 221 | u_char* bp; |
| 222 | uint32* tp; |
| 223 | |
| 224 | assert(s == 0); |
| 225 | assert(sp != NULL); |
| 226 | |
| 227 | npixels = occ / sp->pixel_size; |
| 228 | |
| 229 | if (sp->user_datafmt == SGILOGDATAFMT_RAW) |
| 230 | tp = (uint32 *)op; |
| 231 | else { |
| 232 | assert(sp->tbuflen >= npixels); |
| 233 | tp = (uint32 *) sp->tbuf; |
| 234 | } |
| 235 | _TIFFmemset((tdata_t) tp, 0, npixels*sizeof (tp[0])); |
| 236 | /* copy to array of uint32 */ |
| 237 | bp = (u_char*) tif->tif_rawcp; |
| 238 | cc = tif->tif_rawcc; |
| 239 | for (i = 0; i < npixels && cc > 0; i++) { |
| 240 | tp[i] = bp[0] << 16 | bp[1] << 8 | bp[2]; |
| 241 | bp += 3; |
| 242 | cc -= 3; |
| 243 | } |
| 244 | tif->tif_rawcp = (tidata_t) bp; |
| 245 | tif->tif_rawcc = cc; |
| 246 | if (i != npixels) { |
| 247 | TIFFError(tif->tif_name, |
| 248 | "LogLuvDecode24: Not enough data at row %d (short %d pixels)", |
| 249 | tif->tif_row, npixels - i); |
| 250 | return (0); |
| 251 | } |
| 252 | (*sp->tfunc)(sp, op, npixels); |
| 253 | return (1); |
| 254 | } |
| 255 | |
| 256 | /* |
| 257 | * Decode a string of 32-bit pixels. |
| 258 | */ |
| 259 | static int LINKAGEMODE |
| 260 | LogLuvDecode32(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s) |
| 261 | { |
| 262 | LogLuvState* sp; |
| 263 | int shft, i, npixels; |
| 264 | u_char* bp; |
| 265 | uint32* tp; |
| 266 | uint32 b; |
| 267 | int cc, rc; |
| 268 | |
| 269 | assert(s == 0); |
| 270 | sp = DecoderState(tif); |
| 271 | assert(sp != NULL); |
| 272 | |
| 273 | npixels = occ / sp->pixel_size; |
| 274 | |
| 275 | if (sp->user_datafmt == SGILOGDATAFMT_RAW) |
| 276 | tp = (uint32*) op; |
| 277 | else { |
| 278 | assert(sp->tbuflen >= npixels); |
| 279 | tp = (uint32*) sp->tbuf; |
| 280 | } |
| 281 | _TIFFmemset((tdata_t) tp, 0, npixels*sizeof (tp[0])); |
| 282 | |
| 283 | bp = (u_char*) tif->tif_rawcp; |
| 284 | cc = tif->tif_rawcc; |
| 285 | /* get each byte string */ |
| 286 | for (shft = 4*8; (shft -= 8) >= 0; ) { |
| 287 | for (i = 0; i < npixels && cc > 0; ) |
| 288 | if (*bp >= 128) { /* run */ |
| 289 | rc = *bp++ + (2-128); |
| 290 | b = (uint32)*bp++ << shft; |
| 291 | cc -= 2; |
| 292 | while (rc--) |
| 293 | tp[i++] |= b; |
| 294 | } else { /* non-run */ |
| 295 | rc = *bp++; /* nul is noop */ |
| 296 | while (--cc && rc--) |
| 297 | tp[i++] |= (uint32)*bp++ << shft; |
| 298 | } |
| 299 | if (i != npixels) { |
| 300 | TIFFError(tif->tif_name, |
| 301 | "LogLuvDecode32: Not enough data at row %d (short %d pixels)", |
| 302 | tif->tif_row, npixels - i); |
| 303 | tif->tif_rawcp = (tidata_t) bp; |
| 304 | tif->tif_rawcc = cc; |
| 305 | return (0); |
| 306 | } |
| 307 | } |
| 308 | (*sp->tfunc)(sp, op, npixels); |
| 309 | tif->tif_rawcp = (tidata_t) bp; |
| 310 | tif->tif_rawcc = cc; |
| 311 | return (1); |
| 312 | } |
| 313 | |
| 314 | /* |
| 315 | * Decode a strip of pixels. We break it into rows to |
| 316 | * maintain synchrony with the encode algorithm, which |
| 317 | * is row by row. |
| 318 | */ |
| 319 | static int LINKAGEMODE |
| 320 | LogLuvDecodeStrip(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) |
| 321 | { |
| 322 | tsize_t rowlen = TIFFScanlineSize(tif); |
| 323 | |
| 324 | assert(cc%rowlen == 0); |
| 325 | while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s)) |
| 326 | bp += rowlen, cc -= rowlen; |
| 327 | return (cc == 0); |
| 328 | } |
| 329 | |
| 330 | /* |
| 331 | * Decode a tile of pixels. We break it into rows to |
| 332 | * maintain synchrony with the encode algorithm, which |
| 333 | * is row by row. |
| 334 | */ |
| 335 | static int LINKAGEMODE |
| 336 | LogLuvDecodeTile(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) |
| 337 | { |
| 338 | tsize_t rowlen = TIFFTileRowSize(tif); |
| 339 | |
| 340 | assert(cc%rowlen == 0); |
| 341 | while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s)) |
| 342 | bp += rowlen, cc -= rowlen; |
| 343 | return (cc == 0); |
| 344 | } |
| 345 | |
| 346 | /* |
| 347 | * Encode a row of 16-bit pixels. |
| 348 | */ |
| 349 | static int LINKAGEMODE |
| 350 | LogL16Encode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) |
| 351 | { |
| 352 | LogLuvState* sp = EncoderState(tif); |
| 353 | int shft, i, j, npixels; |
| 354 | tidata_t op; |
| 355 | int16* tp; |
| 356 | int16 b; |
| 357 | int occ, rc=0, mask, beg; |
| 358 | |
| 359 | assert(s == 0); |
| 360 | assert(sp != NULL); |
| 361 | npixels = cc / sp->pixel_size; |
| 362 | |
| 363 | if (sp->user_datafmt == SGILOGDATAFMT_16BIT) |
| 364 | tp = (int16*) bp; |
| 365 | else { |
| 366 | tp = (int16*) sp->tbuf; |
| 367 | assert(sp->tbuflen >= npixels); |
| 368 | (*sp->tfunc)(sp, bp, npixels); |
| 369 | } |
| 370 | /* compress each byte string */ |
| 371 | op = tif->tif_rawcp; |
| 372 | occ = tif->tif_rawdatasize - tif->tif_rawcc; |
| 373 | for (shft = 2*8; (shft -= 8) >= 0; ) |
| 374 | for (i = 0; i < npixels; i += rc) { |
| 375 | if (occ < 4) { |
| 376 | tif->tif_rawcp = op; |
| 377 | tif->tif_rawcc = tif->tif_rawdatasize - occ; |
| 378 | if (!TIFFFlushData1(tif)) |
| 379 | return (-1); |
| 380 | op = tif->tif_rawcp; |
| 381 | occ = tif->tif_rawdatasize - tif->tif_rawcc; |
| 382 | } |
| 383 | mask = 0xff << shft; /* find next run */ |
| 384 | for (beg = i; beg < npixels; beg += rc) { |
| 385 | b = tp[beg] & mask; |
| 386 | rc = 1; |
| 387 | while (rc < 127+2 && beg+rc < npixels && |
| 388 | (tp[beg+rc] & mask) == b) |
| 389 | rc++; |
| 390 | if (rc >= MINRUN) |
| 391 | break; /* long enough */ |
| 392 | } |
| 393 | if (beg-i > 1 && beg-i < MINRUN) { |
| 394 | b = tp[i] & mask; /* check short run */ |
| 395 | j = i+1; |
| 396 | while ((tp[j++] & mask) == b) |
| 397 | if (j == beg) { |
| 398 | *op++ = 128-2+j-i; |
| 399 | *op++ = b >> shft; |
| 400 | occ -= 2; |
| 401 | i = beg; |
| 402 | break; |
| 403 | } |
| 404 | } |
| 405 | while (i < beg) { /* write out non-run */ |
| 406 | if ((j = beg-i) > 127) j = 127; |
| 407 | if (occ < j+3) { |
| 408 | tif->tif_rawcp = op; |
| 409 | tif->tif_rawcc = tif->tif_rawdatasize - occ; |
| 410 | if (!TIFFFlushData1(tif)) |
| 411 | return (-1); |
| 412 | op = tif->tif_rawcp; |
| 413 | occ = tif->tif_rawdatasize - tif->tif_rawcc; |
| 414 | } |
| 415 | *op++ = j; occ--; |
| 416 | while (j--) { |
| 417 | *op++ = tp[i++] >> shft & 0xff; |
| 418 | occ--; |
| 419 | } |
| 420 | } |
| 421 | if (rc >= MINRUN) { /* write out run */ |
| 422 | *op++ = 128-2+rc; |
| 423 | *op++ = tp[beg] >> shft & 0xff; |
| 424 | occ -= 2; |
| 425 | } else |
| 426 | rc = 0; |
| 427 | } |
| 428 | tif->tif_rawcp = op; |
| 429 | tif->tif_rawcc = tif->tif_rawdatasize - occ; |
| 430 | |
| 431 | return (0); |
| 432 | } |
| 433 | |
| 434 | /* |
| 435 | * Encode a row of 24-bit pixels. |
| 436 | */ |
| 437 | static int LINKAGEMODE |
| 438 | LogLuvEncode24(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) |
| 439 | { |
| 440 | LogLuvState* sp = EncoderState(tif); |
| 441 | int i, npixels, occ; |
| 442 | tidata_t op; |
| 443 | uint32* tp; |
| 444 | |
| 445 | assert(s == 0); |
| 446 | assert(sp != NULL); |
| 447 | npixels = cc / sp->pixel_size; |
| 448 | |
| 449 | if (sp->user_datafmt == SGILOGDATAFMT_RAW) |
| 450 | tp = (uint32*) bp; |
| 451 | else { |
| 452 | tp = (uint32*) sp->tbuf; |
| 453 | assert(sp->tbuflen >= npixels); |
| 454 | (*sp->tfunc)(sp, bp, npixels); |
| 455 | } |
| 456 | /* write out encoded pixels */ |
| 457 | op = tif->tif_rawcp; |
| 458 | occ = tif->tif_rawdatasize - tif->tif_rawcc; |
| 459 | for (i = npixels; i--; ) { |
| 460 | if (occ < 3) { |
| 461 | tif->tif_rawcp = op; |
| 462 | tif->tif_rawcc = tif->tif_rawdatasize - occ; |
| 463 | if (!TIFFFlushData1(tif)) |
| 464 | return (-1); |
| 465 | op = tif->tif_rawcp; |
| 466 | occ = tif->tif_rawdatasize - tif->tif_rawcc; |
| 467 | } |
| 468 | *op++ = *tp >> 16; |
| 469 | *op++ = *tp >> 8 & 0xff; |
| 470 | *op++ = *tp++ & 0xff; |
| 471 | occ -= 3; |
| 472 | } |
| 473 | tif->tif_rawcp = op; |
| 474 | tif->tif_rawcc = tif->tif_rawdatasize - occ; |
| 475 | |
| 476 | return (0); |
| 477 | } |
| 478 | |
| 479 | /* |
| 480 | * Encode a row of 32-bit pixels. |
| 481 | */ |
| 482 | static int LINKAGEMODE |
| 483 | LogLuvEncode32(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) |
| 484 | { |
| 485 | LogLuvState* sp = EncoderState(tif); |
| 486 | int shft, i, j, npixels; |
| 487 | tidata_t op; |
| 488 | uint32* tp; |
| 489 | uint32 b; |
| 490 | int occ, rc=0, mask, beg; |
| 491 | |
| 492 | assert(s == 0); |
| 493 | assert(sp != NULL); |
| 494 | |
| 495 | npixels = cc / sp->pixel_size; |
| 496 | |
| 497 | if (sp->user_datafmt == SGILOGDATAFMT_RAW) |
| 498 | tp = (uint32*) bp; |
| 499 | else { |
| 500 | tp = (uint32*) sp->tbuf; |
| 501 | assert(sp->tbuflen >= npixels); |
| 502 | (*sp->tfunc)(sp, bp, npixels); |
| 503 | } |
| 504 | /* compress each byte string */ |
| 505 | op = tif->tif_rawcp; |
| 506 | occ = tif->tif_rawdatasize - tif->tif_rawcc; |
| 507 | for (shft = 4*8; (shft -= 8) >= 0; ) |
| 508 | for (i = 0; i < npixels; i += rc) { |
| 509 | if (occ < 4) { |
| 510 | tif->tif_rawcp = op; |
| 511 | tif->tif_rawcc = tif->tif_rawdatasize - occ; |
| 512 | if (!TIFFFlushData1(tif)) |
| 513 | return (-1); |
| 514 | op = tif->tif_rawcp; |
| 515 | occ = tif->tif_rawdatasize - tif->tif_rawcc; |
| 516 | } |
| 517 | mask = 0xff << shft; /* find next run */ |
| 518 | for (beg = i; beg < npixels; beg += rc) { |
| 519 | b = tp[beg] & mask; |
| 520 | rc = 1; |
| 521 | while (rc < 127+2 && beg+rc < npixels && |
| 522 | (tp[beg+rc] & mask) == b) |
| 523 | rc++; |
| 524 | if (rc >= MINRUN) |
| 525 | break; /* long enough */ |
| 526 | } |
| 527 | if (beg-i > 1 && beg-i < MINRUN) { |
| 528 | b = tp[i] & mask; /* check short run */ |
| 529 | j = i+1; |
| 530 | while ((tp[j++] & mask) == b) |
| 531 | if (j == beg) { |
| 532 | *op++ = 128-2+j-i; |
| 533 | *op++ = b >> shft; |
| 534 | occ -= 2; |
| 535 | i = beg; |
| 536 | break; |
| 537 | } |
| 538 | } |
| 539 | while (i < beg) { /* write out non-run */ |
| 540 | if ((j = beg-i) > 127) j = 127; |
| 541 | if (occ < j+3) { |
| 542 | tif->tif_rawcp = op; |
| 543 | tif->tif_rawcc = tif->tif_rawdatasize - occ; |
| 544 | if (!TIFFFlushData1(tif)) |
| 545 | return (-1); |
| 546 | op = tif->tif_rawcp; |
| 547 | occ = tif->tif_rawdatasize - tif->tif_rawcc; |
| 548 | } |
| 549 | *op++ = j; occ--; |
| 550 | while (j--) { |
| 551 | *op++ = tp[i++] >> shft & 0xff; |
| 552 | occ--; |
| 553 | } |
| 554 | } |
| 555 | if (rc >= MINRUN) { /* write out run */ |
| 556 | *op++ = 128-2+rc; |
| 557 | *op++ = tp[beg] >> shft & 0xff; |
| 558 | occ -= 2; |
| 559 | } else |
| 560 | rc = 0; |
| 561 | } |
| 562 | tif->tif_rawcp = op; |
| 563 | tif->tif_rawcc = tif->tif_rawdatasize - occ; |
| 564 | |
| 565 | return (0); |
| 566 | } |
| 567 | |
| 568 | /* |
| 569 | * Encode a strip of pixels. We break it into rows to |
| 570 | * avoid encoding runs across row boundaries. |
| 571 | */ |
| 572 | static int LINKAGEMODE |
| 573 | LogLuvEncodeStrip(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) |
| 574 | { |
| 575 | tsize_t rowlen = TIFFScanlineSize(tif); |
| 576 | |
| 577 | assert(cc%rowlen == 0); |
| 578 | while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 0) |
| 579 | bp += rowlen, cc -= rowlen; |
| 580 | return (cc == 0); |
| 581 | } |
| 582 | |
| 583 | /* |
| 584 | * Encode a tile of pixels. We break it into rows to |
| 585 | * avoid encoding runs across row boundaries. |
| 586 | */ |
| 587 | static int LINKAGEMODE |
| 588 | LogLuvEncodeTile(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s) |
| 589 | { |
| 590 | tsize_t rowlen = TIFFTileRowSize(tif); |
| 591 | |
| 592 | assert(cc%rowlen == 0); |
| 593 | while (cc && (*tif->tif_encoderow)(tif, bp, rowlen, s) == 0) |
| 594 | bp += rowlen, cc -= rowlen; |
| 595 | return (cc == 0); |
| 596 | } |
| 597 | |
| 598 | /* |
| 599 | * Encode/Decode functions for converting to and from user formats. |
| 600 | */ |
| 601 | #include "uvcode.h" |
| 602 | |
| 603 | #define U_NEU 0.210526316 |
| 604 | #define V_NEU 0.473684211 |
| 605 | |
| 606 | #ifdef M_LN2 |
| 607 | #define LOGOF2 M_LN2 |
| 608 | #else |
| 609 | #define LOGOF2 0.69314718055994530942 |
| 610 | #endif |
| 611 | #ifndef log2 |
| 612 | #define log2(x) ((1./LOGOF2)*log(x)) |
| 613 | #endif |
| 614 | #ifndef exp2 |
| 615 | #define exp2(x) exp(LOGOF2*(x)) |
| 616 | #endif |
| 617 | #define UVSCALE 410. |
| 618 | |
| 619 | static double |
| 620 | pix16toY(int p16) |
| 621 | { |
| 622 | int Le = p16 & 0x7fff; |
| 623 | double Y; |
| 624 | |
| 625 | if (!Le) |
| 626 | return (0.); |
| 627 | Y = exp(LOGOF2/256.*(Le+.5) - LOGOF2*64.); |
| 628 | if (p16 & 0x8000) |
| 629 | return (-Y); |
| 630 | return (Y); |
| 631 | } |
| 632 | |
| 633 | static int |
| 634 | pix16fromY(double Y) |
| 635 | { |
| 636 | if (Y >= 1.84467e19) |
| 637 | return (0x7fff); |
| 638 | if (Y <= -1.84467e19) |
| 639 | return (0xffff); |
| 640 | if (Y > 5.43571e-20) |
| 641 | return (int)(256.*(log2(Y) + 64.)); |
| 642 | if (Y < -5.43571e-20) |
| 643 | return (~0x7fff | (int)(256.*(log2(-Y) + 64.))); |
| 644 | return (0); |
| 645 | } |
| 646 | |
| 647 | static void |
| 648 | L16toY(LogLuvState* sp, tidata_t op, int n) |
| 649 | { |
| 650 | int16* l16 = (int16*) sp->tbuf; |
| 651 | float* yp = (float*) op; |
| 652 | |
| 653 | while (n-- > 0) |
| 654 | *yp++ = pix16toY(*l16++); |
| 655 | } |
| 656 | |
| 657 | static void |
| 658 | L16toGry(LogLuvState* sp, tidata_t op, int n) |
| 659 | { |
| 660 | int16* l16 = (int16*) sp->tbuf; |
| 661 | uint8* gp = (uint8*) op; |
| 662 | |
| 663 | while (n-- > 0) { |
| 664 | double Y = pix16toY(*l16++); |
| 665 | *gp++ = (Y <= 0.) ? 0 : (Y >= 1.) ? 255 : (int)(256.*sqrt(Y)); |
| 666 | } |
| 667 | } |
| 668 | |
| 669 | static void |
| 670 | L16fromY(LogLuvState* sp, tidata_t op, int n) |
| 671 | { |
| 672 | int16* l16 = (int16*) sp->tbuf; |
| 673 | float* yp = (float*) op; |
| 674 | |
| 675 | while (n-- > 0) |
| 676 | *l16++ = pix16fromY(*yp++); |
| 677 | } |
| 678 | |
| 679 | static void |
| 680 | XYZtoRGB24(float xyz[3], uint8 rgb[3]) |
| 681 | { |
| 682 | double r, g, b; |
| 683 | /* assume CCIR-709 primaries */ |
| 684 | r = 2.690*xyz[0] + -1.276*xyz[1] + -0.414*xyz[2]; |
| 685 | g = -1.022*xyz[0] + 1.978*xyz[1] + 0.044*xyz[2]; |
| 686 | b = 0.061*xyz[0] + -0.224*xyz[1] + 1.163*xyz[2]; |
| 687 | /* assume 2.0 gamma for speed */ |
| 688 | /* could use integer sqrt approx., but this is probably faster */ |
| 689 | rgb[0] = (r <= 0.) ? 0 : (r >= 1.) ? 255 : (int)(256.*sqrt(r)); |
| 690 | rgb[1] = (g <= 0.) ? 0 : (g >= 1.) ? 255 : (int)(256.*sqrt(g)); |
| 691 | rgb[2] = (b <= 0.) ? 0 : (b >= 1.) ? 255 : (int)(256.*sqrt(b)); |
| 692 | } |
| 693 | |
| 694 | static int |
| 695 | uv_encode(double u, double v) /* encode (u',v') coordinates */ |
| 696 | { |
| 697 | register int vi, ui; |
| 698 | |
| 699 | if (v < UV_VSTART) |
| 700 | return(-1); |
| 701 | vi = (v - UV_VSTART)*(1./UV_SQSIZ); |
| 702 | if (vi >= UV_NVS) |
| 703 | return(-1); |
| 704 | if (u < uv_row[vi].ustart) |
| 705 | return(-1); |
| 706 | ui = (u - uv_row[vi].ustart)*(1./UV_SQSIZ); |
| 707 | if (ui >= uv_row[vi].nus) |
| 708 | return(-1); |
| 709 | return(uv_row[vi].ncum + ui); |
| 710 | } |
| 711 | |
| 712 | static int |
| 713 | uv_decode(double *up, double *vp, int c) /* decode (u',v') index */ |
| 714 | { |
| 715 | int upper, lower; |
| 716 | register int ui, vi; |
| 717 | |
| 718 | if (c < 0 || c >= UV_NDIVS) |
| 719 | return(-1); |
| 720 | lower = 0; /* binary search */ |
| 721 | upper = UV_NVS; |
| 722 | do { |
| 723 | vi = (lower + upper) >> 1; |
| 724 | ui = c - uv_row[vi].ncum; |
| 725 | if (ui > 0) |
| 726 | lower = vi; |
| 727 | else if (ui < 0) |
| 728 | upper = vi; |
| 729 | else |
| 730 | break; |
| 731 | } while (upper - lower > 1); |
| 732 | vi = lower; |
| 733 | ui = c - uv_row[vi].ncum; |
| 734 | *up = uv_row[vi].ustart + (ui+.5)*UV_SQSIZ; |
| 735 | *vp = UV_VSTART + (vi+.5)*UV_SQSIZ; |
| 736 | return(0); |
| 737 | } |
| 738 | |
| 739 | static void |
| 740 | pix24toXYZ(uint32 p, float XYZ[3]) |
| 741 | { |
| 742 | int Le, Ce; |
| 743 | double L, u, v, s, x, y; |
| 744 | /* decode luminance */ |
| 745 | Le = p >> 14 & 0x3ff; |
| 746 | if (Le == 0) { |
| 747 | XYZ[0] = XYZ[1] = XYZ[2] = 0.; |
| 748 | return; |
| 749 | } |
| 750 | L = exp(LOGOF2/64.*(Le+.5) - LOGOF2*12.); |
| 751 | /* decode color */ |
| 752 | Ce = p & 0x3fff; |
| 753 | if (uv_decode(&u, &v, Ce) < 0) { |
| 754 | u = U_NEU; v = V_NEU; |
| 755 | } |
| 756 | s = 1./(6.*u - 16.*v + 12.); |
| 757 | x = 9.*u * s; |
| 758 | y = 4.*v * s; |
| 759 | /* convert to XYZ */ |
| 760 | XYZ[0] = x/y * L; |
| 761 | XYZ[1] = L; |
| 762 | XYZ[2] = (1.-x-y)/y * L; |
| 763 | } |
| 764 | |
| 765 | static uint32 |
| 766 | pix24fromXYZ(float XYZ[3]) |
| 767 | { |
| 768 | int Le, Ce; |
| 769 | double L, u, v, s; |
| 770 | /* encode luminance */ |
| 771 | L = XYZ[1]; |
| 772 | if (L >= 16.) |
| 773 | Le = 0x3ff; |
| 774 | else if (L <= 1./4096.) |
| 775 | Le = 0; |
| 776 | else |
| 777 | Le = 64.*(log2(L) + 12.); |
| 778 | /* encode color */ |
| 779 | s = XYZ[0] + 15.*XYZ[1] + 3.*XYZ[2]; |
| 780 | if (s == 0.) { |
| 781 | u = U_NEU; |
| 782 | v = V_NEU; |
| 783 | } else { |
| 784 | u = 4.*XYZ[0] / s; |
| 785 | v = 9.*XYZ[1] / s; |
| 786 | } |
| 787 | Ce = uv_encode(u, v); |
| 788 | if (Ce < 0) |
| 789 | Ce = uv_encode(U_NEU, V_NEU); |
| 790 | /* combine encodings */ |
| 791 | return (Le << 14 | Ce); |
| 792 | } |
| 793 | |
| 794 | static void |
| 795 | Luv24toXYZ(LogLuvState* sp, tidata_t op, int n) |
| 796 | { |
| 797 | uint32* luv = (uint32*) sp->tbuf; |
| 798 | float* xyz = (float*) op; |
| 799 | |
| 800 | while (n-- > 0) { |
| 801 | pix24toXYZ(*luv, xyz); |
| 802 | xyz += 3; |
| 803 | luv++; |
| 804 | } |
| 805 | } |
| 806 | |
| 807 | static void |
| 808 | Luv24toLuv48(LogLuvState* sp, tidata_t op, int n) |
| 809 | { |
| 810 | uint32* luv = (uint32*) sp->tbuf; |
| 811 | int16* luv3 = (int16*) op; |
| 812 | |
| 813 | while (n-- > 0) { |
| 814 | double u, v; |
| 815 | |
| 816 | *luv3++ = (*luv >> 12 & 0xffd) + 13314; |
| 817 | if (uv_decode(&u, &v, *luv&0x3fff) < 0) { |
| 818 | u = U_NEU; |
| 819 | v = V_NEU; |
| 820 | } |
| 821 | *luv3++ = u * (1L<<15); |
| 822 | *luv3++ = v * (1L<<15); |
| 823 | luv++; |
| 824 | } |
| 825 | } |
| 826 | |
| 827 | static void |
| 828 | Luv24toRGB(LogLuvState* sp, tidata_t op, int n) |
| 829 | { |
| 830 | uint32* luv = (uint32*) sp->tbuf; |
| 831 | uint8* rgb = (uint8*) op; |
| 832 | |
| 833 | while (n-- > 0) { |
| 834 | float xyz[3]; |
| 835 | |
| 836 | pix24toXYZ(*luv++, xyz); |
| 837 | XYZtoRGB24(xyz, rgb); |
| 838 | rgb += 3; |
| 839 | } |
| 840 | } |
| 841 | |
| 842 | static void |
| 843 | Luv24fromXYZ(LogLuvState* sp, tidata_t op, int n) |
| 844 | { |
| 845 | uint32* luv = (uint32*) sp->tbuf; |
| 846 | float* xyz = (float*) op; |
| 847 | |
| 848 | while (n-- > 0) { |
| 849 | *luv++ = pix24fromXYZ(xyz); |
| 850 | xyz += 3; |
| 851 | } |
| 852 | } |
| 853 | |
| 854 | static void |
| 855 | Luv24fromLuv48(LogLuvState* sp, tidata_t op, int n) |
| 856 | { |
| 857 | uint32* luv = (uint32*) sp->tbuf; |
| 858 | int16* luv3 = (int16*) op; |
| 859 | |
| 860 | while (n-- > 0) { |
| 861 | int Le, Ce; |
| 862 | |
| 863 | if (luv3[0] <= 0) |
| 864 | Le = 0; |
| 865 | else if (luv3[0] >= (1<<12)+3314) |
| 866 | Le = (1<<10) - 1; |
| 867 | else |
| 868 | Le = (luv3[0]-3314) >> 2; |
| 869 | Ce = uv_encode((luv[1]+.5)/(1<<15), (luv[2]+.5)/(1<<15)); |
| 870 | if (Ce < 0) |
| 871 | Ce = uv_encode(U_NEU, V_NEU); |
| 872 | *luv++ = (uint32)Le << 14 | Ce; |
| 873 | luv3 += 3; |
| 874 | } |
| 875 | } |
| 876 | |
| 877 | static void |
| 878 | pix32toXYZ(uint32 p, float XYZ[3]) |
| 879 | { |
| 880 | double L, u, v, s, x, y; |
| 881 | /* decode luminance */ |
| 882 | L = pix16toY((int)p >> 16); |
| 883 | if (L == 0.) { |
| 884 | XYZ[0] = XYZ[1] = XYZ[2] = 0.; |
| 885 | return; |
| 886 | } |
| 887 | /* decode color */ |
| 888 | u = 1./UVSCALE * ((p>>8 & 0xff) + .5); |
| 889 | v = 1./UVSCALE * ((p & 0xff) + .5); |
| 890 | s = 1./(6.*u - 16.*v + 12.); |
| 891 | x = 9.*u * s; |
| 892 | y = 4.*v * s; |
| 893 | /* convert to XYZ */ |
| 894 | XYZ[0] = x/y * L; |
| 895 | XYZ[1] = L; |
| 896 | XYZ[2] = (1.-x-y)/y * L; |
| 897 | } |
| 898 | |
| 899 | static uint32 |
| 900 | pix32fromXYZ(float XYZ[3]) |
| 901 | { |
| 902 | unsigned int Le, ue, ve; |
| 903 | double u, v, s; |
| 904 | /* encode luminance */ |
| 905 | Le = (unsigned int)pix16fromY(XYZ[1]); |
| 906 | /* encode color */ |
| 907 | s = XYZ[0] + 15.*XYZ[1] + 3.*XYZ[2]; |
| 908 | if (s == 0.) { |
| 909 | u = U_NEU; |
| 910 | v = V_NEU; |
| 911 | } else { |
| 912 | u = 4.*XYZ[0] / s; |
| 913 | v = 9.*XYZ[1] / s; |
| 914 | } |
| 915 | if (u <= 0.) ue = 0; |
| 916 | else ue = UVSCALE * u; |
| 917 | if (ue > 255) ue = 255; |
| 918 | if (v <= 0.) ve = 0; |
| 919 | else ve = UVSCALE * v; |
| 920 | if (ve > 255) ve = 255; |
| 921 | /* combine encodings */ |
| 922 | return (Le << 16 | ue << 8 | ve); |
| 923 | } |
| 924 | |
| 925 | static void |
| 926 | Luv32toXYZ(LogLuvState* sp, tidata_t op, int n) |
| 927 | { |
| 928 | uint32* luv = (uint32*) sp->tbuf; |
| 929 | float* xyz = (float*) op; |
| 930 | |
| 931 | while (n-- > 0) { |
| 932 | pix32toXYZ(*luv++, xyz); |
| 933 | xyz += 3; |
| 934 | } |
| 935 | } |
| 936 | |
| 937 | static void |
| 938 | Luv32toLuv48(LogLuvState* sp, tidata_t op, int n) |
| 939 | { |
| 940 | uint32* luv = (uint32*) sp->tbuf; |
| 941 | int16* luv3 = (int16*) op; |
| 942 | |
| 943 | while (n-- > 0) { |
| 944 | double u, v; |
| 945 | |
| 946 | *luv3++ = *luv >> 16; |
| 947 | u = 1./UVSCALE * ((*luv>>8 & 0xff) + .5); |
| 948 | v = 1./UVSCALE * ((*luv & 0xff) + .5); |
| 949 | *luv3++ = u * (1L<<15); |
| 950 | *luv3++ = v * (1L<<15); |
| 951 | luv++; |
| 952 | } |
| 953 | } |
| 954 | |
| 955 | static void |
| 956 | Luv32toRGB(LogLuvState* sp, tidata_t op, int n) |
| 957 | { |
| 958 | uint32* luv = (uint32*) sp->tbuf; |
| 959 | uint8* rgb = (uint8*) op; |
| 960 | |
| 961 | while (n-- > 0) { |
| 962 | float xyz[3]; |
| 963 | |
| 964 | pix32toXYZ(*luv++, xyz); |
| 965 | XYZtoRGB24(xyz, rgb); |
| 966 | rgb += 3; |
| 967 | } |
| 968 | } |
| 969 | |
| 970 | static void |
| 971 | Luv32fromXYZ(LogLuvState* sp, tidata_t op, int n) |
| 972 | { |
| 973 | uint32* luv = (uint32*) sp->tbuf; |
| 974 | float* xyz = (float*) op; |
| 975 | |
| 976 | while (n-- > 0) { |
| 977 | *luv++ = pix32fromXYZ(xyz); |
| 978 | xyz += 3; |
| 979 | } |
| 980 | } |
| 981 | |
| 982 | static void |
| 983 | Luv32fromLuv48(LogLuvState* sp, tidata_t op, int n) |
| 984 | { |
| 985 | uint32* luv = (uint32*) sp->tbuf; |
| 986 | int16* luv3 = (int16*) op; |
| 987 | |
| 988 | while (n-- > 0) { |
| 989 | *luv++ = (uint32)luv3[0] << 16 | |
| 990 | (luv3[1]*(uint32)(UVSCALE+.5) >> 7 & 0xff00) | |
| 991 | (luv3[2]*(uint32)(UVSCALE+.5) >> 15 & 0xff); |
| 992 | luv3 += 3; |
| 993 | } |
| 994 | } |
| 995 | |
| 996 | static void |
| 997 | _logLuvNop(LogLuvState* sp, tidata_t op, int n) |
| 998 | { |
| 999 | (void) sp; (void) op; (void) n; |
| 1000 | } |
| 1001 | |
| 1002 | static int |
| 1003 | LogL16GuessDataFmt(TIFFDirectory *td) |
| 1004 | { |
| 1005 | #define PACK(s,b,f) (((b)<<6)|((s)<<3)|(f)) |
| 1006 | switch (PACK(td->td_samplesperpixel, td->td_bitspersample, td->td_sampleformat)) { |
| 1007 | case PACK(1, 32, SAMPLEFORMAT_IEEEFP): |
| 1008 | return (SGILOGDATAFMT_FLOAT); |
| 1009 | case PACK(1, 16, SAMPLEFORMAT_VOID): |
| 1010 | case PACK(1, 16, SAMPLEFORMAT_INT): |
| 1011 | case PACK(1, 16, SAMPLEFORMAT_UINT): |
| 1012 | return (SGILOGDATAFMT_16BIT); |
| 1013 | case PACK(1, 8, SAMPLEFORMAT_VOID): |
| 1014 | case PACK(1, 8, SAMPLEFORMAT_UINT): |
| 1015 | return (SGILOGDATAFMT_8BIT); |
| 1016 | } |
| 1017 | #undef PACK |
| 1018 | return (SGILOGDATAFMT_UNKNOWN); |
| 1019 | } |
| 1020 | |
| 1021 | static int |
| 1022 | LogL16InitState(TIFF* tif) |
| 1023 | { |
| 1024 | TIFFDirectory *td = &tif->tif_dir; |
| 1025 | LogLuvState* sp = DecoderState(tif); |
| 1026 | static const char module[] = "LogL16InitState"; |
| 1027 | |
| 1028 | assert(sp != NULL); |
| 1029 | assert(td->td_photometric == PHOTOMETRIC_LOGL); |
| 1030 | |
| 1031 | /* for some reason, we can't do this in TIFFInitLogL16 */ |
| 1032 | if (sp->user_datafmt == SGILOGDATAFMT_UNKNOWN) |
| 1033 | sp->user_datafmt = LogL16GuessDataFmt(td); |
| 1034 | switch (sp->user_datafmt) { |
| 1035 | case SGILOGDATAFMT_FLOAT: |
| 1036 | sp->pixel_size = sizeof (float); |
| 1037 | break; |
| 1038 | case SGILOGDATAFMT_16BIT: |
| 1039 | sp->pixel_size = sizeof (int16); |
| 1040 | break; |
| 1041 | case SGILOGDATAFMT_8BIT: |
| 1042 | sp->pixel_size = sizeof (uint8); |
| 1043 | break; |
| 1044 | default: |
| 1045 | TIFFError(tif->tif_name, |
| 1046 | "No support for converting user data format to LogL"); |
| 1047 | return (0); |
| 1048 | } |
| 1049 | sp->tbuflen = td->td_imagewidth * td->td_rowsperstrip; |
| 1050 | sp->tbuf = (tidata_t*) _TIFFmalloc(sp->tbuflen * sizeof (int16)); |
| 1051 | if (sp->tbuf == NULL) { |
| 1052 | TIFFError(module, "%s: No space for SGILog translation buffer", |
| 1053 | tif->tif_name); |
| 1054 | return (0); |
| 1055 | } |
| 1056 | return (1); |
| 1057 | } |
| 1058 | |
| 1059 | static int |
| 1060 | LogLuvGuessDataFmt(TIFFDirectory *td) |
| 1061 | { |
| 1062 | int guess; |
| 1063 | |
| 1064 | /* |
| 1065 | * If the user didn't tell us their datafmt, |
| 1066 | * take our best guess from the bitspersample. |
| 1067 | */ |
| 1068 | #define PACK(a,b) (((a)<<3)|(b)) |
| 1069 | switch (PACK(td->td_bitspersample, td->td_sampleformat)) { |
| 1070 | case PACK(32, SAMPLEFORMAT_IEEEFP): |
| 1071 | guess = SGILOGDATAFMT_FLOAT; |
| 1072 | break; |
| 1073 | case PACK(32, SAMPLEFORMAT_VOID): |
| 1074 | case PACK(32, SAMPLEFORMAT_UINT): |
| 1075 | case PACK(32, SAMPLEFORMAT_INT): |
| 1076 | guess = SGILOGDATAFMT_RAW; |
| 1077 | break; |
| 1078 | case PACK(16, SAMPLEFORMAT_VOID): |
| 1079 | case PACK(16, SAMPLEFORMAT_INT): |
| 1080 | case PACK(16, SAMPLEFORMAT_UINT): |
| 1081 | guess = SGILOGDATAFMT_16BIT; |
| 1082 | break; |
| 1083 | case PACK( 8, SAMPLEFORMAT_VOID): |
| 1084 | case PACK( 8, SAMPLEFORMAT_UINT): |
| 1085 | guess = SGILOGDATAFMT_8BIT; |
| 1086 | break; |
| 1087 | default: |
| 1088 | guess = SGILOGDATAFMT_UNKNOWN; |
| 1089 | break; |
| 1090 | #undef PACK |
| 1091 | } |
| 1092 | /* |
| 1093 | * Double-check samples per pixel. |
| 1094 | */ |
| 1095 | switch (td->td_samplesperpixel) { |
| 1096 | case 1: |
| 1097 | if (guess != SGILOGDATAFMT_RAW) |
| 1098 | guess = SGILOGDATAFMT_UNKNOWN; |
| 1099 | break; |
| 1100 | case 3: |
| 1101 | if (guess == SGILOGDATAFMT_RAW) |
| 1102 | guess = SGILOGDATAFMT_UNKNOWN; |
| 1103 | break; |
| 1104 | default: |
| 1105 | guess = SGILOGDATAFMT_UNKNOWN; |
| 1106 | break; |
| 1107 | } |
| 1108 | return (guess); |
| 1109 | } |
| 1110 | |
| 1111 | static int |
| 1112 | LogLuvInitState(TIFF* tif) |
| 1113 | { |
| 1114 | TIFFDirectory* td = &tif->tif_dir; |
| 1115 | LogLuvState* sp = DecoderState(tif); |
| 1116 | static const char module[] = "LogLuvInitState"; |
| 1117 | |
| 1118 | assert(sp != NULL); |
| 1119 | assert(td->td_photometric == PHOTOMETRIC_LOGLUV); |
| 1120 | |
| 1121 | /* for some reason, we can't do this in TIFFInitLogLuv */ |
| 1122 | if (td->td_planarconfig != PLANARCONFIG_CONTIG) { |
| 1123 | TIFFError(module, |
| 1124 | "SGILog compression cannot handle non-contiguous data"); |
| 1125 | return (0); |
| 1126 | } |
| 1127 | if (sp->user_datafmt == SGILOGDATAFMT_UNKNOWN) |
| 1128 | sp->user_datafmt = LogLuvGuessDataFmt(td); |
| 1129 | switch (sp->user_datafmt) { |
| 1130 | case SGILOGDATAFMT_FLOAT: |
| 1131 | sp->pixel_size = 3*sizeof (float); |
| 1132 | break; |
| 1133 | case SGILOGDATAFMT_16BIT: |
| 1134 | sp->pixel_size = 3*sizeof (int16); |
| 1135 | break; |
| 1136 | case SGILOGDATAFMT_RAW: |
| 1137 | sp->pixel_size = sizeof (uint32); |
| 1138 | break; |
| 1139 | case SGILOGDATAFMT_8BIT: |
| 1140 | sp->pixel_size = 3*sizeof (uint8); |
| 1141 | break; |
| 1142 | default: |
| 1143 | TIFFError(tif->tif_name, |
| 1144 | "No support for converting user data format to LogLuv"); |
| 1145 | return (0); |
| 1146 | } |
| 1147 | sp->tbuflen = td->td_imagewidth * td->td_rowsperstrip; |
| 1148 | sp->tbuf = (tidata_t*) _TIFFmalloc(sp->tbuflen * sizeof (uint32)); |
| 1149 | if (sp->tbuf == NULL) { |
| 1150 | TIFFError(module, "%s: No space for SGILog translation buffer", |
| 1151 | tif->tif_name); |
| 1152 | return (0); |
| 1153 | } |
| 1154 | return (1); |
| 1155 | } |
| 1156 | |
| 1157 | static int |
| 1158 | LogLuvSetupDecode(TIFF* tif) |
| 1159 | { |
| 1160 | LogLuvState* sp = DecoderState(tif); |
| 1161 | TIFFDirectory* td = &tif->tif_dir; |
| 1162 | |
| 1163 | tif->tif_postdecode = _TIFFNoPostDecode; |
| 1164 | switch (td->td_photometric) { |
| 1165 | case PHOTOMETRIC_LOGLUV: |
| 1166 | if (!LogLuvInitState(tif)) |
| 1167 | break; |
| 1168 | if (td->td_compression == COMPRESSION_SGILOG24) { |
| 1169 | tif->tif_decoderow = LogLuvDecode24; |
| 1170 | switch (sp->user_datafmt) { |
| 1171 | case SGILOGDATAFMT_FLOAT: |
| 1172 | sp->tfunc = Luv24toXYZ; |
| 1173 | break; |
| 1174 | case SGILOGDATAFMT_16BIT: |
| 1175 | sp->tfunc = Luv24toLuv48; |
| 1176 | break; |
| 1177 | case SGILOGDATAFMT_8BIT: |
| 1178 | sp->tfunc = Luv24toRGB; |
| 1179 | break; |
| 1180 | } |
| 1181 | } else { |
| 1182 | tif->tif_decoderow = LogLuvDecode32; |
| 1183 | switch (sp->user_datafmt) { |
| 1184 | case SGILOGDATAFMT_FLOAT: |
| 1185 | sp->tfunc = Luv32toXYZ; |
| 1186 | break; |
| 1187 | case SGILOGDATAFMT_16BIT: |
| 1188 | sp->tfunc = Luv32toLuv48; |
| 1189 | break; |
| 1190 | case SGILOGDATAFMT_8BIT: |
| 1191 | sp->tfunc = Luv32toRGB; |
| 1192 | break; |
| 1193 | } |
| 1194 | } |
| 1195 | return (1); |
| 1196 | case PHOTOMETRIC_LOGL: |
| 1197 | if (!LogL16InitState(tif)) |
| 1198 | break; |
| 1199 | tif->tif_decoderow = LogL16Decode; |
| 1200 | switch (sp->user_datafmt) { |
| 1201 | case SGILOGDATAFMT_FLOAT: |
| 1202 | sp->tfunc = L16toY; |
| 1203 | break; |
| 1204 | case SGILOGDATAFMT_8BIT: |
| 1205 | sp->tfunc = L16toGry; |
| 1206 | break; |
| 1207 | } |
| 1208 | return (1); |
| 1209 | default: |
| 1210 | TIFFError(tif->tif_name, |
| 1211 | "Inappropriate photometric interpretation %d for SGILog compression; %s", |
| 1212 | td->td_photometric, "must be either LogLUV or LogL"); |
| 1213 | break; |
| 1214 | } |
| 1215 | return (0); |
| 1216 | } |
| 1217 | |
| 1218 | static int |
| 1219 | LogLuvSetupEncode(TIFF* tif) |
| 1220 | { |
| 1221 | LogLuvState* sp = EncoderState(tif); |
| 1222 | TIFFDirectory* td = &tif->tif_dir; |
| 1223 | |
| 1224 | switch (td->td_photometric) { |
| 1225 | case PHOTOMETRIC_LOGLUV: |
| 1226 | if (!LogLuvInitState(tif)) |
| 1227 | break; |
| 1228 | if (td->td_compression == COMPRESSION_SGILOG24) { |
| 1229 | tif->tif_encoderow = LogLuvEncode24; |
| 1230 | switch (sp->user_datafmt) { |
| 1231 | case SGILOGDATAFMT_FLOAT: |
| 1232 | sp->tfunc = Luv24fromXYZ; |
| 1233 | break; |
| 1234 | case SGILOGDATAFMT_16BIT: |
| 1235 | sp->tfunc = Luv24fromLuv48; |
| 1236 | break; |
| 1237 | case SGILOGDATAFMT_RAW: |
| 1238 | break; |
| 1239 | default: |
| 1240 | goto notsupported; |
| 1241 | } |
| 1242 | } else { |
| 1243 | tif->tif_encoderow = LogLuvEncode32; |
| 1244 | switch (sp->user_datafmt) { |
| 1245 | case SGILOGDATAFMT_FLOAT: |
| 1246 | sp->tfunc = Luv32fromXYZ; |
| 1247 | break; |
| 1248 | case SGILOGDATAFMT_16BIT: |
| 1249 | sp->tfunc = Luv32fromLuv48; |
| 1250 | break; |
| 1251 | case SGILOGDATAFMT_RAW: |
| 1252 | break; |
| 1253 | default: |
| 1254 | goto notsupported; |
| 1255 | } |
| 1256 | } |
| 1257 | break; |
| 1258 | case PHOTOMETRIC_LOGL: |
| 1259 | if (!LogL16InitState(tif)) |
| 1260 | break; |
| 1261 | tif->tif_encoderow = LogL16Encode; |
| 1262 | switch (sp->user_datafmt) { |
| 1263 | case SGILOGDATAFMT_FLOAT: |
| 1264 | sp->tfunc = L16fromY; |
| 1265 | break; |
| 1266 | case SGILOGDATAFMT_16BIT: |
| 1267 | break; |
| 1268 | default: |
| 1269 | goto notsupported; |
| 1270 | } |
| 1271 | break; |
| 1272 | default: |
| 1273 | TIFFError(tif->tif_name, |
| 1274 | "Inappropriate photometric interpretation %d for SGILog compression; %s", |
| 1275 | td->td_photometric, "must be either LogLUV or LogL"); |
| 1276 | break; |
| 1277 | } |
| 1278 | return (1); |
| 1279 | notsupported: |
| 1280 | TIFFError(tif->tif_name, |
| 1281 | "SGILog compression supported only for %s, or raw data", |
| 1282 | td->td_photometric == PHOTOMETRIC_LOGL ? "Y, L" : "XYZ, Luv"); |
| 1283 | return (0); |
| 1284 | } |
| 1285 | |
| 1286 | static void |
| 1287 | LogLuvClose(TIFF* tif) |
| 1288 | { |
| 1289 | TIFFDirectory *td = &tif->tif_dir; |
| 1290 | |
| 1291 | /* |
| 1292 | * For consistency, we always want to write out the same |
| 1293 | * bitspersample and sampleformat for our TIFF file, |
| 1294 | * regardless of the data format being used by the application. |
| 1295 | * Since this routine is called after tags have been set but |
| 1296 | * before they have been recorded in the file, we reset them here. |
| 1297 | */ |
| 1298 | td->td_samplesperpixel = |
| 1299 | (td->td_photometric == PHOTOMETRIC_LOGL) ? 1 : 3; |
| 1300 | td->td_bitspersample = 16; |
| 1301 | td->td_sampleformat = SAMPLEFORMAT_INT; |
| 1302 | } |
| 1303 | |
| 1304 | static void |
| 1305 | LogLuvCleanup(TIFF* tif) |
| 1306 | { |
| 1307 | LogLuvState* sp = (LogLuvState *)tif->tif_data; |
| 1308 | |
| 1309 | if (sp) { |
| 1310 | if (sp->tbuf) |
| 1311 | _TIFFfree(sp->tbuf); |
| 1312 | _TIFFfree(sp); |
| 1313 | tif->tif_data = NULL; |
| 1314 | } |
| 1315 | } |
| 1316 | |
| 1317 | static int |
| 1318 | LogLuvVSetField(TIFF* tif, ttag_t tag, va_list ap) |
| 1319 | { |
| 1320 | LogLuvState* sp = DecoderState(tif); |
| 1321 | int bps, fmt; |
| 1322 | |
| 1323 | switch (tag) { |
| 1324 | case TIFFTAG_SGILOGDATAFMT: |
| 1325 | sp->user_datafmt = va_arg(ap, int); |
| 1326 | /* |
| 1327 | * Tweak the TIFF header so that the rest of libtiff knows what |
| 1328 | * size of data will be passed between app and library, and |
| 1329 | * assume that the app knows what it is doing and is not |
| 1330 | * confused by these header manipulations... |
| 1331 | */ |
| 1332 | switch (sp->user_datafmt) { |
| 1333 | case SGILOGDATAFMT_FLOAT: |
| 1334 | bps = 32, fmt = SAMPLEFORMAT_IEEEFP; |
| 1335 | break; |
| 1336 | case SGILOGDATAFMT_16BIT: |
| 1337 | bps = 16, fmt = SAMPLEFORMAT_INT; |
| 1338 | break; |
| 1339 | case SGILOGDATAFMT_RAW: |
| 1340 | bps = 32, fmt = SAMPLEFORMAT_UINT; |
| 1341 | break; |
| 1342 | case SGILOGDATAFMT_8BIT: |
| 1343 | bps = 8, fmt = SAMPLEFORMAT_UINT; |
| 1344 | break; |
| 1345 | default: |
| 1346 | TIFFError(tif->tif_name, |
| 1347 | "Unknown data format %d for LogLuv compression", |
| 1348 | sp->user_datafmt); |
| 1349 | return (0); |
| 1350 | } |
| 1351 | TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, bps); |
| 1352 | TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, fmt); |
| 1353 | /* |
| 1354 | * Must recalculate sizes should bits/sample change. |
| 1355 | */ |
| 1356 | tif->tif_tilesize = TIFFTileSize(tif); |
| 1357 | tif->tif_scanlinesize = TIFFScanlineSize(tif); |
| 1358 | return (1); |
| 1359 | default: |
| 1360 | return (*sp->vsetparent)(tif, tag, ap); |
| 1361 | } |
| 1362 | } |
| 1363 | |
| 1364 | static int |
| 1365 | LogLuvVGetField(TIFF* tif, ttag_t tag, va_list ap) |
| 1366 | { |
| 1367 | LogLuvState *sp = (LogLuvState *)tif->tif_data; |
| 1368 | |
| 1369 | switch (tag) { |
| 1370 | case TIFFTAG_SGILOGDATAFMT: |
| 1371 | *va_arg(ap, int*) = sp->user_datafmt; |
| 1372 | return (1); |
| 1373 | default: |
| 1374 | return (*sp->vgetparent)(tif, tag, ap); |
| 1375 | } |
| 1376 | } |
| 1377 | |
| 1378 | static const TIFFFieldInfo LogLuvFieldInfo[] = { |
| 1379 | { TIFFTAG_SGILOGDATAFMT, 0, 0, TIFF_SHORT, FIELD_PSEUDO, |
| 1380 | TRUE, FALSE, "SGILogDataFmt"} |
| 1381 | }; |
| 1382 | |
| 1383 | int |
| 1384 | TIFFInitSGILog(TIFF* tif, int scheme) |
| 1385 | { |
| 1386 | static const char module[] = "TIFFInitSGILog"; |
| 1387 | LogLuvState* sp; |
| 1388 | |
| 1389 | assert(scheme == COMPRESSION_SGILOG24 || scheme == COMPRESSION_SGILOG); |
| 1390 | |
| 1391 | /* |
| 1392 | * Allocate state block so tag methods have storage to record values. |
| 1393 | */ |
| 1394 | tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (LogLuvState)); |
| 1395 | if (tif->tif_data == NULL) |
| 1396 | goto bad; |
| 1397 | sp = (LogLuvState*) tif->tif_data; |
| 1398 | memset(sp, 0, sizeof (*sp)); |
| 1399 | sp->user_datafmt = SGILOGDATAFMT_UNKNOWN; |
| 1400 | sp->tfunc = _logLuvNop; |
| 1401 | |
| 1402 | /* |
| 1403 | * Install codec methods. |
| 1404 | * NB: tif_decoderow & tif_encoderow are filled |
| 1405 | * in at setup time. |
| 1406 | */ |
| 1407 | tif->tif_setupdecode = LogLuvSetupDecode; |
| 1408 | tif->tif_decodestrip = LogLuvDecodeStrip; |
| 1409 | tif->tif_decodetile = LogLuvDecodeTile; |
| 1410 | tif->tif_setupencode = LogLuvSetupEncode; |
| 1411 | tif->tif_encodestrip = LogLuvEncodeStrip; |
| 1412 | tif->tif_encodetile = LogLuvEncodeTile; |
| 1413 | tif->tif_close = LogLuvClose; |
| 1414 | tif->tif_cleanup = LogLuvCleanup; |
| 1415 | |
| 1416 | /* override SetField so we can handle our private pseudo-tag */ |
| 1417 | _TIFFMergeFieldInfo(tif, LogLuvFieldInfo, N(LogLuvFieldInfo)); |
| 1418 | sp->vgetparent = tif->tif_vgetfield; |
| 1419 | tif->tif_vgetfield = LogLuvVGetField; /* hook for codec tags */ |
| 1420 | sp->vsetparent = tif->tif_vsetfield; |
| 1421 | tif->tif_vsetfield = LogLuvVSetField; /* hook for codec tags */ |
| 1422 | |
| 1423 | return (1); |
| 1424 | bad: |
| 1425 | TIFFError(module, "%s: No space for LogLuv state block", tif->tif_name); |
| 1426 | return (0); |
| 1427 | } |
| 1428 | #endif /* LOGLUV_SUPPORT */ |