📄 tif_pixarlog.c
字号:
g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1;
b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1;
}
} else if (stride == 4) {
r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]);
b2 = wp[2] = CLAMP(ip[2]); a2 = wp[3] = CLAMP(ip[3]);
n -= 4;
while (n > 0) {
n -= 4;
wp += 4;
ip += 4;
r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1;
g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1;
b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1;
a1 = CLAMP(ip[3]); wp[3] = (a1-a2) & mask; a2 = a1;
}
} else {
ip += n - 1; /* point to last one */
wp += n - 1; /* point to last one */
n -= stride;
while (n > 0) {
REPEAT(stride, wp[0] = CLAMP(ip[0]);
wp[stride] -= wp[0];
wp[stride] &= mask;
wp--; ip--)
n -= stride;
}
REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--)
}
}
}
static void
horizontalDifference16(unsigned short *ip, int n, int stride,
unsigned short *wp, uint16 *From14)
{
register int r1, g1, b1, a1, r2, g2, b2, a2, mask;
/* assumption is unsigned pixel values */
#undef CLAMP
#define CLAMP(v) From14[(v) >> 2]
mask = CODE_MASK;
if (n >= stride) {
if (stride == 3) {
r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]);
b2 = wp[2] = CLAMP(ip[2]);
n -= 3;
while (n > 0) {
n -= 3;
wp += 3;
ip += 3;
r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1;
g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1;
b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1;
}
} else if (stride == 4) {
r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]);
b2 = wp[2] = CLAMP(ip[2]); a2 = wp[3] = CLAMP(ip[3]);
n -= 4;
while (n > 0) {
n -= 4;
wp += 4;
ip += 4;
r1 = CLAMP(ip[0]); wp[0] = (r1-r2) & mask; r2 = r1;
g1 = CLAMP(ip[1]); wp[1] = (g1-g2) & mask; g2 = g1;
b1 = CLAMP(ip[2]); wp[2] = (b1-b2) & mask; b2 = b1;
a1 = CLAMP(ip[3]); wp[3] = (a1-a2) & mask; a2 = a1;
}
} else {
ip += n - 1; /* point to last one */
wp += n - 1; /* point to last one */
n -= stride;
while (n > 0) {
REPEAT(stride, wp[0] = CLAMP(ip[0]);
wp[stride] -= wp[0];
wp[stride] &= mask;
wp--; ip--)
n -= stride;
}
REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--)
}
}
}
static void
horizontalDifference8(unsigned char *ip, int n, int stride,
unsigned short *wp, uint16 *From8)
{
register int r1, g1, b1, a1, r2, g2, b2, a2, mask;
#undef CLAMP
#define CLAMP(v) (From8[(v)])
mask = CODE_MASK;
if (n >= stride) {
if (stride == 3) {
r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]);
b2 = wp[2] = CLAMP(ip[2]);
n -= 3;
while (n > 0) {
n -= 3;
r1 = CLAMP(ip[3]); wp[3] = (r1-r2) & mask; r2 = r1;
g1 = CLAMP(ip[4]); wp[4] = (g1-g2) & mask; g2 = g1;
b1 = CLAMP(ip[5]); wp[5] = (b1-b2) & mask; b2 = b1;
wp += 3;
ip += 3;
}
} else if (stride == 4) {
r2 = wp[0] = CLAMP(ip[0]); g2 = wp[1] = CLAMP(ip[1]);
b2 = wp[2] = CLAMP(ip[2]); a2 = wp[3] = CLAMP(ip[3]);
n -= 4;
while (n > 0) {
n -= 4;
r1 = CLAMP(ip[4]); wp[4] = (r1-r2) & mask; r2 = r1;
g1 = CLAMP(ip[5]); wp[5] = (g1-g2) & mask; g2 = g1;
b1 = CLAMP(ip[6]); wp[6] = (b1-b2) & mask; b2 = b1;
a1 = CLAMP(ip[7]); wp[7] = (a1-a2) & mask; a2 = a1;
wp += 4;
ip += 4;
}
} else {
wp += n + stride - 1; /* point to last one */
ip += n + stride - 1; /* point to last one */
n -= stride;
while (n > 0) {
REPEAT(stride, wp[0] = CLAMP(ip[0]);
wp[stride] -= wp[0];
wp[stride] &= mask;
wp--; ip--)
n -= stride;
}
REPEAT(stride, wp[0] = CLAMP(ip[0]); wp--; ip--)
}
}
}
/*
* Encode a chunk of pixels.
*/
static int
PixarLogEncode(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
{
TIFFDirectory *td = &tif->tif_dir;
PixarLogState *sp = EncoderState(tif);
static const char module[] = "PixarLogEncode";
int i, n, llen;
unsigned short * up;
(void) s;
switch (sp->user_datafmt) {
case PIXARLOGDATAFMT_FLOAT:
n = cc / sizeof(float); /* XXX float == 32 bits */
break;
case PIXARLOGDATAFMT_16BIT:
case PIXARLOGDATAFMT_12BITPICIO:
case PIXARLOGDATAFMT_11BITLOG:
n = cc / sizeof(uint16); /* XXX uint16 == 16 bits */
break;
case PIXARLOGDATAFMT_8BIT:
case PIXARLOGDATAFMT_8BITABGR:
n = cc;
break;
default:
TIFFError(tif->tif_name,
"%d bit input not supported in PixarLog",
td->td_bitspersample);
return 0;
}
llen = sp->stride * td->td_imagewidth;
for (i = 0, up = sp->tbuf; i < n; i += llen, up += llen) {
switch (sp->user_datafmt) {
case PIXARLOGDATAFMT_FLOAT:
horizontalDifferenceF((float *)bp, llen,
sp->stride, up, sp->FromLT2);
bp += llen * sizeof(float);
break;
case PIXARLOGDATAFMT_16BIT:
horizontalDifference16((uint16 *)bp, llen,
sp->stride, up, sp->From14);
bp += llen * sizeof(uint16);
break;
case PIXARLOGDATAFMT_8BIT:
horizontalDifference8((unsigned char *)bp, llen,
sp->stride, up, sp->From8);
bp += llen * sizeof(unsigned char);
break;
default:
TIFFError(tif->tif_name,
"%d bit input not supported in PixarLog",
td->td_bitspersample);
return 0;
}
}
sp->stream.next_in = (unsigned char *) sp->tbuf;
sp->stream.avail_in = n * sizeof(uint16);
do {
if (deflate(&sp->stream, Z_NO_FLUSH) != Z_OK) {
TIFFError(module, "%s: Encoder error: %s",
tif->tif_name, sp->stream.msg);
return (0);
}
if (sp->stream.avail_out == 0) {
tif->tif_rawcc = tif->tif_rawdatasize;
TIFFFlushData1(tif);
sp->stream.next_out = tif->tif_rawdata;
sp->stream.avail_out = tif->tif_rawdatasize;
}
} while (sp->stream.avail_in > 0);
return (1);
}
/*
* Finish off an encoded strip by flushing the last
* string and tacking on an End Of Information code.
*/
static int
PixarLogPostEncode(TIFF* tif)
{
PixarLogState *sp = EncoderState(tif);
static const char module[] = "PixarLogPostEncode";
int state;
sp->stream.avail_in = 0;
do {
state = deflate(&sp->stream, Z_FINISH);
switch (state) {
case Z_STREAM_END:
case Z_OK:
if (sp->stream.avail_out != tif->tif_rawdatasize) {
tif->tif_rawcc =
tif->tif_rawdatasize - sp->stream.avail_out;
TIFFFlushData1(tif);
sp->stream.next_out = tif->tif_rawdata;
sp->stream.avail_out = tif->tif_rawdatasize;
}
break;
default:
TIFFError(module, "%s: zlib error: %s",
tif->tif_name, sp->stream.msg);
return (0);
}
} while (state != Z_STREAM_END);
return (1);
}
static void
PixarLogClose(TIFF* tif)
{
TIFFDirectory *td = &tif->tif_dir;
/* In a really sneaky maneuver, on close, we covertly modify both
* bitspersample and sampleformat in the directory to indicate
* 8-bit linear. This way, the decode "just works" even for
* readers that don't know about PixarLog, or how to set
* the PIXARLOGDATFMT pseudo-tag.
*/
td->td_bitspersample = 8;
td->td_sampleformat = SAMPLEFORMAT_UINT;
}
static void
PixarLogCleanup(TIFF* tif)
{
PixarLogState* sp = (PixarLogState*) tif->tif_data;
if (sp) {
if (sp->FromLT2) _TIFFfree(sp->FromLT2);
if (sp->From14) _TIFFfree(sp->From14);
if (sp->From8) _TIFFfree(sp->From8);
if (sp->ToLinearF) _TIFFfree(sp->ToLinearF);
if (sp->ToLinear16) _TIFFfree(sp->ToLinear16);
if (sp->ToLinear8) _TIFFfree(sp->ToLinear8);
if (sp->state&PLSTATE_INIT) {
if (tif->tif_mode == O_RDONLY)
inflateEnd(&sp->stream);
else
deflateEnd(&sp->stream);
}
if (sp->tbuf)
_TIFFfree(sp->tbuf);
_TIFFfree(sp);
tif->tif_data = NULL;
}
}
static int
PixarLogVSetField(TIFF* tif, ttag_t tag, va_list ap)
{
PixarLogState *sp = (PixarLogState *)tif->tif_data;
int result;
static const char module[] = "PixarLogVSetField";
switch (tag) {
case TIFFTAG_PIXARLOGQUALITY:
sp->quality = va_arg(ap, int);
if (tif->tif_mode != O_RDONLY && (sp->state&PLSTATE_INIT)) {
if (deflateParams(&sp->stream,
sp->quality, Z_DEFAULT_STRATEGY) != Z_OK) {
TIFFError(module, "%s: zlib error: %s",
tif->tif_name, sp->stream.msg);
return (0);
}
}
return (1);
case TIFFTAG_PIXARLOGDATAFMT:
sp->user_datafmt = va_arg(ap, int);
/* Tweak the TIFF header so that the rest of libtiff knows what
* size of data will be passed between app and library, and
* assume that the app knows what it is doing and is not
* confused by these header manipulations...
*/
switch (sp->user_datafmt) {
case PIXARLOGDATAFMT_8BIT:
case PIXARLOGDATAFMT_8BITABGR:
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 8);
TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
break;
case PIXARLOGDATAFMT_11BITLOG:
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
break;
case PIXARLOGDATAFMT_12BITPICIO:
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_INT);
break;
case PIXARLOGDATAFMT_16BIT:
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 16);
TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_UINT);
break;
case PIXARLOGDATAFMT_FLOAT:
TIFFSetField(tif, TIFFTAG_BITSPERSAMPLE, 32);
TIFFSetField(tif, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);
break;
}
/*
* Must recalculate sizes should bits/sample change.
*/
tif->tif_tilesize = isTiled(tif) ? TIFFTileSize(tif) : (tsize_t) -1;
tif->tif_scanlinesize = TIFFScanlineSize(tif);
result = 1; /* NB: pseudo tag */
break;
default:
result = (*sp->vsetparent)(tif, tag, ap);
}
return (result);
}
static int
PixarLogVGetField(TIFF* tif, ttag_t tag, va_list ap)
{
PixarLogState *sp = (PixarLogState *)tif->tif_data;
switch (tag) {
case TIFFTAG_PIXARLOGQUALITY:
*va_arg(ap, int*) = sp->quality;
break;
case TIFFTAG_PIXARLOGDATAFMT:
*va_arg(ap, int*) = sp->user_datafmt;
break;
default:
return (*sp->vgetparent)(tif, tag, ap);
}
return (1);
}
static const TIFFFieldInfo pixarlogFieldInfo[] = {
{TIFFTAG_PIXARLOGDATAFMT,0,0,TIFF_ANY, FIELD_PSEUDO,FALSE,FALSE,""},
{TIFFTAG_PIXARLOGQUALITY,0,0,TIFF_ANY, FIELD_PSEUDO,FALSE,FALSE,""}
};
int
TIFFInitPixarLog(TIFF* tif, int scheme)
{
PixarLogState* sp;
assert(scheme == COMPRESSION_PIXARLOG);
/*
* Allocate state block so tag methods have storage to record values.
*/
tif->tif_data = (tidata_t) _TIFFmalloc(sizeof (PixarLogState));
if (tif->tif_data == NULL)
goto bad;
sp = (PixarLogState*) tif->tif_data;
_TIFFmemset(sp, 0, sizeof (*sp));
sp->stream.data_type = Z_BINARY;
sp->user_datafmt = PIXARLOGDATAFMT_UNKNOWN;
/*
* Install codec methods.
*/
tif->tif_setupdecode = PixarLogSetupDecode;
tif->tif_predecode = PixarLogPreDecode;
tif->tif_decoderow = PixarLogDecode;
tif->tif_decodestrip = PixarLogDecode;
tif->tif_decodetile = PixarLogDecode;
tif->tif_setupencode = PixarLogSetupEncode;
tif->tif_preencode = PixarLogPreEncode;
tif->tif_postencode = PixarLogPostEncode;
tif->tif_encoderow = PixarLogEncode;
tif->tif_encodestrip = PixarLogEncode;
tif->tif_encodetile = PixarLogEncode;
tif->tif_close = PixarLogClose;
tif->tif_cleanup = PixarLogCleanup;
/* Override SetField so we can handle our private pseudo-tag */
_TIFFMergeFieldInfo(tif, pixarlogFieldInfo, N(pixarlogFieldInfo));
sp->vgetparent = tif->tif_tagmethods.vgetfield;
tif->tif_tagmethods.vgetfield = PixarLogVGetField; /* hook for codec tags */
sp->vsetparent = tif->tif_tagmethods.vsetfield;
tif->tif_tagmethods.vsetfield = PixarLogVSetField; /* hook for codec tags */
/* Default values for codec-specific fields */
sp->quality = Z_DEFAULT_COMPRESSION; /* default comp. level */
sp->state = 0;
/* we don't wish to use the predictor,
* the default is none, which predictor value 1
*/
(void) TIFFPredictorInit(tif);
/*
* build the companding tables
*/
PixarLogMakeTables(sp);
return (1);
bad:
TIFFError("TIFFInitPixarLog", "No space for PixarLog state block");
return (0);
}
#endif /* PIXARLOG_SUPPORT */
/* vim: set ts=8 sts=8 sw=8 noet: */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -