Added ability to decode floating point predictor, as per TIFF technical Note

3.
This commit is contained in:
Andrey Kiselev 2005-04-14 11:57:30 +00:00
parent 1125b82d29
commit b737303768
2 changed files with 123 additions and 44 deletions

View File

@ -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: */

View File

@ -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: */