Added support for averaging resampling

This commit is contained in:
Frank Warmerdam 2000-04-18 22:48:31 +00:00
parent 859c2524f6
commit 557efe0f3c
2 changed files with 211 additions and 36 deletions

View File

@ -1,5 +1,5 @@
/****************************************************************************** /******************************************************************************
* $Id: addtiffo.c,v 1.2 2000-01-28 15:36:38 warmerda Exp $ * $Id: addtiffo.c,v 1.3 2000-04-18 22:48:31 warmerda Exp $
* *
* Project: GeoTIFF Overview Builder * Project: GeoTIFF Overview Builder
* Purpose: Mainline for building overviews in a TIFF file. * Purpose: Mainline for building overviews in a TIFF file.
@ -28,7 +28,10 @@
****************************************************************************** ******************************************************************************
* *
* $Log: addtiffo.c,v $ * $Log: addtiffo.c,v $
* Revision 1.2 2000-01-28 15:36:38 warmerda * Revision 1.3 2000-04-18 22:48:31 warmerda
* Added support for averaging resampling
*
* Revision 1.2 2000/01/28 15:36:38 warmerda
* pass TIFF handle instead of filename to overview builder * pass TIFF handle instead of filename to overview builder
* *
* Revision 1.1 1999/08/17 01:47:59 warmerda * Revision 1.1 1999/08/17 01:47:59 warmerda
@ -48,7 +51,8 @@
#include <stdlib.h> #include <stdlib.h>
#include "tiffio.h" #include "tiffio.h"
void TIFFBuildOverviews( TIFF *, int, int *, int ); void TIFFBuildOverviews( TIFF *, int, int *, int, const char *,
int (*)(double,void*), void * );
/************************************************************************/ /************************************************************************/
/* main() */ /* main() */
@ -61,23 +65,35 @@ int main( int argc, char ** argv )
int nOverviewCount = 0; int nOverviewCount = 0;
int bUseSubIFD = 0; int bUseSubIFD = 0;
TIFF *hTIFF; TIFF *hTIFF;
const char *pszResampling = "nearest";
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
/* Usage: */ /* Usage: */
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
if( argc < 2 ) if( argc < 2 )
{ {
printf( "Usage: addtiffo tiff_filename [resolution_reductions]\n" ); printf( "Usage: addtiffo [-r {nearest,average,mode}]\n"
printf( "\n" ); " tiff_filename [resolution_reductions]\n"
printf( "Example:\n" ); "\n"
printf( " %% addtifo abc.tif 2 4 8 16\n" ); "Example:\n"
" %% addtifo abc.tif 2 4 8 16\n" );
exit( 1 ); exit( 1 );
} }
if( strcmp(argv[1],"-subifd") == 0 ) while( argv[1][0] == '-' )
{ {
bUseSubIFD = 1; if( strcmp(argv[1],"-subifd") == 0 )
argv++; {
bUseSubIFD = 1;
argv++;
argc--;
}
else if( strcmp(argv[1],"-r") == 0 )
{
argv += 2;
argc -= 2;
pszResampling = *argv;
}
} }
/* -------------------------------------------------------------------- */ /* -------------------------------------------------------------------- */
@ -113,7 +129,8 @@ int main( int argc, char ** argv )
exit( 1 ); exit( 1 );
} }
TIFFBuildOverviews( hTIFF, nOverviewCount, anOverviews, bUseSubIFD ); TIFFBuildOverviews( hTIFF, nOverviewCount, anOverviews, bUseSubIFD,
pszResampling, NULL, NULL );
TIFFClose( hTIFF ); TIFFClose( hTIFF );

View File

@ -1,5 +1,5 @@
/****************************************************************************** /******************************************************************************
* $Id: tif_overview.c,v 1.2 2000-01-28 15:36:38 warmerda Exp $ * $Id: tif_overview.c,v 1.3 2000-04-18 22:48:31 warmerda Exp $
* *
* Project: TIFF Overview Builder * Project: TIFF Overview Builder
* Purpose: Library function for building overviews in a TIFF file. * Purpose: Library function for building overviews in a TIFF file.
@ -45,7 +45,10 @@
****************************************************************************** ******************************************************************************
* *
* $Log: tif_overview.c,v $ * $Log: tif_overview.c,v $
* Revision 1.2 2000-01-28 15:36:38 warmerda * Revision 1.3 2000-04-18 22:48:31 warmerda
* Added support for averaging resampling
*
* Revision 1.2 2000/01/28 15:36:38 warmerda
* pass TIFF handle instead of filename to overview builder * pass TIFF handle instead of filename to overview builder
* *
* Revision 1.1 2000/01/28 15:04:03 warmerda * Revision 1.1 2000/01/28 15:04:03 warmerda
@ -71,7 +74,8 @@
# define MAX(a,b) ((a>b) ? a : b) # define MAX(a,b) ((a>b) ? a : b)
#endif #endif
void TIFFBuildOverviews( TIFF *, int, int *, int ); void TIFFBuildOverviews( TIFF *, int, int *, int, const char *,
int (*)(double,void*), void * );
/************************************************************************/ /************************************************************************/
/* TIFF_WriteOverview() */ /* TIFF_WriteOverview() */
@ -149,6 +153,99 @@ uint32 TIFF_WriteOverview( TIFF *hTIFF, int nXSize, int nYSize,
return nOffset; return nOffset;
} }
/************************************************************************/
/* TIFF_GetSourceSamples() */
/************************************************************************/
static void
TIFF_GetSourceSamples( double * padfSamples, unsigned char *pabySrc,
int nPixelBytes, int nSampleFormat,
int nXSize, int nYSize,
int nPixelOffset, int nLineOffset )
{
int iXOff, iYOff, iSample;
iSample = 0;
for( iYOff = 0; iYOff < nYSize; iYOff++ )
{
for( iXOff = 0; iXOff < nXSize; iXOff++ )
{
unsigned char *pabyData;
pabyData = pabySrc + iYOff * nLineOffset + iXOff * nPixelOffset;
if( nSampleFormat == SAMPLEFORMAT_UINT && nPixelBytes == 1 )
{
padfSamples[iSample++] = *pabyData;
}
else if( nSampleFormat == SAMPLEFORMAT_UINT && nPixelBytes == 2 )
{
padfSamples[iSample++] = ((uint16 *) pabyData)[0];
}
else if( nSampleFormat == SAMPLEFORMAT_UINT && nPixelBytes == 4 )
{
padfSamples[iSample++] = ((uint32 *) pabyData)[0];
}
else if( nSampleFormat == SAMPLEFORMAT_INT && nPixelBytes == 2 )
{
padfSamples[iSample++] = ((int16 *) pabyData)[0];
}
else if( nSampleFormat == SAMPLEFORMAT_INT && nPixelBytes == 32 )
{
padfSamples[iSample++] = ((int32 *) pabyData)[0];
}
else if( nSampleFormat == SAMPLEFORMAT_IEEEFP && nPixelBytes == 4 )
{
padfSamples[iSample++] = ((float *) pabyData)[0];
}
else if( nSampleFormat == SAMPLEFORMAT_IEEEFP && nPixelBytes == 8 )
{
padfSamples[iSample++] = ((double *) pabyData)[0];
}
}
}
}
/************************************************************************/
/* TIFF_SetSample() */
/************************************************************************/
static void
TIFF_SetSample( unsigned char * pabyData, int nPixelBytes, int nSampleFormat,
double dfValue )
{
if( nSampleFormat == SAMPLEFORMAT_UINT && nPixelBytes == 1 )
{
*pabyData = (unsigned char) MAX(0,MIN(255,dfValue));
}
else if( nSampleFormat == SAMPLEFORMAT_UINT && nPixelBytes == 2 )
{
*((uint16 *)pabyData) = (uint16) MAX(0,MIN(65535,dfValue));
}
else if( nSampleFormat == SAMPLEFORMAT_UINT && nPixelBytes == 4 )
{
*((uint32 *)pabyData) = (uint32) dfValue;
}
else if( nSampleFormat == SAMPLEFORMAT_INT && nPixelBytes == 2 )
{
*((int16 *)pabyData) = (int16) MAX(-32768,MIN(32767,dfValue));
}
else if( nSampleFormat == SAMPLEFORMAT_INT && nPixelBytes == 32 )
{
*((int32 *)pabyData) = (int32) dfValue;
}
else if( nSampleFormat == SAMPLEFORMAT_IEEEFP && nPixelBytes == 4 )
{
*((float *)pabyData) = (float) dfValue;
}
else if( nSampleFormat == SAMPLEFORMAT_IEEEFP && nPixelBytes == 8 )
{
*((double *)pabyData) = dfValue;
}
}
/************************************************************************/ /************************************************************************/
/* TIFF_DownSample() */ /* TIFF_DownSample() */
/* */ /* */
@ -162,45 +259,102 @@ void TIFF_DownSample( unsigned char *pabySrcTile,
int nPixelSkewBits, int nBitsPerPixel, int nPixelSkewBits, int nBitsPerPixel,
unsigned char * pabyOTile, unsigned char * pabyOTile,
int nOBlockXSize, int nOBlockYSize, int nOBlockXSize, int nOBlockYSize,
int nTXOff, int nTYOff, int nOMult ) int nTXOff, int nTYOff, int nOMult,
int nSampleFormat, const char * pszResampling )
{ {
int i, j, k, nPixelBytes = (nBitsPerPixel) / 8; int i, j, k, nPixelBytes = (nBitsPerPixel) / 8;
int nPixelGroupBytes = (nBitsPerPixel+nPixelSkewBits)/8; int nPixelGroupBytes = (nBitsPerPixel+nPixelSkewBits)/8;
unsigned char *pabySrc, *pabyDst; unsigned char *pabySrc, *pabyDst;
double *padfSamples;
assert( nBitsPerPixel >= 8 ); assert( nBitsPerPixel >= 8 );
/* -------------------------------------------------------------------- */ padfSamples = (double *) malloc(sizeof(double) * nOMult * nOMult);
/* Handle case of one or more whole bytes per sample. */
/* -------------------------------------------------------------------- */ /* ==================================================================== */
/* Loop over scanline chunks to process, establishing where the */
/* data is going. */
/* ==================================================================== */
for( j = 0; j*nOMult < nBlockYSize; j++ ) for( j = 0; j*nOMult < nBlockYSize; j++ )
{ {
if( j + nTYOff >= nOBlockYSize ) if( j + nTYOff >= nOBlockYSize )
break; break;
pabySrc = pabySrcTile + j*nOMult*nBlockXSize * nPixelGroupBytes;
pabyDst = pabyOTile pabyDst = pabyOTile
+ ((j+nTYOff)*nOBlockXSize + nTXOff) * nPixelBytes; + ((j+nTYOff)*nOBlockXSize + nTXOff) * nPixelBytes;
for( i = 0; i*nOMult < nBlockXSize; i++ ) /* -------------------------------------------------------------------- */
/* Handler nearest resampling ... we don't even care about the */
/* data type, we just do a bytewise copy. */
/* -------------------------------------------------------------------- */
if( strncmp(pszResampling,"nearest",4) == 0
|| strncmp(pszResampling,"NEAR",4) == 0 )
{ {
if( i + nTXOff >= nOBlockXSize ) pabySrc = pabySrcTile + j*nOMult*nBlockXSize * nPixelGroupBytes;
break;
/*
* For now use simple subsampling, from the top left corner
* of the source block of pixels.
*/
for( k = 0; k < nPixelBytes; k++ ) for( i = 0; i*nOMult < nBlockXSize; i++ )
{ {
*(pabyDst++) = pabySrc[k]; if( i + nTXOff >= nOBlockXSize )
} break;
pabySrc += nOMult * nPixelGroupBytes; /*
* For now use simple subsampling, from the top left corner
* of the source block of pixels.
*/
for( k = 0; k < nPixelBytes; k++ )
{
*(pabyDst++) = pabySrc[k];
}
pabySrc += nOMult * nPixelGroupBytes;
}
}
/* -------------------------------------------------------------------- */
/* Handle the case of averaging. For this we also have to */
/* handle each sample format we are concerned with. */
/* -------------------------------------------------------------------- */
else if( strncmp(pszResampling,"averag",6) == 0
|| strncmp(pszResampling,"AVERAG",6) == 0 )
{
pabySrc = pabySrcTile + j*nOMult*nBlockXSize * nPixelGroupBytes;
for( i = 0; i*nOMult < nBlockXSize; i++ )
{
double dfTotal;
int iSample;
int nXSize, nYSize;
if( i + nTXOff >= nOBlockXSize )
break;
nXSize = MIN(nOMult,nBlockXSize-i);
nYSize = MIN(nOMult,nBlockYSize-j);
TIFF_GetSourceSamples( padfSamples, pabySrc,
nPixelBytes, nSampleFormat,
nXSize, nYSize,
nPixelGroupBytes,
nPixelGroupBytes * nBlockXSize );
dfTotal = 0;
for( iSample = 0; iSample < nXSize*nYSize; iSample++ )
{
dfTotal += padfSamples[iSample];
}
TIFF_SetSample( pabyDst, nPixelBytes, nSampleFormat,
dfTotal / (nXSize*nYSize) );
pabySrc += nOMult * nPixelGroupBytes;
pabyDst += nPixelBytes;
}
} }
} }
free( padfSamples );
} }
/************************************************************************/ /************************************************************************/
@ -216,8 +370,9 @@ void TIFF_ProcessFullResBlock( TIFF *hTIFF, int nPlanarConfig,
int nSamples, TIFFOvrCache ** papoRawBIs, int nSamples, TIFFOvrCache ** papoRawBIs,
int nSXOff, int nSYOff, int nSXOff, int nSYOff,
unsigned char *pabySrcTile, unsigned char *pabySrcTile,
int nBlockXSize, int nBlockYSize ) int nBlockXSize, int nBlockYSize,
int nSampleFormat, const char * pszResampling )
{ {
int iOverview, iSample; int iOverview, iSample;
@ -301,7 +456,7 @@ void TIFF_ProcessFullResBlock( TIFF *hTIFF, int nPlanarConfig,
nSkewBits, nBitsPerPixel, pabyOTile, nSkewBits, nBitsPerPixel, pabyOTile,
poRBI->nBlockXSize, poRBI->nBlockYSize, poRBI->nBlockXSize, poRBI->nBlockYSize,
nTXOff, nTYOff, nTXOff, nTYOff,
nOMult ); nOMult, nSampleFormat, pszResampling );
#ifdef DBMALLOC #ifdef DBMALLOC
malloc_chain_check( 1 ); malloc_chain_check( 1 );
#endif #endif
@ -320,7 +475,9 @@ void TIFF_ProcessFullResBlock( TIFF *hTIFF, int nPlanarConfig,
/************************************************************************/ /************************************************************************/
void TIFFBuildOverviews( TIFF *hTIFF, int nOverviews, int * panOvList, void TIFFBuildOverviews( TIFF *hTIFF, int nOverviews, int * panOvList,
int bUseSubIFDs ) int bUseSubIFDs, const char *pszResampleMethod,
int (*pfnProgress)( double, void * ),
void * pProgressData )
{ {
TIFFOvrCache **papoRawBIs; TIFFOvrCache **papoRawBIs;
@ -468,7 +625,8 @@ void TIFFBuildOverviews( TIFF *hTIFF, int nOverviews, int * panOvList,
nOverviews, panOvList, nOverviews, panOvList,
nBitsPerPixel, nSamples, papoRawBIs, nBitsPerPixel, nSamples, papoRawBIs,
nSXOff, nSYOff, pabySrcTile, nSXOff, nSYOff, pabySrcTile,
nBlockXSize, nBlockYSize ); nBlockXSize, nBlockYSize,
nSampleFormat, pszResampleMethod );
} }
} }