summaryrefslogtreecommitdiff
path: root/contrib
diff options
context:
space:
mode:
authorfwarmerdam <fwarmerdam>2005-12-16 05:59:55 +0000
committerfwarmerdam <fwarmerdam>2005-12-16 05:59:55 +0000
commit9c901e868dc41d2130c16138bc84797960d4dbe9 (patch)
treeb8407637277f7e751830c4422bdff1581913985d /contrib
parentaaf4b1abd65dc65f6901a43bb5977daaacf741dc (diff)
downloadlibtiff-9c901e868dc41d2130c16138bc84797960d4dbe9.tar.gz
Major upgrade to support YCbCr subsampled jpeg images
Diffstat (limited to 'contrib')
-rw-r--r--contrib/addtiffo/addtiffo.c31
-rw-r--r--contrib/addtiffo/tif_overview.c362
-rw-r--r--contrib/addtiffo/tif_ovrcache.c46
-rw-r--r--contrib/addtiffo/tif_ovrcache.h12
4 files changed, 374 insertions, 77 deletions
diff --git a/contrib/addtiffo/addtiffo.c b/contrib/addtiffo/addtiffo.c
index 72f364fd..d36d62a6 100644
--- a/contrib/addtiffo/addtiffo.c
+++ b/contrib/addtiffo/addtiffo.c
@@ -1,9 +1,9 @@
/******************************************************************************
- * $Id: addtiffo.c,v 1.5 2005-12-13 15:18:11 joris Exp $
+ * $Id: addtiffo.c,v 1.6 2005-12-16 05:59:55 fwarmerdam Exp $
*
* Project: GeoTIFF Overview Builder
* Purpose: Mainline for building overviews in a TIFF file.
- * Author: Frank Warmerdam, warmerda@home.com
+ * Author: Frank Warmerdam, warmerdam@pobox.com
*
******************************************************************************
* Copyright (c) 1999, Frank Warmerdam
@@ -28,8 +28,8 @@
******************************************************************************
*
* $Log: addtiffo.c,v $
- * Revision 1.5 2005-12-13 15:18:11 joris
- * Some minor nitpicking
+ * Revision 1.6 2005-12-16 05:59:55 fwarmerdam
+ * Major upgrade to support YCbCr subsampled jpeg images
*
* Revision 1.4 2004/09/21 13:31:23 dron
* Add missed include string.h.
@@ -68,7 +68,7 @@ void TIFFBuildOverviews( TIFF *, int, int *, int, const char *,
int main( int argc, char ** argv )
{
- int anOverviews[100];
+ int anOverviews[100]; /* TODO: un-hardwire array length, flexible allocate */
int nOverviewCount = 0;
int bUseSubIFD = 0;
TIFF *hTIFF;
@@ -84,7 +84,7 @@ int main( int argc, char ** argv )
"\n"
"Example:\n"
" %% addtiffo abc.tif 2 4 8 16\n" );
- exit( 1 );
+ return( 1 );
}
while( argv[1][0] == '-' )
@@ -104,20 +104,22 @@ int main( int argc, char ** argv )
else
{
fprintf( stderr, "Incorrect parameters\n" );
- exit( 1 );
+ return( 1 );
}
}
+ /* TODO: resampling mode parameter needs to be encoded in an integer from this point on */
+
/* -------------------------------------------------------------------- */
/* Collect the user requested reduction factors. */
/* -------------------------------------------------------------------- */
- while( ( nOverviewCount < argc - 2 ) && ( nOverviewCount < 100 ) )
+ while( nOverviewCount < argc - 2 && nOverviewCount < 100 )
{
anOverviews[nOverviewCount] = atoi(argv[nOverviewCount+2]);
if( anOverviews[nOverviewCount] <= 0)
{
fprintf( stderr, "Incorrect parameters\n" );
- exit( 1 );
+ return(1);
}
nOverviewCount++;
}
@@ -126,10 +128,11 @@ int main( int argc, char ** argv )
/* Default to four overview levels. It would be nicer if it */
/* defaulted based on the size of the source image. */
/* -------------------------------------------------------------------- */
+ /* TODO: make it default based on the size of the source image */
if( nOverviewCount == 0 )
{
nOverviewCount = 4;
-
+
anOverviews[0] = 2;
anOverviews[1] = 4;
anOverviews[2] = 8;
@@ -143,20 +146,20 @@ int main( int argc, char ** argv )
if( hTIFF == NULL )
{
fprintf( stderr, "TIFFOpen(%s) failed.\n", argv[1] );
- exit( 1 );
+ return( 1 );
}
TIFFBuildOverviews( hTIFF, nOverviewCount, anOverviews, bUseSubIFD,
pszResampling, NULL, NULL );
TIFFClose( hTIFF );
-
+
/* -------------------------------------------------------------------- */
/* Optionally test for memory leaks. */
/* -------------------------------------------------------------------- */
#ifdef DBMALLOC
malloc_dump(1);
#endif
-
- exit( 0 );
+
+ return( 0 );
}
diff --git a/contrib/addtiffo/tif_overview.c b/contrib/addtiffo/tif_overview.c
index 1423d875..b8c2c9f6 100644
--- a/contrib/addtiffo/tif_overview.c
+++ b/contrib/addtiffo/tif_overview.c
@@ -45,6 +45,8 @@
******************************************************************************
*/
+/* TODO: update notes in header above */
+
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
@@ -83,7 +85,8 @@ uint32 TIFF_WriteOverview( TIFF *hTIFF, int nXSize, int nYSize,
unsigned short *panRed,
unsigned short *panGreen,
unsigned short *panBlue,
- int bUseSubIFDs )
+ int bUseSubIFDs,
+ int nHorSubsampling, int nVerSubsampling )
{
uint32 nBaseDirOffset;
@@ -92,7 +95,7 @@ uint32 TIFF_WriteOverview( TIFF *hTIFF, int nXSize, int nYSize,
nBaseDirOffset = TIFFCurrentDirOffset( hTIFF );
TIFFCreateDirectory( hTIFF );
-
+
/* -------------------------------------------------------------------- */
/* Setup TIFF fields. */
/* -------------------------------------------------------------------- */
@@ -118,7 +121,15 @@ uint32 TIFF_WriteOverview( TIFF *hTIFF, int nXSize, int nYSize,
TIFFSetField( hTIFF, TIFFTAG_ROWSPERSTRIP, nBlockYSize );
TIFFSetField( hTIFF, TIFFTAG_SUBFILETYPE, FILETYPE_REDUCEDIMAGE );
-
+
+ if( nPhotometric == PHOTOMETRIC_YCBCR || nPhotometric == PHOTOMETRIC_ITULAB )
+ {
+ TIFFSetField( hTIFF, TIFFTAG_YCBCRSUBSAMPLING, nHorSubsampling, nVerSubsampling);
+ /* TODO: also write YCbCrPositioning and YCbCrCoefficients tag identical to source IFD */
+ }
+ /* TODO: add command-line parameter for selecting jpeg compression quality
+ * that gets ignored when compression isn't jpeg */
+
/* -------------------------------------------------------------------- */
/* Write color table if one is present. */
/* -------------------------------------------------------------------- */
@@ -270,7 +281,7 @@ void TIFF_DownSample( unsigned char *pabySrcTile,
{
if( j + nTYOff >= nOBlockYSize )
break;
-
+
pabyDst = pabyOTile + ((j+nTYOff)*nOBlockXSize + nTXOff)
* nPixelBytes * nPixelGroupBytes;
@@ -305,7 +316,7 @@ void TIFF_DownSample( unsigned char *pabySrcTile,
/* 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
+ else if( strncmp(pszResampling,"averag",6) == 0
|| strncmp(pszResampling,"AVERAG",6) == 0 )
{
pabySrc = pabySrcTile + j*nOMult*nBlockXSize * nPixelGroupBytes;
@@ -322,12 +333,12 @@ void TIFF_DownSample( unsigned char *pabySrcTile,
nXSize = MIN(nOMult,nBlockXSize-i);
nYSize = MIN(nOMult,nBlockYSize-j);
- TIFF_GetSourceSamples( padfSamples, pabySrc,
- nPixelBytes, nSampleFormat,
- nXSize, nYSize,
- nPixelGroupBytes,
+ TIFF_GetSourceSamples( padfSamples, pabySrc,
+ nPixelBytes, nSampleFormat,
+ nXSize, nYSize,
+ nPixelGroupBytes,
nPixelGroupBytes * nBlockXSize );
-
+
dfTotal = 0;
for( iSample = 0; iSample < nXSize*nYSize; iSample++ )
{
@@ -346,6 +357,187 @@ void TIFF_DownSample( unsigned char *pabySrcTile,
free( padfSamples );
}
+static
+void TIFF_DownSample_Subsampled( unsigned char *pabySrcTile, int nSample,
+ int nBlockXSize, int nBlockYSize,
+ unsigned char * pabyOTile,
+ int nOBlockXSize, int nOBlockYSize,
+ int nTXOff, int nTYOff, int nOMult,
+ const char * pszResampling,
+ int nHorSubsampling, int nVerSubsampling )
+{
+ /* TODO: test with variety of subsampling values, and incovinient tile/strip sizes */
+ int nSampleBlockSize;
+ int nSourceSampleRowSize;
+ int nDestSampleRowSize;
+ int nSourceX, nSourceY;
+ int nSourceXSec, nSourceYSec;
+ int nSourceXSecEnd, nSourceYSecEnd;
+ int nDestX, nDestY;
+ int nSampleOffsetInSampleBlock;
+ unsigned char * pSourceBase;
+ unsigned char * pDestBase;
+ int nSourceBaseInc;
+ unsigned char * pSourceBaseEnd;
+ unsigned int nCummulator;
+ unsigned int nCummulatorCount;
+
+ nSampleBlockSize = nHorSubsampling * nVerSubsampling + 2;
+ nSourceSampleRowSize = ( ( nBlockXSize + nHorSubsampling - 1 ) / nHorSubsampling ) * nSampleBlockSize;
+ nDestSampleRowSize = ( ( nOBlockXSize + nHorSubsampling - 1 ) / nHorSubsampling ) * nSampleBlockSize;
+
+ if( strncmp(pszResampling,"nearest",4) == 0
+ || strncmp(pszResampling,"NEAR",4) == 0 )
+ {
+ if( nSample == 0 )
+ {
+#ifdef NOOPTIMIZATION
+ /*
+ * This version is not optimized, and should not be used except as documentation and as more clear
+ * starting point for bug fixes (hope not) and extension
+ */
+ for( nSourceY = 0, nDestY = nTYOff; nSourceY < nBlockYSize; nSourceY += nOMult, nDestY ++)
+ {
+ for( nSourceX = 0, nDestX = nTXOff; nSourceX < nBlockXSize; nSourceX += nOMult, nDestX ++)
+ {
+ * ( pabyOTile + ( nDestY / nVerSubsampling ) * nDestSampleRowSize
+ + ( nDestY % nVerSubsampling ) * nHorSubsampling
+ + ( nDestX / nHorSubsampling ) * nSampleBlockSize
+ + ( nDestX % nHorSubsampling ) ) =
+ * ( pabySrcTile + ( nSourceY / nVerSubsampling ) * nSourceSampleRowSize
+ + ( nSourceY % nVerSubsampling ) * nHorSubsampling
+ + ( nSourceX / nHorSubsampling ) * nSampleBlockSize
+ + ( nSourceX % nHorSubsampling ) );
+ }
+ }
+#else
+ for( nSourceY = 0, nDestY = nTYOff; nSourceY < nBlockYSize; nSourceY += nOMult, nDestY ++)
+ {
+ pSourceBase = pabySrcTile + ( nSourceY / nVerSubsampling ) * nSourceSampleRowSize
+ + ( nSourceY % nVerSubsampling ) * nHorSubsampling;
+ pDestBase = pabyOTile + ( nDestY / nVerSubsampling ) * nDestSampleRowSize
+ + ( nDestY % nVerSubsampling ) * nHorSubsampling;
+ for( nSourceX = 0, nDestX = nTXOff; nSourceX < nBlockXSize; nSourceX += nOMult, nDestX ++)
+ {
+ * ( pDestBase + ( nDestX / nHorSubsampling ) * nSampleBlockSize
+ + ( nDestX % nHorSubsampling ) ) =
+ * ( pSourceBase + ( nSourceX / nHorSubsampling ) * nSampleBlockSize
+ + ( nSourceX % nHorSubsampling ) );
+ }
+ }
+#endif
+ }
+ else
+ {
+#ifdef NOOPTIMIZATION
+ /*
+ * This version is not optimized, and should not be used except as documentation and as more clear
+ * starting point for bug fixes (hope not) and extension
+ */
+ nSampleOffsetInSampleBlock = nHorSubsampling * nVerSubsampling + nSample - 1;
+ for( nSourceY = 0, nDestY = ( nTYOff / nVerSubsampling ); nSourceY < ( nBlockYSize / nVerSubsampling );
+ nSourceY += nOMult, nDestY ++)
+ {
+ for( nSourceX = 0, nDestX = ( nTXOff / nHorSubsampling ); nSourceX < ( nBlockXSize / nHorSubsampling );
+ nSourceX += nOMult, nDestX ++)
+ {
+ * ( pabyOTile + nDestY * nDestSampleRowSize
+ + nDestX * nSampleBlockSize
+ + nSampleOffsetInSampleBlock ) =
+ * ( pabySrcTile + nSourceY * nSourceSampleRowSize
+ + nSourceX * nSampleBlockSize
+ + nSampleOffsetInSampleBlock );
+ }
+ }
+#else
+ nSampleOffsetInSampleBlock = nHorSubsampling * nVerSubsampling + nSample - 1;
+ nSourceBaseInc = nOMult * nSampleBlockSize;
+ for( nSourceY = 0, nDestY = ( nTYOff / nVerSubsampling ); nSourceY < ( nBlockYSize / nVerSubsampling);
+ nSourceY += nOMult, nDestY ++)
+ {
+ pSourceBase = pabySrcTile + nSourceY * nSourceSampleRowSize
+ + nSampleOffsetInSampleBlock;
+ pSourceBaseEnd = pSourceBase + ( ( ( nBlockXSize / nHorSubsampling ) + nOMult - 1 ) / nOMult ) * nSourceBaseInc;
+ pDestBase = pabyOTile + nDestY * nDestSampleRowSize
+ + ( nTXOff / nHorSubsampling ) * nSampleBlockSize
+ + nSampleOffsetInSampleBlock;
+ for( ; pSourceBase < pSourceBaseEnd; pSourceBase += nSourceBaseInc, pDestBase += nSampleBlockSize)
+ * pDestBase = * pSourceBase;
+ }
+#endif
+ }
+ }
+ else if( strncmp(pszResampling,"averag",6) == 0
+ || strncmp(pszResampling,"AVERAG",6) == 0 )
+ {
+ if( nSample == 0 )
+ {
+ for( nSourceY = 0, nDestY = nTYOff; nSourceY < nBlockYSize; nSourceY += nOMult, nDestY ++)
+ {
+ for( nSourceX = 0, nDestX = nTXOff; nSourceX < nBlockXSize; nSourceX += nOMult, nDestX ++)
+ {
+ nSourceXSecEnd = nSourceX + nOMult;
+ if( nSourceXSecEnd > nBlockXSize )
+ nSourceXSecEnd = nBlockXSize;
+ nSourceYSecEnd = nSourceY + nOMult;
+ if( nSourceYSecEnd > nBlockYSize )
+ nSourceYSecEnd = nBlockYSize;
+ nCummulator = 0;
+ for( nSourceYSec = nSourceY; nSourceYSec < nSourceYSecEnd; nSourceYSec ++)
+ {
+ for( nSourceXSec = nSourceX; nSourceXSec < nSourceXSecEnd; nSourceXSec ++)
+ {
+ nCummulator += * ( pabySrcTile + ( nSourceYSec / nVerSubsampling ) * nSourceSampleRowSize
+ + ( nSourceYSec % nVerSubsampling ) * nHorSubsampling
+ + ( nSourceXSec / nHorSubsampling ) * nSampleBlockSize
+ + ( nSourceXSec % nHorSubsampling ) );
+ }
+ }
+ nCummulatorCount = ( nSourceXSecEnd - nSourceX ) * ( nSourceYSecEnd - nSourceY );
+ * ( pabyOTile + ( nDestY / nVerSubsampling ) * nDestSampleRowSize
+ + ( nDestY % nVerSubsampling ) * nHorSubsampling
+ + ( nDestX / nHorSubsampling ) * nSampleBlockSize
+ + ( nDestX % nHorSubsampling ) ) =
+ ( ( nCummulator + ( nCummulatorCount >> 1 ) ) / nCummulatorCount );
+ }
+ }
+ }
+ else
+ {
+ nSampleOffsetInSampleBlock = nHorSubsampling * nVerSubsampling + nSample - 1;
+ for( nSourceY = 0, nDestY = ( nTYOff / nVerSubsampling ); nSourceY < ( nBlockYSize / nVerSubsampling );
+ nSourceY += nOMult, nDestY ++)
+ {
+ for( nSourceX = 0, nDestX = ( nTXOff / nHorSubsampling ); nSourceX < ( nBlockXSize / nHorSubsampling );
+ nSourceX += nOMult, nDestX ++)
+ {
+ nSourceXSecEnd = nSourceX + nOMult;
+ if( nSourceXSecEnd > ( nBlockXSize / nHorSubsampling ) )
+ nSourceXSecEnd = ( nBlockXSize / nHorSubsampling );
+ nSourceYSecEnd = nSourceY + nOMult;
+ if( nSourceYSecEnd > ( nBlockYSize / nVerSubsampling ) )
+ nSourceYSecEnd = ( nBlockYSize / nVerSubsampling );
+ nCummulator = 0;
+ for( nSourceYSec = nSourceY; nSourceYSec < nSourceYSecEnd; nSourceYSec ++)
+ {
+ for( nSourceXSec = nSourceX; nSourceXSec < nSourceXSecEnd; nSourceXSec ++)
+ {
+ nCummulator += * ( pabySrcTile + nSourceYSec * nSourceSampleRowSize
+ + nSourceXSec * nSampleBlockSize
+ + nSampleOffsetInSampleBlock );
+ }
+ }
+ nCummulatorCount = ( nSourceXSecEnd - nSourceX ) * ( nSourceYSecEnd - nSourceY );
+ * ( pabyOTile + nDestY * nDestSampleRowSize
+ + nDestX * nSampleBlockSize
+ + nSampleOffsetInSampleBlock ) =
+ ( ( nCummulator + ( nCummulatorCount >> 1 ) ) / nCummulatorCount );
+ }
+ }
+ }
+ }
+}
+
/************************************************************************/
/* TIFF_ProcessFullResBlock() */
/* */
@@ -354,8 +546,9 @@ void TIFF_DownSample( unsigned char *pabySrcTile,
/************************************************************************/
void TIFF_ProcessFullResBlock( TIFF *hTIFF, int nPlanarConfig,
+ int bSubsampled, int nHorSubsampling, int nVerSubsampling,
int nOverviews, int * panOvList,
- int nBitsPerPixel,
+ int nBitsPerPixel,
int nSamples, TIFFOvrCache ** papoRawBIs,
int nSXOff, int nSYOff,
unsigned char *pabySrcTile,
@@ -410,46 +603,78 @@ void TIFF_ProcessFullResBlock( TIFF *hTIFF, int nPlanarConfig,
nOMult = panOvList[iOverview];
nOXOff = (nSXOff/nOMult) / nOBlockXSize;
nOYOff = (nSYOff/nOMult) / nOBlockYSize;
- pabyOTile = TIFFGetOvrBlock( poRBI, nOXOff, nOYOff, iSample );
-
- /*
- * Establish the offset into this tile at which we should
- * start placing data.
- */
- nTXOff = (nSXOff - nOXOff*nOMult*nOBlockXSize) / nOMult;
- nTYOff = (nSYOff - nOYOff*nOMult*nOBlockYSize) / nOMult;
- /*
- * Figure out the skew (extra space between ``our samples'') and
- * the byte offset to the first sample.
- */
- assert( (nBitsPerPixel % 8) == 0 );
- if( nPlanarConfig == PLANARCONFIG_SEPARATE )
+ if( bSubsampled )
{
- nSkewBits = 0;
- nSampleByteOffset = 0;
+ pabyOTile = TIFFGetOvrBlock_Subsampled( poRBI, nOXOff, nOYOff );
+
+ /*
+ * Establish the offset into this tile at which we should
+ * start placing data.
+ */
+ nTXOff = (nSXOff - nOXOff*nOMult*nOBlockXSize) / nOMult;
+ nTYOff = (nSYOff - nOYOff*nOMult*nOBlockYSize) / nOMult;
+
+
+#ifdef DBMALLOC
+ malloc_chain_check( 1 );
+#endif
+ TIFF_DownSample_Subsampled( pabySrcTile, iSample,
+ nBlockXSize, nBlockYSize,
+ pabyOTile,
+ poRBI->nBlockXSize, poRBI->nBlockYSize,
+ nTXOff, nTYOff,
+ nOMult, pszResampling,
+ nHorSubsampling, nVerSubsampling );
+#ifdef DBMALLOC
+ malloc_chain_check( 1 );
+#endif
+
}
else
{
- nSkewBits = nBitsPerPixel * (nSamples-1);
- nSampleByteOffset = (nBitsPerPixel/8) * iSample;
- }
-
- /*
- * Perform the downsampling.
- */
+
+ pabyOTile = TIFFGetOvrBlock( poRBI, nOXOff, nOYOff, iSample );
+
+ /*
+ * Establish the offset into this tile at which we should
+ * start placing data.
+ */
+ nTXOff = (nSXOff - nOXOff*nOMult*nOBlockXSize) / nOMult;
+ nTYOff = (nSYOff - nOYOff*nOMult*nOBlockYSize) / nOMult;
+
+ /*
+ * Figure out the skew (extra space between ``our samples'') and
+ * the byte offset to the first sample.
+ */
+ assert( (nBitsPerPixel % 8) == 0 );
+ if( nPlanarConfig == PLANARCONFIG_SEPARATE )
+ {
+ nSkewBits = 0;
+ nSampleByteOffset = 0;
+ }
+ else
+ {
+ nSkewBits = nBitsPerPixel * (nSamples-1);
+ nSampleByteOffset = (nBitsPerPixel/8) * iSample;
+ }
+
+ /*
+ * Perform the downsampling.
+ */
#ifdef DBMALLOC
- malloc_chain_check( 1 );
+ malloc_chain_check( 1 );
#endif
- TIFF_DownSample( pabySrcTile + nSampleByteOffset,
- nBlockXSize, nBlockYSize,
- nSkewBits, nBitsPerPixel, pabyOTile,
- poRBI->nBlockXSize, poRBI->nBlockYSize,
- nTXOff, nTYOff,
- nOMult, nSampleFormat, pszResampling );
+ TIFF_DownSample( pabySrcTile + nSampleByteOffset,
+ nBlockXSize, nBlockYSize,
+ nSkewBits, nBitsPerPixel, pabyOTile,
+ poRBI->nBlockXSize, poRBI->nBlockYSize,
+ nTXOff, nTYOff,
+ nOMult, nSampleFormat, pszResampling );
#ifdef DBMALLOC
- malloc_chain_check( 1 );
-#endif
+ malloc_chain_check( 1 );
+#endif
+ }
}
}
}
@@ -474,6 +699,8 @@ void TIFFBuildOverviews( TIFF *hTIFF, int nOverviews, int * panOvList,
uint32 nXSize, nYSize, nBlockXSize, nBlockYSize;
uint16 nBitsPerPixel, nPhotometric, nCompressFlag, nSamples,
nPlanarConfig, nSampleFormat;
+ int bSubsampled;
+ uint16 nHorSubsampling, nVerSubsampling;
int bTiled, nSXOff, nSYOff, i;
unsigned char *pabySrcTile;
uint16 *panRedMap, *panGreenMap, *panBlueMap;
@@ -486,6 +713,7 @@ void TIFFBuildOverviews( TIFF *hTIFF, int nOverviews, int * panOvList,
TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &nYSize );
TIFFGetField( hTIFF, TIFFTAG_BITSPERSAMPLE, &nBitsPerPixel );
+ /* TODO: nBitsPerPixel seems misnomer and may need renaming to nBitsPerSample */
TIFFGetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, &nSamples );
TIFFGetFieldDefaulted( hTIFF, TIFFTAG_PLANARCONFIG, &nPlanarConfig );
@@ -493,15 +721,39 @@ void TIFFBuildOverviews( TIFF *hTIFF, int nOverviews, int * panOvList,
TIFFGetFieldDefaulted( hTIFF, TIFFTAG_COMPRESSION, &nCompressFlag );
TIFFGetFieldDefaulted( hTIFF, TIFFTAG_SAMPLEFORMAT, &nSampleFormat );
- if( nBitsPerPixel < 8 )
+ if( nPhotometric == PHOTOMETRIC_YCBCR || nPhotometric == PHOTOMETRIC_ITULAB )
{
- TIFFError( "TIFFBuildOverviews",
- "File `%s' has samples of %d bits per sample. Sample\n"
- "sizes of less than 8 bits per sample are not supported.\n",
- TIFFFileName(hTIFF), nBitsPerPixel );
- return;
+ if( nBitsPerPixel != 8 || nSamples != 3 || nPlanarConfig != PLANARCONFIG_CONTIG ||
+ nSampleFormat != SAMPLEFORMAT_UINT)
+ {
+ TIFFError( NULL, "TIFFBuildOverviews",
+ "File `%s' has an unsupported subsampling configuration.\n",
+ TIFFFileName(hTIFF) );
+ /* If you need support for this particular flavor, please contact either
+ * Frank Warmerdam warmerdam@pobox.com
+ * Joris Van Damme info@awaresystems.be
+ */
+ return;
+ }
+ bSubsampled = 1;
+ TIFFGetField( hTIFF, TIFFTAG_YCBCRSUBSAMPLING, &nHorSubsampling, &nVerSubsampling );
+ /* TODO: find out if maybe TIFFGetFieldDefaulted is better choice for YCbCrSubsampling tag */
}
-
+ else
+ {
+ if( nBitsPerPixel < 8 )
+ {
+ TIFFError( NULL, "TIFFBuildOverviews",
+ "File `%s' has samples of %d bits per sample. Sample\n"
+ "sizes of less than 8 bits per sample are not supported.\n",
+ TIFFFileName(hTIFF), nBitsPerPixel );
+ return;
+ }
+ bSubsampled = 0;
+ nHorSubsampling = 1;
+ nVerSubsampling = 1;
+ }
+
/* -------------------------------------------------------------------- */
/* Turn off warnings to avoid alot of repeated warnings while */
/* rereading directories. */
@@ -548,7 +800,7 @@ void TIFFBuildOverviews( TIFF *hTIFF, int nOverviews, int * panOvList,
{
panRedMap = panGreenMap = panBlueMap = NULL;
}
-
+
/* -------------------------------------------------------------------- */
/* Initialize overviews. */
/* -------------------------------------------------------------------- */
@@ -569,7 +821,7 @@ void TIFFBuildOverviews( TIFF *hTIFF, int nOverviews, int * panOvList,
{
if( (nOBlockXSize % 16) != 0 )
nOBlockXSize = nOBlockXSize + 16 - (nOBlockXSize % 16);
-
+
if( (nOBlockYSize % 16) != 0 )
nOBlockYSize = nOBlockYSize + 16 - (nOBlockYSize % 16);
}
@@ -580,7 +832,8 @@ void TIFFBuildOverviews( TIFF *hTIFF, int nOverviews, int * panOvList,
bTiled, nCompressFlag, nPhotometric,
nSampleFormat,
panRedMap, panGreenMap, panBlueMap,
- bUseSubIFDs );
+ bUseSubIFDs,
+ nHorSubsampling, nVerSubsampling );
papoRawBIs[i] = TIFFCreateOvrCache( hTIFF, nDirOffset );
}
@@ -613,6 +866,7 @@ void TIFFBuildOverviews( TIFF *hTIFF, int nOverviews, int * panOvList,
*/
TIFF_ProcessFullResBlock( hTIFF, nPlanarConfig,
+ bSubsampled,nHorSubsampling,nVerSubsampling,
nOverviews, panOvList,
nBitsPerPixel, nSamples, papoRawBIs,
nSXOff, nSYOff, pabySrcTile,
@@ -636,3 +890,5 @@ void TIFFBuildOverviews( TIFF *hTIFF, int nOverviews, int * panOvList,
TIFFSetWarningHandler( pfnWarning );
}
+
+
diff --git a/contrib/addtiffo/tif_ovrcache.c b/contrib/addtiffo/tif_ovrcache.c
index 3210f17c..5cb2400d 100644
--- a/contrib/addtiffo/tif_ovrcache.c
+++ b/contrib/addtiffo/tif_ovrcache.c
@@ -1,10 +1,10 @@
/******************************************************************************
- * $Id: tif_ovrcache.c,v 1.4 2005-06-07 14:26:04 dron Exp $
+ * $Id: tif_ovrcache.c,v 1.5 2005-12-16 05:59:55 fwarmerdam Exp $
*
* Project: TIFF Overview Builder
* Purpose: Library functions to maintain two rows of tiles or two strips
* of data for output overviews as an output cache.
- * Author: Frank Warmerdam, warmerda@home.com
+ * Author: Frank Warmerdam, warmerdam@pobox.com
*
******************************************************************************
* Copyright (c) 2000, Frank Warmerdam
@@ -109,6 +109,7 @@ TIFFOvrCache *TIFFCreateOvrCache( TIFF *hTIFF, int nDirOffset )
{
TIFFError( hTIFF->tif_name,
"Can't allocate memory for overview cache." );
+ /* TODO: use of TIFFError is inconsistent with use of fprintf in addtiffo.c, sort out */
return NULL;
}
@@ -138,9 +139,9 @@ static void TIFFWriteOvrRow( TIFFOvrCache * psCache )
uint32 nBaseDirOffset;
/* -------------------------------------------------------------------- */
-/* If the output cache is multi-byte per sample, and the file */
-/* being written to is of a different byte order than the current */
-/* platform, we will need to byte swap the data. */
+/* If the output cache is multi-byte per sample, and the file */
+/* being written to is of a different byte order than the current */
+/* platform, we will need to byte swap the data. */
/* -------------------------------------------------------------------- */
if( TIFFIsByteSwapped(psCache->hTIFF) )
{
@@ -233,6 +234,7 @@ static void TIFFWriteOvrRow( TIFFOvrCache * psCache )
}
}
}
+ /* TODO: add checks on error status return of TIFFWriteEncodedTile and TIFFWriteEncodedStrip */
/* -------------------------------------------------------------------- */
/* Rotate buffers. */
@@ -249,20 +251,23 @@ static void TIFFWriteOvrRow( TIFFOvrCache * psCache )
/* Restore access to original directory. */
/* -------------------------------------------------------------------- */
TIFFFlush( psCache->hTIFF );
-
+ /* TODO: add checks on error status return of TIFFFlush */
TIFFSetSubDirectory( psCache->hTIFF, nBaseDirOffset );
+ /* TODO: add checks on error status return of TIFFSetSubDirectory */
}
/************************************************************************/
/* TIFFGetOvrBlock() */
/************************************************************************/
+/* TODO: make TIFF_Downsample handle iSample offset, so that we can
+ * do with a single TIFFGetOvrBlock and no longer need TIFFGetOvrBlock_Subsampled */
unsigned char *TIFFGetOvrBlock( TIFFOvrCache *psCache, int iTileX, int iTileY,
int iSample )
{
int nRowOffset;
-
+
if( iTileY > psCache->nBlockOffset + 1 )
TIFFWriteOvrRow( psCache );
@@ -286,6 +291,33 @@ unsigned char *TIFFGetOvrBlock( TIFFOvrCache *psCache, int iTileX, int iTileY,
}
/************************************************************************/
+/* TIFFGetOvrBlock_Subsampled() */
+/************************************************************************/
+
+unsigned char *TIFFGetOvrBlock_Subsampled( TIFFOvrCache *psCache,
+ int iTileX, int iTileY )
+
+{
+ int nRowOffset;
+
+ if( iTileY > psCache->nBlockOffset + 1 )
+ TIFFWriteOvrRow( psCache );
+
+ assert( iTileX >= 0 && iTileX < psCache->nBlocksPerRow );
+ assert( iTileY >= 0 && iTileY < psCache->nBlocksPerColumn );
+ assert( iTileY >= psCache->nBlockOffset
+ && iTileY < psCache->nBlockOffset+2 );
+ assert( psCache->nPlanarConfig != PLANARCONFIG_SEPARATE );
+
+ nRowOffset = iTileX * psCache->nBytesPerBlock;
+
+ if( iTileY == psCache->nBlockOffset )
+ return psCache->pabyRow1Blocks + nRowOffset;
+ else
+ return psCache->pabyRow2Blocks + nRowOffset;
+}
+
+/************************************************************************/
/* TIFFDestroyOvrCache() */
/************************************************************************/
diff --git a/contrib/addtiffo/tif_ovrcache.h b/contrib/addtiffo/tif_ovrcache.h
index 0b9b3f9d..3298c872 100644
--- a/contrib/addtiffo/tif_ovrcache.h
+++ b/contrib/addtiffo/tif_ovrcache.h
@@ -4,7 +4,7 @@
* Project: TIFF Overview Builder
* Purpose: Library functions to maintain two rows of tiles or two strips
* of data for output overviews as an output cache.
- * Author: Frank Warmerdam, warmerda@home.com
+ * Author: Frank Warmerdam, warmerdam@pobox.com
*
* This code could potentially be used by other applications wanting to
* manage a once-through write cache.
@@ -68,13 +68,16 @@ typedef struct
} TIFFOvrCache;
TIFFOvrCache *TIFFCreateOvrCache( TIFF *hTIFF, int nDirOffset );
-unsigned char *TIFFGetOvrBlock( TIFFOvrCache *, int, int, int );
+unsigned char *TIFFGetOvrBlock( TIFFOvrCache *psCache, int iTileX, int iTileY,
+ int iSample );
+unsigned char *TIFFGetOvrBlock_Subsampled( TIFFOvrCache *psCache, int iTileX, int iTileY );
void TIFFDestroyOvrCache( TIFFOvrCache * );
void TIFFBuildOverviews( TIFF *, int, int *, int, const char *,
int (*)(double,void*), void * );
void TIFF_ProcessFullResBlock( TIFF *hTIFF, int nPlanarConfig,
+ int bSubsampled, int nHorSamples, int nVerSamples,
int nOverviews, int * panOvList,
int nBitsPerPixel,
int nSamples, TIFFOvrCache ** papoRawBIs,
@@ -85,7 +88,10 @@ void TIFF_ProcessFullResBlock( TIFF *hTIFF, int nPlanarConfig,
uint32 TIFF_WriteOverview( TIFF *, int, int, int, int, int, int, int,
int, int, int, int, unsigned short *,
- unsigned short *, unsigned short *, int );
+ unsigned short *, unsigned short *, int,
+ int, int);
+
+
#if defined(__cplusplus)
}