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