?? tif_pixarlog.c
字號(hào):
/* $Id: tif_pixarlog.c,v 1.4 2004/10/16 15:34:33 drolon Exp $ */
/*
* Copyright (c) 1996-1997 Sam Leffler
* Copyright (c) 1996 Pixar
*
* 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
* Pixar, Sam Leffler and Silicon Graphics may not be used in any advertising or
* publicity relating to the software without the specific, prior written
* permission of Pixar, Sam Leffler 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 PIXAR, SAM LEFFLER 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 PIXARLOG_SUPPORT
/*
* TIFF Library.
* PixarLog Compression Support
*
* Contributed by Dan McCoy.
*
* PixarLog film support uses the TIFF library to store companded
* 11 bit values into a tiff file, which are compressed using the
* zip compressor.
*
* The codec can take as input and produce as output 32-bit IEEE float values
* as well as 16-bit or 8-bit unsigned integer values.
*
* On writing any of the above are converted into the internal
* 11-bit log format. In the case of 8 and 16 bit values, the
* input is assumed to be unsigned linear color values that represent
* the range 0-1. In the case of IEEE values, the 0-1 range is assumed to
* be the normal linear color range, in addition over 1 values are
* accepted up to a value of about 25.0 to encode "hot" hightlights and such.
* The encoding is lossless for 8-bit values, slightly lossy for the
* other bit depths. The actual color precision should be better
* than the human eye can perceive with extra room to allow for
* error introduced by further image computation. As with any quantized
* color format, it is possible to perform image calculations which
* expose the quantization error. This format should certainly be less
* susceptable to such errors than standard 8-bit encodings, but more
* susceptable than straight 16-bit or 32-bit encodings.
*
* On reading the internal format is converted to the desired output format.
* The program can request which format it desires by setting the internal
* pseudo tag TIFFTAG_PIXARLOGDATAFMT to one of these possible values:
* PIXARLOGDATAFMT_FLOAT = provide IEEE float values.
* PIXARLOGDATAFMT_16BIT = provide unsigned 16-bit integer values
* PIXARLOGDATAFMT_8BIT = provide unsigned 8-bit integer values
*
* alternately PIXARLOGDATAFMT_8BITABGR provides unsigned 8-bit integer
* values with the difference that if there are exactly three or four channels
* (rgb or rgba) it swaps the channel order (bgr or abgr).
*
* PIXARLOGDATAFMT_11BITLOG provides the internal encoding directly
* packed in 16-bit values. However no tools are supplied for interpreting
* these values.
*
* "hot" (over 1.0) areas written in floating point get clamped to
* 1.0 in the integer data types.
*
* When the file is closed after writing, the bit depth and sample format
* are set always to appear as if 8-bit data has been written into it.
* That way a naive program unaware of the particulars of the encoding
* gets the format it is most likely able to handle.
*
* The codec does it's own horizontal differencing step on the coded
* values so the libraries predictor stuff should be turned off.
* The codec also handle byte swapping the encoded values as necessary
* since the library does not have the information necessary
* to know the bit depth of the raw unencoded buffer.
*
*/
#include "tif_predict.h"
#include "../ZLib/zlib.h"
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/* Tables for converting to/from 11 bit coded values */
#define TSIZE 2048 /* decode table size (11-bit tokens) */
#define TSIZEP1 2049 /* Plus one for slop */
#define ONE 1250 /* token value of 1.0 exactly */
#define RATIO 1.004 /* nominal ratio for log part */
#define CODE_MASK 0x7ff /* 11 bits. */
static float Fltsize;
static float LogK1, LogK2;
#define REPEAT(n, op) { int i; i=n; do { i--; op; } while (i>0); }
static void
horizontalAccumulateF(uint16 *wp, int n, int stride, float *op,
float *ToLinearF)
{
register unsigned int cr, cg, cb, ca, mask;
register float t0, t1, t2, t3;
if (n >= stride) {
mask = CODE_MASK;
if (stride == 3) {
t0 = ToLinearF[cr = wp[0]];
t1 = ToLinearF[cg = wp[1]];
t2 = ToLinearF[cb = wp[2]];
op[0] = t0;
op[1] = t1;
op[2] = t2;
n -= 3;
while (n > 0) {
wp += 3;
op += 3;
n -= 3;
t0 = ToLinearF[(cr += wp[0]) & mask];
t1 = ToLinearF[(cg += wp[1]) & mask];
t2 = ToLinearF[(cb += wp[2]) & mask];
op[0] = t0;
op[1] = t1;
op[2] = t2;
}
} else if (stride == 4) {
t0 = ToLinearF[cr = wp[0]];
t1 = ToLinearF[cg = wp[1]];
t2 = ToLinearF[cb = wp[2]];
t3 = ToLinearF[ca = wp[3]];
op[0] = t0;
op[1] = t1;
op[2] = t2;
op[3] = t3;
n -= 4;
while (n > 0) {
wp += 4;
op += 4;
n -= 4;
t0 = ToLinearF[(cr += wp[0]) & mask];
t1 = ToLinearF[(cg += wp[1]) & mask];
t2 = ToLinearF[(cb += wp[2]) & mask];
t3 = ToLinearF[(ca += wp[3]) & mask];
op[0] = t0;
op[1] = t1;
op[2] = t2;
op[3] = t3;
}
} else {
REPEAT(stride, *op = ToLinearF[*wp&mask]; wp++; op++)
n -= stride;
while (n > 0) {
REPEAT(stride,
wp[stride] += *wp; *op = ToLinearF[*wp&mask]; wp++; op++)
n -= stride;
}
}
}
}
static void
horizontalAccumulate12(uint16 *wp, int n, int stride, int16 *op,
float *ToLinearF)
{
register unsigned int cr, cg, cb, ca, mask;
register float t0, t1, t2, t3;
#define SCALE12 2048.0F
#define CLAMP12(t) (((t) < 3071) ? (uint16) (t) : 3071)
if (n >= stride) {
mask = CODE_MASK;
if (stride == 3) {
t0 = ToLinearF[cr = wp[0]] * SCALE12;
t1 = ToLinearF[cg = wp[1]] * SCALE12;
t2 = ToLinearF[cb = wp[2]] * SCALE12;
op[0] = CLAMP12(t0);
op[1] = CLAMP12(t1);
op[2] = CLAMP12(t2);
n -= 3;
while (n > 0) {
wp += 3;
op += 3;
n -= 3;
t0 = ToLinearF[(cr += wp[0]) & mask] * SCALE12;
t1 = ToLinearF[(cg += wp[1]) & mask] * SCALE12;
t2 = ToLinearF[(cb += wp[2]) & mask] * SCALE12;
op[0] = CLAMP12(t0);
op[1] = CLAMP12(t1);
op[2] = CLAMP12(t2);
}
} else if (stride == 4) {
t0 = ToLinearF[cr = wp[0]] * SCALE12;
t1 = ToLinearF[cg = wp[1]] * SCALE12;
t2 = ToLinearF[cb = wp[2]] * SCALE12;
t3 = ToLinearF[ca = wp[3]] * SCALE12;
op[0] = CLAMP12(t0);
op[1] = CLAMP12(t1);
op[2] = CLAMP12(t2);
op[3] = CLAMP12(t3);
n -= 4;
while (n > 0) {
wp += 4;
op += 4;
n -= 4;
t0 = ToLinearF[(cr += wp[0]) & mask] * SCALE12;
t1 = ToLinearF[(cg += wp[1]) & mask] * SCALE12;
t2 = ToLinearF[(cb += wp[2]) & mask] * SCALE12;
t3 = ToLinearF[(ca += wp[3]) & mask] * SCALE12;
op[0] = CLAMP12(t0);
op[1] = CLAMP12(t1);
op[2] = CLAMP12(t2);
op[3] = CLAMP12(t3);
}
} else {
REPEAT(stride, t0 = ToLinearF[*wp&mask] * SCALE12;
*op = CLAMP12(t0); wp++; op++)
n -= stride;
while (n > 0) {
REPEAT(stride,
wp[stride] += *wp; t0 = ToLinearF[wp[stride]&mask]*SCALE12;
*op = CLAMP12(t0); wp++; op++)
n -= stride;
}
}
}
}
static void
horizontalAccumulate16(uint16 *wp, int n, int stride, uint16 *op,
uint16 *ToLinear16)
{
register unsigned int cr, cg, cb, ca, mask;
if (n >= stride) {
mask = CODE_MASK;
if (stride == 3) {
op[0] = ToLinear16[cr = wp[0]];
op[1] = ToLinear16[cg = wp[1]];
op[2] = ToLinear16[cb = wp[2]];
n -= 3;
while (n > 0) {
wp += 3;
op += 3;
n -= 3;
op[0] = ToLinear16[(cr += wp[0]) & mask];
op[1] = ToLinear16[(cg += wp[1]) & mask];
op[2] = ToLinear16[(cb += wp[2]) & mask];
}
} else if (stride == 4) {
op[0] = ToLinear16[cr = wp[0]];
op[1] = ToLinear16[cg = wp[1]];
op[2] = ToLinear16[cb = wp[2]];
op[3] = ToLinear16[ca = wp[3]];
n -= 4;
while (n > 0) {
wp += 4;
op += 4;
n -= 4;
op[0] = ToLinear16[(cr += wp[0]) & mask];
op[1] = ToLinear16[(cg += wp[1]) & mask];
op[2] = ToLinear16[(cb += wp[2]) & mask];
op[3] = ToLinear16[(ca += wp[3]) & mask];
}
} else {
REPEAT(stride, *op = ToLinear16[*wp&mask]; wp++; op++)
n -= stride;
while (n > 0) {
REPEAT(stride,
wp[stride] += *wp; *op = ToLinear16[*wp&mask]; wp++; op++)
n -= stride;
}
}
}
}
/*
* Returns the log encoded 11-bit values with the horizontal
* differencing undone.
*/
static void
horizontalAccumulate11(uint16 *wp, int n, int stride, uint16 *op)
{
register unsigned int cr, cg, cb, ca, mask;
if (n >= stride) {
mask = CODE_MASK;
if (stride == 3) {
op[0] = cr = wp[0]; op[1] = cg = wp[1]; op[2] = cb = wp[2];
n -= 3;
while (n > 0) {
wp += 3;
op += 3;
n -= 3;
op[0] = (cr += wp[0]) & mask;
op[1] = (cg += wp[1]) & mask;
op[2] = (cb += wp[2]) & mask;
}
} else if (stride == 4) {
op[0] = cr = wp[0]; op[1] = cg = wp[1];
op[2] = cb = wp[2]; op[3] = ca = wp[3];
n -= 4;
while (n > 0) {
wp += 4;
op += 4;
n -= 4;
op[0] = (cr += wp[0]) & mask;
op[1] = (cg += wp[1]) & mask;
op[2] = (cb += wp[2]) & mask;
op[3] = (ca += wp[3]) & mask;
}
} else {
REPEAT(stride, *op = *wp&mask; wp++; op++)
n -= stride;
while (n > 0) {
REPEAT(stride,
wp[stride] += *wp; *op = *wp&mask; wp++; op++)
n -= stride;
}
}
}
}
static void
horizontalAccumulate8(uint16 *wp, int n, int stride, unsigned char *op,
unsigned char *ToLinear8)
{
register unsigned int cr, cg, cb, ca, mask;
if (n >= stride) {
mask = CODE_MASK;
if (stride == 3) {
op[0] = ToLinear8[cr = wp[0]];
op[1] = ToLinear8[cg = wp[1]];
op[2] = ToLinear8[cb = wp[2]];
n -= 3;
while (n > 0) {
n -= 3;
wp += 3;
op += 3;
op[0] = ToLinear8[(cr += wp[0]) & mask];
op[1] = ToLinear8[(cg += wp[1]) & mask];
op[2] = ToLinear8[(cb += wp[2]) & mask];
}
} else if (stride == 4) {
op[0] = ToLinear8[cr = wp[0]];
op[1] = ToLinear8[cg = wp[1]];
op[2] = ToLinear8[cb = wp[2]];
op[3] = ToLinear8[ca = wp[3]];
n -= 4;
while (n > 0) {
n -= 4;
wp += 4;
op += 4;
op[0] = ToLinear8[(cr += wp[0]) & mask];
op[1] = ToLinear8[(cg += wp[1]) & mask];
op[2] = ToLinear8[(cb += wp[2]) & mask];
op[3] = ToLinear8[(ca += wp[3]) & mask];
}
} else {
REPEAT(stride, *op = ToLinear8[*wp&mask]; wp++; op++)
n -= stride;
while (n > 0) {
REPEAT(stride,
wp[stride] += *wp; *op = ToLinear8[*wp&mask]; wp++; op++)
n -= stride;
}
}
}
}
static void
horizontalAccumulate8abgr(uint16 *wp, int n, int stride, unsigned char *op,
unsigned char *ToLinear8)
{
register unsigned int cr, cg, cb, ca, mask;
register unsigned char t0, t1, t2, t3;
if (n >= stride) {
mask = CODE_MASK;
if (stride == 3) {
op[0] = 0;
t1 = ToLinear8[cb = wp[2]];
t2 = ToLinear8[cg = wp[1]];
t3 = ToLinear8[cr = wp[0]];
op[1] = t1;
op[2] = t2;
op[3] = t3;
n -= 3;
while (n > 0) {
n -= 3;
wp += 3;
op += 4;
op[0] = 0;
t1 = ToLinear8[(cb += wp[2]) & mask];
t2 = ToLinear8[(cg += wp[1]) & mask];
t3 = ToLinear8[(cr += wp[0]) & mask];
op[1] = t1;
op[2] = t2;
op[3] = t3;
}
} else if (stride == 4) {
t0 = ToLinear8[ca = wp[3]];
t1 = ToLinear8[cb = wp[2]];
t2 = ToLinear8[cg = wp[1]];
t3 = ToLinear8[cr = wp[0]];
op[0] = t0;
op[1] = t1;
op[2] = t2;
op[3] = t3;
n -= 4;
while (n > 0) {
n -= 4;
wp += 4;
op += 4;
t0 = ToLinear8[(ca += wp[3]) & mask];
t1 = ToLinear8[(cb += wp[2]) & mask];
t2 = ToLinear8[(cg += wp[1]) & mask];
t3 = ToLinear8[(cr += wp[0]) & mask];
op[0] = t0;
op[1] = t1;
op[2] = t2;
op[3] = t3;
}
} else {
REPEAT(stride, *op = ToLinear8[*wp&mask]; wp++; op++)
n -= stride;
while (n > 0) {
REPEAT(stride,
wp[stride] += *wp; *op = ToLinear8[*wp&mask]; wp++; op++)
n -= stride;
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -