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
|
* 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 swabHorAcc16(TIFF*, tidata_t, tsize_t);
|
||||||
static void horDiff8(TIFF*, tidata_t, tsize_t);
|
static void horDiff8(TIFF*, tidata_t, tsize_t);
|
||||||
static void horDiff16(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 PredictorDecodeRow(TIFF*, tidata_t, tsize_t, tsample_t);
|
||||||
static int PredictorDecodeTile(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);
|
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
|
static int
|
||||||
PredictorSetup(TIFF* tif)
|
PredictorSetup(TIFF* tif)
|
||||||
{
|
{
|
||||||
|
static const char module[] = "PredictorSetup";
|
||||||
|
|
||||||
TIFFPredictorState* sp = PredictorState(tif);
|
TIFFPredictorState* sp = PredictorState(tif);
|
||||||
TIFFDirectory* td = &tif->tif_dir;
|
TIFFDirectory* td = &tif->tif_dir;
|
||||||
|
|
||||||
if (sp->predictor == 1) /* no differencing */
|
switch (sp->predictor) /* no differencing */
|
||||||
return (1);
|
{
|
||||||
if (sp->predictor != 2) {
|
case PREDICTOR_NONE:
|
||||||
TIFFError(tif->tif_name, "\"Predictor\" value %d not supported",
|
return 1;
|
||||||
sp->predictor);
|
case PREDICTOR_HORIZONTAL:
|
||||||
return (0);
|
if (td->td_bitspersample != 8
|
||||||
}
|
&& td->td_bitspersample != 16) {
|
||||||
if (td->td_bitspersample != 8 && td->td_bitspersample != 16) {
|
TIFFError(module,
|
||||||
TIFFError(tif->tif_name,
|
|
||||||
"Horizontal differencing \"Predictor\" not supported with %d-bit samples",
|
"Horizontal differencing \"Predictor\" not supported with %d-bit samples",
|
||||||
td->td_bitspersample);
|
td->td_bitspersample);
|
||||||
return (0);
|
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 ?
|
sp->stride = (td->td_planarconfig == PLANARCONFIG_CONTIG ?
|
||||||
td->td_samplesperpixel : 1);
|
td->td_samplesperpixel : 1);
|
||||||
@ -72,7 +89,8 @@ PredictorSetup(TIFF* tif)
|
|||||||
sp->rowsize = TIFFTileRowSize(tif);
|
sp->rowsize = TIFFTileRowSize(tif);
|
||||||
else
|
else
|
||||||
sp->rowsize = TIFFScanlineSize(tif);
|
sp->rowsize = TIFFScanlineSize(tif);
|
||||||
return (1);
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -82,15 +100,16 @@ PredictorSetupDecode(TIFF* tif)
|
|||||||
TIFFDirectory* td = &tif->tif_dir;
|
TIFFDirectory* td = &tif->tif_dir;
|
||||||
|
|
||||||
if (!(*sp->setupdecode)(tif) || !PredictorSetup(tif))
|
if (!(*sp->setupdecode)(tif) || !PredictorSetup(tif))
|
||||||
return (0);
|
return 0;
|
||||||
|
|
||||||
if (sp->predictor == 2) {
|
if (sp->predictor == 2) {
|
||||||
switch (td->td_bitspersample) {
|
switch (td->td_bitspersample) {
|
||||||
case 8: sp->pfunc = horAcc8; break;
|
case 8: sp->pfunc = horAcc8; break;
|
||||||
case 16: sp->pfunc = horAcc16; break;
|
case 16: sp->pfunc = horAcc16; break;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
* Override default decoding method with
|
* Override default decoding method with one that does the
|
||||||
* one that does the predictor stuff.
|
* predictor stuff.
|
||||||
*/
|
*/
|
||||||
sp->coderow = tif->tif_decoderow;
|
sp->coderow = tif->tif_decoderow;
|
||||||
tif->tif_decoderow = PredictorDecodeRow;
|
tif->tif_decoderow = PredictorDecodeRow;
|
||||||
@ -99,22 +118,47 @@ PredictorSetupDecode(TIFF* tif)
|
|||||||
sp->codetile = tif->tif_decodetile;
|
sp->codetile = tif->tif_decodetile;
|
||||||
tif->tif_decodetile = PredictorDecodeTile;
|
tif->tif_decodetile = PredictorDecodeTile;
|
||||||
/*
|
/*
|
||||||
* If the data is horizontally differenced
|
* If the data is horizontally differenced 16-bit data that
|
||||||
* 16-bit data that requires byte-swapping,
|
* requires byte-swapping, then it must be byte swapped before
|
||||||
* then it must be byte swapped before the
|
* the accumulation step. We do this with a special-purpose
|
||||||
* accumulation step. We do this with a
|
* routine and override the normal post decoding logic that
|
||||||
* special-purpose routine and override the
|
* the library setup when the directory was read.
|
||||||
* 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) {
|
if (sp->pfunc == horAcc16) {
|
||||||
sp->pfunc = swabHorAcc16;
|
sp->pfunc = swabHorAcc16;
|
||||||
tif->tif_postdecode = _TIFFNoPostDecode;
|
tif->tif_postdecode = _TIFFNoPostDecode;
|
||||||
} /* else handle 32-bit case... */
|
} /* 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
|
static int
|
||||||
@ -157,8 +201,7 @@ PredictorSetupEncode(TIFF* tif)
|
|||||||
static void
|
static void
|
||||||
horAcc8(TIFF* tif, tidata_t cp0, tsize_t cc)
|
horAcc8(TIFF* tif, tidata_t cp0, tsize_t cc)
|
||||||
{
|
{
|
||||||
TIFFPredictorState* sp = PredictorState(tif);
|
tsize_t stride = PredictorState(tif)->stride;
|
||||||
tsize_t stride = sp->stride;
|
|
||||||
|
|
||||||
char* cp = (char*) cp0;
|
char* cp = (char*) cp0;
|
||||||
if (cc > stride) {
|
if (cc > stride) {
|
||||||
@ -200,8 +243,7 @@ horAcc8(TIFF* tif, tidata_t cp0, tsize_t cc)
|
|||||||
static void
|
static void
|
||||||
swabHorAcc16(TIFF* tif, tidata_t cp0, tsize_t cc)
|
swabHorAcc16(TIFF* tif, tidata_t cp0, tsize_t cc)
|
||||||
{
|
{
|
||||||
TIFFPredictorState* sp = PredictorState(tif);
|
tsize_t stride = PredictorState(tif)->stride;
|
||||||
tsize_t stride = sp->stride;
|
|
||||||
uint16* wp = (uint16*) cp0;
|
uint16* wp = (uint16*) cp0;
|
||||||
tsize_t wc = cc / 2;
|
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.
|
* 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);
|
assert(sp->pfunc != NULL);
|
||||||
if ((*sp->coderow)(tif, op0, occ0, s)) {
|
if ((*sp->coderow)(tif, op0, occ0, s)) {
|
||||||
(*sp->pfunc)(tif, op0, occ0);
|
(*sp->pfunc)(tif, op0, occ0);
|
||||||
return (1);
|
return 1;
|
||||||
} else
|
} else
|
||||||
return (0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -272,9 +348,9 @@ PredictorDecodeTile(TIFF* tif, tidata_t op0, tsize_t occ0, tsample_t s)
|
|||||||
occ0 -= rowsize;
|
occ0 -= rowsize;
|
||||||
op0 += rowsize;
|
op0 += rowsize;
|
||||||
}
|
}
|
||||||
return (1);
|
return 1;
|
||||||
} else
|
} else
|
||||||
return (0);
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -350,7 +426,7 @@ PredictorEncodeRow(TIFF* tif, tidata_t bp, tsize_t cc, tsample_t s)
|
|||||||
assert(sp->coderow != NULL);
|
assert(sp->coderow != NULL);
|
||||||
/* XXX horizontal differencing alters user's data XXX */
|
/* XXX horizontal differencing alters user's data XXX */
|
||||||
(*sp->pfunc)(tif, bp, cc);
|
(*sp->pfunc)(tif, bp, cc);
|
||||||
return ((*sp->coderow)(tif, bp, cc, s));
|
return (*sp->coderow)(tif, bp, cc, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -370,7 +446,7 @@ PredictorEncodeTile(TIFF* tif, tidata_t bp0, tsize_t cc0, tsample_t s)
|
|||||||
cc -= rowsize;
|
cc -= rowsize;
|
||||||
bp += rowsize;
|
bp += rowsize;
|
||||||
}
|
}
|
||||||
return ((*sp->codetile)(tif, bp0, cc0, s));
|
return (*sp->codetile)(tif, bp0, cc0, s);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define FIELD_PREDICTOR (FIELD_CODEC+0) /* XXX */
|
#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);
|
return (*sp->vsetparent)(tif, tag, ap);
|
||||||
}
|
}
|
||||||
tif->tif_flags |= TIFF_DIRTYDIRECT;
|
tif->tif_flags |= TIFF_DIRTYDIRECT;
|
||||||
return (1);
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -410,7 +486,7 @@ PredictorVGetField(TIFF* tif, ttag_t tag, va_list ap)
|
|||||||
default:
|
default:
|
||||||
return (*sp->vgetparent)(tif, tag, ap);
|
return (*sp->vgetparent)(tif, tag, ap);
|
||||||
}
|
}
|
||||||
return (1);
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -424,6 +500,7 @@ PredictorPrintDir(TIFF* tif, FILE* fd, long flags)
|
|||||||
switch (sp->predictor) {
|
switch (sp->predictor) {
|
||||||
case 1: fprintf(fd, "none "); break;
|
case 1: fprintf(fd, "none "); break;
|
||||||
case 2: fprintf(fd, "horizontal differencing "); 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);
|
fprintf(fd, "%u (0x%x)\n", sp->predictor, sp->predictor);
|
||||||
}
|
}
|
||||||
@ -458,7 +535,7 @@ TIFFPredictorInit(TIFF* tif)
|
|||||||
|
|
||||||
sp->predictor = 1; /* default value */
|
sp->predictor = 1; /* default value */
|
||||||
sp->pfunc = NULL; /* no predictor routine */
|
sp->pfunc = NULL; /* no predictor routine */
|
||||||
return (1);
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* vim: set ts=8 sts=8 sw=8 noet: */
|
/* 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
|
* Copyright (c) 1995-1997 Sam Leffler
|
||||||
@ -36,9 +36,9 @@
|
|||||||
* the predictor code can cast tif_data to find its state.
|
* the predictor code can cast tif_data to find its state.
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int predictor; /* predictor tag value */
|
int predictor; /* predictor tag value */
|
||||||
int stride; /* sample stride over data */
|
int stride; /* sample stride over data */
|
||||||
tsize_t rowsize; /* tile/strip row size */
|
tsize_t rowsize; /* tile/strip row size */
|
||||||
|
|
||||||
TIFFPostMethod pfunc; /* horizontal differencer/accumulator */
|
TIFFPostMethod pfunc; /* horizontal differencer/accumulator */
|
||||||
TIFFCodeMethod coderow; /* parent codec encode/decode row */
|
TIFFCodeMethod coderow; /* parent codec encode/decode row */
|
||||||
@ -59,3 +59,5 @@ extern int TIFFPredictorInit(TIFF*);
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#endif /* _TIFFPREDICT_ */
|
#endif /* _TIFFPREDICT_ */
|
||||||
|
|
||||||
|
/* vim: set ts=8 sts=8 sw=8 noet: */
|
||||||
|
Loading…
Reference in New Issue
Block a user