From b7373037689c3aa6cd9b6ebb109f5a4654ad4e14 Mon Sep 17 00:00:00 2001 From: Andrey Kiselev Date: Thu, 14 Apr 2005 11:57:30 +0000 Subject: [PATCH] Added ability to decode floating point predictor, as per TIFF technical Note 3. --- libtiff/tif_predict.c | 157 +++++++++++++++++++++++++++++++----------- libtiff/tif_predict.h | 10 +-- 2 files changed, 123 insertions(+), 44 deletions(-) diff --git a/libtiff/tif_predict.c b/libtiff/tif_predict.c index 313bdf6d..72501a7b 100644 --- a/libtiff/tif_predict.c +++ b/libtiff/tif_predict.c @@ -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: */ diff --git a/libtiff/tif_predict.h b/libtiff/tif_predict.h index c4789bc4..da8ec00e 100644 --- a/libtiff/tif_predict.h +++ b/libtiff/tif_predict.h @@ -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: */