📄 tif_luv.c
字号:
/* * Copyright (c) 1997 Greg Ward Larson * Copyright (c) 1997 Silicon Graphics, Inc. * * Permission to use, copy, modify, distribute, and sell this software and * its documentation for any purpose is hereby granted without fee, provided * that (i) the above copyright notices and this permission notice appear in * all copies of the software and related documentation, and (ii) the names of * Sam Leffler, Greg Larson and Silicon Graphics may not be used in any * advertising or publicity relating to the software without the specific, * prior written permission of Sam Leffler, Greg Larson and Silicon Graphics. * * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. * * IN NO EVENT SHALL SAM LEFFLER, GREG LARSON OR SILICON GRAPHICS BE LIABLE * FOR ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE * OF THIS SOFTWARE. */#include "tiffiop.h"#ifdef LOGLUV_SUPPORT/* * TIFF Library. * LogLuv compression support for high dynamic range images. * * Contributed by Greg Larson. * * LogLuv image support uses the TIFF library to store 16 or 10-bit * log luminance values with 8 bits each of u and v or a 14-bit index. * * The codec can take as input and produce as output 32-bit IEEE float values * as well as 16-bit integer values. A 16-bit luminance is interpreted * as a sign bit followed by a 15-bit integer that is converted * to and from a linear magnitude using the transformation: * * L = 2^( (Le+.5)/256 - 64 ) # real from 15-bit * * Le = floor( 256*(log2(L) + 64) ) # 15-bit from real * * The actual conversion to world luminance units in candelas per sq. meter * requires an additional multiplier, which is stored in the TIFFTAG_STONITS. * This value is usually set such that a reasonable exposure comes from * clamping decoded luminances above 1 to 1 in the displayed image. * * The 16-bit values for u and v may be converted to real values by dividing * each by 32768. (This allows for negative values, which aren't useful as * far as we know, but are left in case of future improvements in human * color vision.) * * Conversion from (u,v), which is actually the CIE (u',v') system for * you color scientists, is accomplished by the following transformation: * * u = 4*x / (-2*x + 12*y + 3) * v = 9*y / (-2*x + 12*y + 3) * * x = 9*u / (6*u - 16*v + 12) * y = 4*v / (6*u - 16*v + 12) * * This process is greatly simplified by passing 32-bit IEEE floats * for each of three CIE XYZ coordinates. The codec then takes care * of conversion to and from LogLuv, though the application is still * responsible for interpreting the TIFFTAG_STONITS calibration factor. * * By definition, a CIE XYZ vector of [1 1 1] corresponds to a neutral white * point of (x,y)=(1/3,1/3). However, most color systems assume some other * white point, such as D65, and an absolute color conversion to XYZ then * to another color space with a different white point may introduce an * unwanted color cast to the image. It is often desirable, therefore, to * perform a white point conversion that maps the input white to [1 1 1] * in XYZ, then record the original white point using the TIFFTAG_WHITEPOINT * tag value. A decoder that demands absolute color calibration may use * this white point tag to get back the original colors, but usually it * will be ignored and the new white point will be used instead that * matches the output color space. * * Pixel information is compressed into one of two basic encodings, depending * on the setting of the compression tag, which is one of COMPRESSION_SGILOG * or COMPRESSION_SGILOG24. For COMPRESSION_SGILOG, greyscale data is * stored as: * * 1 15 * |-+---------------| * * COMPRESSION_SGILOG color data is stored as: * * 1 15 8 8 * |-+---------------|--------+--------| * S Le ue ve * * For the 24-bit COMPRESSION_SGILOG24 color format, the data is stored as: * * 10 14 * |----------|--------------| * Le' Ce * * There is no sign bit in the 24-bit case, and the (u,v) chromaticity is * encoded as an index for optimal color resolution. The 10 log bits are * defined by the following conversions: * * L = 2^((Le'+.5)/64 - 12) # real from 10-bit * * Le' = floor( 64*(log2(L) + 12) ) # 10-bit from real * * The 10 bits of the smaller format may be converted into the 15 bits of * the larger format by multiplying by 4 and adding 13314. Obviously, * a smaller range of magnitudes is covered (about 5 orders of magnitude * instead of 38), and the lack of a sign bit means that negative luminances * are not allowed. (Well, they aren't allowed in the real world, either, * but they are useful for certain types of image processing.) * * The desired user format is controlled by the setting the internal * pseudo tag TIFFTAG_SGILOGDATAFMT to one of: * SGILOGDATAFMT_FLOAT = IEEE 32-bit float XYZ values * SGILOGDATAFMT_16BIT = 16-bit integer encodings of logL, u and v * Raw data i/o is also possible using: * SGILOGDATAFMT_RAW = 32-bit unsigned integer with encoded pixel * In addition, the following decoding is provided for ease of display: * SGILOGDATAFMT_8BIT = 8-bit default RGB gamma-corrected values * * For grayscale images, we provide the following data formats: * SGILOGDATAFMT_FLOAT = IEEE 32-bit float Y values * SGILOGDATAFMT_16BIT = 16-bit integer w/ encoded luminance * SGILOGDATAFMT_8BIT = 8-bit gray monitor values * * Note that the COMPRESSION_SGILOG applies a simple run-length encoding * scheme by separating the logL, u and v bytes for each row and applying * a PackBits type of compression. Since the 24-bit encoding is not * adaptive, the 32-bit color format takes less space in many cases. * * Further control is provided over the conversion from higher-resolution * formats to final encoded values through the pseudo tag * TIFFTAG_SGILOGENCODE: * SGILOGENCODE_NODITHER = do not dither encoded values * SGILOGENCODE_RANDITHER = apply random dithering during encoding * * The default value of this tag is SGILOGENCODE_NODITHER for * COMPRESSION_SGILOG to maximize run-length encoding and * SGILOGENCODE_RANDITHER for COMPRESSION_SGILOG24 to turn * quantization errors into noise. */#include <stdio.h>#include <assert.h>#include <stdlib.h>#include <math.h>/* * State block for each open TIFF * file using LogLuv compression/decompression. */typedef struct logLuvState LogLuvState;struct logLuvState { int user_datafmt; /* user data format */ int encode_meth; /* encoding method */ int pixel_size; /* bytes per pixel */ tidata_t* tbuf; /* translation buffer */ int tbuflen; /* buffer length */ void (*tfunc)(LogLuvState*, tidata_t, int); TIFFVSetMethod vgetparent; /* super-class method */ TIFFVSetMethod vsetparent; /* super-class method */};#define DecoderState(tif) ((LogLuvState*) (tif)->tif_data)#define EncoderState(tif) ((LogLuvState*) (tif)->tif_data)#define N(a) (sizeof(a)/sizeof(a[0]))#define SGILOGDATAFMT_UNKNOWN -1#define MINRUN 4 /* minimum run length *//* * Decode a string of 16-bit gray pixels. */static intLogL16Decode(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s){ LogLuvState* sp = DecoderState(tif); int shft, i, npixels; u_char* bp; int16* tp; int16 b; int cc, rc; assert(s == 0); assert(sp != NULL); npixels = occ / sp->pixel_size; if (sp->user_datafmt == SGILOGDATAFMT_16BIT) tp = (int16*) op; else { assert(sp->tbuflen >= npixels); tp = (int16*) sp->tbuf; } _TIFFmemset((tdata_t) tp, 0, npixels*sizeof (tp[0])); bp = (u_char*) tif->tif_rawcp; cc = tif->tif_rawcc; /* get each byte string */ for (shft = 2*8; (shft -= 8) >= 0; ) { for (i = 0; i < npixels && cc > 0; ) if (*bp >= 128) { /* run */ rc = *bp++ + (2-128); b = (int16)*bp++ << shft; cc -= 2; while (rc--) tp[i++] |= b; } else { /* non-run */ rc = *bp++; /* nul is noop */ while (--cc && rc--) tp[i++] |= (int16)*bp++ << shft; } if (i != npixels) { TIFFError(tif->tif_name, "LogL16Decode: Not enough data at row %d (short %d pixels)", tif->tif_row, npixels - i); tif->tif_rawcp = (tidata_t) bp; tif->tif_rawcc = cc; return (0); } } (*sp->tfunc)(sp, op, npixels); tif->tif_rawcp = (tidata_t) bp; tif->tif_rawcc = cc; return (1);}/* * Decode a string of 24-bit pixels. */static intLogLuvDecode24(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s){ LogLuvState* sp = DecoderState(tif); int cc, i, npixels; u_char* bp; uint32* tp; assert(s == 0); assert(sp != NULL); npixels = occ / sp->pixel_size; if (sp->user_datafmt == SGILOGDATAFMT_RAW) tp = (uint32 *)op; else { assert(sp->tbuflen >= npixels); tp = (uint32 *) sp->tbuf; } /* copy to array of uint32 */ bp = (u_char*) tif->tif_rawcp; cc = tif->tif_rawcc; for (i = 0; i < npixels && cc > 0; i++) { tp[i] = bp[0] << 16 | bp[1] << 8 | bp[2]; bp += 3; cc -= 3; } tif->tif_rawcp = (tidata_t) bp; tif->tif_rawcc = cc; if (i != npixels) { TIFFError(tif->tif_name, "LogLuvDecode24: Not enough data at row %d (short %d pixels)", tif->tif_row, npixels - i); return (0); } (*sp->tfunc)(sp, op, npixels); return (1);}/* * Decode a string of 32-bit pixels. */static intLogLuvDecode32(TIFF* tif, tidata_t op, tsize_t occ, tsample_t s){ LogLuvState* sp; int shft, i, npixels; u_char* bp; uint32* tp; uint32 b; int cc, rc; assert(s == 0); sp = DecoderState(tif); assert(sp != NULL); npixels = occ / sp->pixel_size; if (sp->user_datafmt == SGILOGDATAFMT_RAW) tp = (uint32*) op; else { assert(sp->tbuflen >= npixels); tp = (uint32*) sp->tbuf; } _TIFFmemset((tdata_t) tp, 0, npixels*sizeof (tp[0])); bp = (u_char*) tif->tif_rawcp; cc = tif->tif_rawcc; /* get each byte string */ for (shft = 4*8; (shft -= 8) >= 0; ) { for (i = 0; i < npixels && cc > 0; ) if (*bp >= 128) { /* run */ rc = *bp++ + (2-128); b = (uint32)*bp++ << shft; cc -= 2; while (rc--) tp[i++] |= b; } else { /* non-run */ rc = *bp++; /* nul is noop */ while (--cc && rc--) tp[i++] |= (uint32)*bp++ << shft; } if (i != npixels) { TIFFError(tif->tif_name, "LogLuvDecode32: Not enough data at row %d (short %d pixels)", tif->tif_row, npixels - i); tif->tif_rawcp = (tidata_t) bp; tif->tif_rawcc = cc; return (0); } } (*sp->tfunc)(sp, op, npixels); tif->tif_rawcp = (tidata_t) bp; tif->tif_rawcc = cc; return (1);}/* * Decode a strip of pixels. We break it into rows to * maintain synchrony with the encode algorithm, which * is row by row. */static intLogLuvDecodeStrip(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s){ tsize_t rowlen = TIFFScanlineSize(tif); assert(cc%rowlen == 0); while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s)) bp += rowlen, cc -= rowlen; return (cc == 0);}/* * Decode a tile of pixels. We break it into rows to * maintain synchrony with the encode algorithm, which * is row by row. */static intLogLuvDecodeTile(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s){ tsize_t rowlen = TIFFTileRowSize(tif); assert(cc%rowlen == 0); while (cc && (*tif->tif_decoderow)(tif, bp, rowlen, s)) bp += rowlen, cc -= rowlen; return (cc == 0);}/* * Encode a row of 16-bit pixels. */static intLogL16Encode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s){ LogLuvState* sp = EncoderState(tif); int shft, i, j, npixels; tidata_t op; int16* tp; int16 b; int occ, rc=0, mask, beg; assert(s == 0); assert(sp != NULL); npixels = cc / sp->pixel_size; if (sp->user_datafmt == SGILOGDATAFMT_16BIT) tp = (int16*) bp; else { tp = (int16*) sp->tbuf; assert(sp->tbuflen >= npixels); (*sp->tfunc)(sp, bp, npixels); } /* compress each byte string */ op = tif->tif_rawcp; occ = tif->tif_rawdatasize - tif->tif_rawcc; for (shft = 2*8; (shft -= 8) >= 0; ) for (i = 0; i < npixels; i += rc) { if (occ < 4) { tif->tif_rawcp = op; tif->tif_rawcc = tif->tif_rawdatasize - occ; if (!TIFFFlushData1(tif)) return (-1); op = tif->tif_rawcp; occ = tif->tif_rawdatasize - tif->tif_rawcc; } mask = 0xff << shft; /* find next run */ for (beg = i; beg < npixels; beg += rc) { b = tp[beg] & mask; rc = 1; while (rc < 127+2 && beg+rc < npixels && (tp[beg+rc] & mask) == b) rc++; if (rc >= MINRUN) break; /* long enough */ } if (beg-i > 1 && beg-i < MINRUN) { b = tp[i] & mask; /* check short run */ j = i+1; while ((tp[j++] & mask) == b) if (j == beg) { *op++ = 128-2+j-i; *op++ = b >> shft; occ -= 2; i = beg; break; } } while (i < beg) { /* write out non-run */ if ((j = beg-i) > 127) j = 127; if (occ < j+3) { tif->tif_rawcp = op; tif->tif_rawcc = tif->tif_rawdatasize - occ; if (!TIFFFlushData1(tif)) return (-1); op = tif->tif_rawcp; occ = tif->tif_rawdatasize - tif->tif_rawcc; } *op++ = j; occ--; while (j--) { *op++ = tp[i++] >> shft & 0xff; occ--; } } if (rc >= MINRUN) { /* write out run */ *op++ = 128-2+rc; *op++ = tp[beg] >> shft & 0xff; occ -= 2; } else rc = 0; } tif->tif_rawcp = op; tif->tif_rawcc = tif->tif_rawdatasize - occ; return (0);}/* * Encode a row of 24-bit pixels. */static intLogLuvEncode24(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s){ LogLuvState* sp = EncoderState(tif); int i, npixels, occ; tidata_t op; uint32* tp; assert(s == 0); assert(sp != NULL); npixels = cc / sp->pixel_size; if (sp->user_datafmt == SGILOGDATAFMT_RAW) tp = (uint32*) bp; else { tp = (uint32*) sp->tbuf; assert(sp->tbuflen >= npixels); (*sp->tfunc)(sp, bp, npixels); } /* write out encoded pixels */ op = tif->tif_rawcp; occ = tif->tif_rawdatasize - tif->tif_rawcc; for (i = npixels; i--; ) { if (occ < 3) { tif->tif_rawcp = op; tif->tif_rawcc = tif->tif_rawdatasize - occ; if (!TIFFFlushData1(tif)) return (-1); op = tif->tif_rawcp; occ = tif->tif_rawdatasize - tif->tif_rawcc; } *op++ = (tidataval_t)(*tp >> 16); *op++ = (tidataval_t)(*tp >> 8 & 0xff); *op++ = (tidataval_t)(*tp++ & 0xff); occ -= 3; } tif->tif_rawcp = op; tif->tif_rawcc = tif->tif_rawdatasize - occ; return (0);}/* * Encode a row of 32-bit pixels. */static intLogLuvEncode32(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s){ LogLuvState* sp = EncoderState(tif); int shft, i, j, npixels; tidata_t op; uint32* tp; uint32 b; int occ, rc=0, mask, beg; assert(s == 0); assert(sp != NULL); npixels = cc / sp->pixel_size; if (sp->user_datafmt == SGILOGDATAFMT_RAW) tp = (uint32*) bp; else { tp = (uint32*) sp->tbuf; assert(sp->tbuflen >= npixels); (*sp->tfunc)(sp, bp, npixels); } /* compress each byte string */ op = tif->tif_rawcp; occ = tif->tif_rawdatasize - tif->tif_rawcc;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -