Added ability to decode floating point predictor, as per TIFF technical Note
3.
This commit is contained in:
parent
1125b82d29
commit
b737303768
@ -1,4 +1,4 @@
|
||||
/* $Id: tif_predict.c,v 1.6 2004-10-02 13:29:41 dron Exp $ */
|
||||
/* $Id: tif_predict.c,v 1.7 2005-04-14 11:57:30 dron Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988-1997 Sam Leffler
|
||||
@ -39,6 +39,7 @@ static void horAcc16(TIFF*, tidata_t, tsize_t);
|
||||
static void swabHorAcc16(TIFF*, tidata_t, tsize_t);
|
||||
static void horDiff8(TIFF*, tidata_t, tsize_t);
|
||||
static void horDiff16(TIFF*, tidata_t, tsize_t);
|
||||
static void fpAcc(TIFF*, tidata_t, tsize_t);
|
||||
static int PredictorDecodeRow(TIFF*, tidata_t, tsize_t, tsample_t);
|
||||
static int PredictorDecodeTile(TIFF*, tidata_t, tsize_t, tsample_t);
|
||||
static int PredictorEncodeRow(TIFF*, tidata_t, tsize_t, tsample_t);
|
||||
@ -47,21 +48,37 @@ static int PredictorEncodeTile(TIFF*, tidata_t, tsize_t, tsample_t);
|
||||
static int
|
||||
PredictorSetup(TIFF* tif)
|
||||
{
|
||||
static const char module[] = "PredictorSetup";
|
||||
|
||||
TIFFPredictorState* sp = PredictorState(tif);
|
||||
TIFFDirectory* td = &tif->tif_dir;
|
||||
|
||||
if (sp->predictor == 1) /* no differencing */
|
||||
return (1);
|
||||
if (sp->predictor != 2) {
|
||||
TIFFError(tif->tif_name, "\"Predictor\" value %d not supported",
|
||||
sp->predictor);
|
||||
return (0);
|
||||
}
|
||||
if (td->td_bitspersample != 8 && td->td_bitspersample != 16) {
|
||||
TIFFError(tif->tif_name,
|
||||
switch (sp->predictor) /* no differencing */
|
||||
{
|
||||
case PREDICTOR_NONE:
|
||||
return 1;
|
||||
case PREDICTOR_HORIZONTAL:
|
||||
if (td->td_bitspersample != 8
|
||||
&& td->td_bitspersample != 16) {
|
||||
TIFFError(module,
|
||||
"Horizontal differencing \"Predictor\" not supported with %d-bit samples",
|
||||
td->td_bitspersample);
|
||||
return (0);
|
||||
td->td_bitspersample);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case PREDICTOR_FLOATINGPOINT:
|
||||
if (td->td_sampleformat != SAMPLEFORMAT_IEEEFP) {
|
||||
TIFFError(module,
|
||||
"Floating point \"Predictor\" not supported with %d data format",
|
||||
td->td_sampleformat);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
TIFFError(module,
|
||||
"\"Predictor\" value %d not supported",
|
||||
sp->predictor);
|
||||
return 0;
|
||||
}
|
||||
sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ?
|
||||
td->td_samplesperpixel : 1);
|
||||
@ -72,7 +89,8 @@ PredictorSetup(TIFF* tif)
|
||||
sp->rowsize = TIFFTileRowSize(tif);
|
||||
else
|
||||
sp->rowsize = TIFFScanlineSize(tif);
|
||||
return (1);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -82,15 +100,16 @@ PredictorSetupDecode(TIFF* tif)
|
||||
TIFFDirectory* td = &tif->tif_dir;
|
||||
|
||||
if (!(*sp->setupdecode)(tif) || !PredictorSetup(tif))
|
||||
return (0);
|
||||
return 0;
|
||||
|
||||
if (sp->predictor == 2) {
|
||||
switch (td->td_bitspersample) {
|
||||
case 8: sp->pfunc = horAcc8; break;
|
||||
case 16: sp->pfunc = horAcc16; break;
|
||||
case 8: sp->pfunc = horAcc8; break;
|
||||
case 16: sp->pfunc = horAcc16; break;
|
||||
}
|
||||
/*
|
||||
* Override default decoding method with
|
||||
* one that does the predictor stuff.
|
||||
* Override default decoding method with one that does the
|
||||
* predictor stuff.
|
||||
*/
|
||||
sp->coderow = tif->tif_decoderow;
|
||||
tif->tif_decoderow = PredictorDecodeRow;
|
||||
@ -99,22 +118,47 @@ PredictorSetupDecode(TIFF* tif)
|
||||
sp->codetile = tif->tif_decodetile;
|
||||
tif->tif_decodetile = PredictorDecodeTile;
|
||||
/*
|
||||
* If the data is horizontally differenced
|
||||
* 16-bit data that requires byte-swapping,
|
||||
* then it must be byte swapped before the
|
||||
* accumulation step. We do this with a
|
||||
* special-purpose routine and override the
|
||||
* normal post decoding logic that the library
|
||||
* setup when the directory was read.
|
||||
* If the data is horizontally differenced 16-bit data that
|
||||
* requires byte-swapping, then it must be byte swapped before
|
||||
* the accumulation step. We do this with a special-purpose
|
||||
* routine and override the normal post decoding logic that
|
||||
* the library setup when the directory was read.
|
||||
*/
|
||||
if (tif->tif_flags&TIFF_SWAB) {
|
||||
if (tif->tif_flags & TIFF_SWAB) {
|
||||
if (sp->pfunc == horAcc16) {
|
||||
sp->pfunc = swabHorAcc16;
|
||||
tif->tif_postdecode = _TIFFNoPostDecode;
|
||||
} /* else handle 32-bit case... */
|
||||
}
|
||||
}
|
||||
return (1);
|
||||
|
||||
else if (sp->predictor == 3) {
|
||||
sp->pfunc = fpAcc;
|
||||
/*
|
||||
* Override default decoding method with one that does the
|
||||
* predictor stuff.
|
||||
*/
|
||||
sp->coderow = tif->tif_decoderow;
|
||||
tif->tif_decoderow = PredictorDecodeRow;
|
||||
sp->codestrip = tif->tif_decodestrip;
|
||||
tif->tif_decodestrip = PredictorDecodeTile;
|
||||
sp->codetile = tif->tif_decodetile;
|
||||
tif->tif_decodetile = PredictorDecodeTile;
|
||||
/*
|
||||
* The data should not be swapped outside of the floating
|
||||
* point predictor, the accumulation routine should return
|
||||
* byres in the native order.
|
||||
*/
|
||||
if (tif->tif_flags & TIFF_SWAB) {
|
||||
tif->tif_postdecode = _TIFFNoPostDecode;
|
||||
}
|
||||
/*
|
||||
* Allocate buffer to keep the decoded bytes before
|
||||
* rearranging in the ight order
|
||||
*/
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -157,8 +201,7 @@ PredictorSetupEncode(TIFF* tif)
|
||||
static void
|
||||
horAcc8(TIFF* tif, tidata_t cp0, tsize_t cc)
|
||||
{
|
||||
TIFFPredictorState* sp = PredictorState(tif);
|
||||
tsize_t stride = sp->stride;
|
||||
tsize_t stride = PredictorState(tif)->stride;
|
||||
|
||||
char* cp = (char*) cp0;
|
||||
if (cc > stride) {
|
||||
@ -200,8 +243,7 @@ horAcc8(TIFF* tif, tidata_t cp0, tsize_t cc)
|
||||
static void
|
||||
swabHorAcc16(TIFF* tif, tidata_t cp0, tsize_t cc)
|
||||
{
|
||||
TIFFPredictorState* sp = PredictorState(tif);
|
||||
tsize_t stride = sp->stride;
|
||||
tsize_t stride = PredictorState(tif)->stride;
|
||||
uint16* wp = (uint16*) cp0;
|
||||
tsize_t wc = cc / 2;
|
||||
|
||||
@ -231,6 +273,40 @@ horAcc16(TIFF* tif, tidata_t cp0, tsize_t cc)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Floating point predictor accumulation routine.
|
||||
*/
|
||||
static void
|
||||
fpAcc(TIFF* tif, tidata_t cp0, tsize_t cc)
|
||||
{
|
||||
tsize_t stride = PredictorState(tif)->stride;
|
||||
uint32 bps = tif->tif_dir.td_bitspersample / 8;
|
||||
tsize_t wc = cc / bps;
|
||||
tsize_t count = cc;
|
||||
uint8 *cp = (uint8 *) cp0;
|
||||
uint8 *tmp = (uint8 *)_TIFFmalloc(cc);
|
||||
|
||||
if (!tmp)
|
||||
return;
|
||||
|
||||
while (count > stride) {
|
||||
REPEAT4(stride, cp[stride] += cp[0]; cp++)
|
||||
count -= stride;
|
||||
}
|
||||
|
||||
_TIFFmemcpy(tmp, cp0, cc);
|
||||
cp = (uint8 *) cp0;
|
||||
for (count = 0; count < wc; count++) {
|
||||
uint32 byte;
|
||||
for (byte = 0; byte < bps; byte++) {
|
||||
tmp[bps * count + byte] =
|
||||
cp[(bps - byte - 1) * wc + count];
|
||||
}
|
||||
}
|
||||
_TIFFmemcpy(cp0, tmp, cc);
|
||||
_TIFFfree(tmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode a scanline and apply the predictor routine.
|
||||
*/
|
||||
@ -244,9 +320,9 @@ PredictorDecodeRow(TIFF* tif, tidata_t op0, tsize_t occ0, tsample_t s)
|
||||
assert(sp->pfunc != NULL);
|
||||
if ((*sp->coderow)(tif, op0, occ0, s)) {
|
||||
(*sp->pfunc)(tif, op0, occ0);
|
||||
return (1);
|
||||
return 1;
|
||||
} else
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -272,9 +348,9 @@ PredictorDecodeTile(TIFF* tif, tidata_t op0, tsize_t occ0, tsample_t s)
|
||||
occ0 -= rowsize;
|
||||
op0 += rowsize;
|
||||
}
|
||||
return (1);
|
||||
return 1;
|
||||
} else
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -350,7 +426,7 @@ PredictorEncodeRow(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
|
||||
assert(sp->coderow != NULL);
|
||||
/* XXX horizontal differencing alters user's data XXX */
|
||||
(*sp->pfunc)(tif, bp, cc);
|
||||
return ((*sp->coderow)(tif, bp, cc, s));
|
||||
return (*sp->coderow)(tif, bp, cc, s);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -370,7 +446,7 @@ PredictorEncodeTile(TIFF* tif, tidata_t bp0, tsize_t cc0, tsample_t s)
|
||||
cc -= rowsize;
|
||||
bp += rowsize;
|
||||
}
|
||||
return ((*sp->codetile)(tif, bp0, cc0, s));
|
||||
return (*sp->codetile)(tif, bp0, cc0, s);
|
||||
}
|
||||
|
||||
#define FIELD_PREDICTOR (FIELD_CODEC+0) /* XXX */
|
||||
@ -395,7 +471,7 @@ PredictorVSetField(TIFF* tif, ttag_t tag, va_list ap)
|
||||
return (*sp->vsetparent)(tif, tag, ap);
|
||||
}
|
||||
tif->tif_flags |= TIFF_DIRTYDIRECT;
|
||||
return (1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
@ -410,7 +486,7 @@ PredictorVGetField(TIFF* tif, ttag_t tag, va_list ap)
|
||||
default:
|
||||
return (*sp->vgetparent)(tif, tag, ap);
|
||||
}
|
||||
return (1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
@ -424,6 +500,7 @@ PredictorPrintDir(TIFF* tif, FILE* fd, long flags)
|
||||
switch (sp->predictor) {
|
||||
case 1: fprintf(fd, "none "); break;
|
||||
case 2: fprintf(fd, "horizontal differencing "); break;
|
||||
case 3: fprintf(fd, "floating point predictor "); break;
|
||||
}
|
||||
fprintf(fd, "%u (0x%x)\n", sp->predictor, sp->predictor);
|
||||
}
|
||||
@ -458,7 +535,7 @@ TIFFPredictorInit(TIFF* tif)
|
||||
|
||||
sp->predictor = 1; /* default value */
|
||||
sp->pfunc = NULL; /* no predictor routine */
|
||||
return (1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* vim: set ts=8 sts=8 sw=8 noet: */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $Header: /cvs/maptools/cvsroot/libtiff/libtiff/tif_predict.h,v 1.1 1999-07-27 21:50:27 mike Exp $ */
|
||||
/* $Id: tif_predict.h,v 1.2 2005-04-14 11:57:30 dron Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1995-1997 Sam Leffler
|
||||
@ -36,9 +36,9 @@
|
||||
* the predictor code can cast tif_data to find its state.
|
||||
*/
|
||||
typedef struct {
|
||||
int predictor; /* predictor tag value */
|
||||
int stride; /* sample stride over data */
|
||||
tsize_t rowsize; /* tile/strip row size */
|
||||
int predictor; /* predictor tag value */
|
||||
int stride; /* sample stride over data */
|
||||
tsize_t rowsize; /* tile/strip row size */
|
||||
|
||||
TIFFPostMethod pfunc; /* horizontal differencer/accumulator */
|
||||
TIFFCodeMethod coderow; /* parent codec encode/decode row */
|
||||
@ -59,3 +59,5 @@ extern int TIFFPredictorInit(TIFF*);
|
||||
}
|
||||
#endif
|
||||
#endif /* _TIFFPREDICT_ */
|
||||
|
||||
/* vim: set ts=8 sts=8 sw=8 noet: */
|
||||
|
Loading…
Reference in New Issue
Block a user