diff options
author | fwarmerdam <fwarmerdam> | 2005-12-16 05:59:55 +0000 |
---|---|---|
committer | fwarmerdam <fwarmerdam> | 2005-12-16 05:59:55 +0000 |
commit | 9c901e868dc41d2130c16138bc84797960d4dbe9 (patch) | |
tree | b8407637277f7e751830c4422bdff1581913985d /contrib | |
parent | aaf4b1abd65dc65f6901a43bb5977daaacf741dc (diff) | |
download | libtiff-9c901e868dc41d2130c16138bc84797960d4dbe9.tar.gz |
Major upgrade to support YCbCr subsampled jpeg images
Diffstat (limited to 'contrib')
-rw-r--r-- | contrib/addtiffo/addtiffo.c | 31 | ||||
-rw-r--r-- | contrib/addtiffo/tif_overview.c | 362 | ||||
-rw-r--r-- | contrib/addtiffo/tif_ovrcache.c | 46 | ||||
-rw-r--r-- | contrib/addtiffo/tif_ovrcache.h | 12 |
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) } |