void TIFFBuildOverviews( TIFF *hTIFF, int nOverviews, int * panOvList, int bUseSubIFDs, const char *pszResampleMethod, int (*pfnProgress)( double, void * ), void * pProgressData ) { TIFFOvrCache **papoRawBIs; uint32 nXSize, nYSize, nBlockXSize, nBlockYSize; uint16 nBitsPerPixel, nPhotometric, nCompressFlag, nSamples, nPlanarConfig, nSampleFormat; int bTiled, nSXOff, nSYOff, i; unsigned char *pabySrcTile; uint16 *panRedMap, *panGreenMap, *panBlueMap; TIFFErrorHandler pfnWarning; /* -------------------------------------------------------------------- */ /* Get the base raster size. */ /* -------------------------------------------------------------------- */ TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &nXSize ); TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &nYSize ); TIFFGetField( hTIFF, TIFFTAG_BITSPERSAMPLE, &nBitsPerPixel ); TIFFGetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, &nSamples ); TIFFGetFieldDefaulted( hTIFF, TIFFTAG_PLANARCONFIG, &nPlanarConfig ); TIFFGetFieldDefaulted( hTIFF, TIFFTAG_PHOTOMETRIC, &nPhotometric ); TIFFGetFieldDefaulted( hTIFF, TIFFTAG_COMPRESSION, &nCompressFlag ); TIFFGetFieldDefaulted( hTIFF, TIFFTAG_SAMPLEFORMAT, &nSampleFormat ); if( nBitsPerPixel < 8 ) { 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; } /* -------------------------------------------------------------------- */ /* Turn off warnings to avoid alot of repeated warnings while */ /* rereading directories. */ /* -------------------------------------------------------------------- */ pfnWarning = TIFFSetWarningHandler( NULL ); /* -------------------------------------------------------------------- */ /* Get the base raster block size. */ /* -------------------------------------------------------------------- */ if( TIFFGetField( hTIFF, TIFFTAG_ROWSPERSTRIP, &(nBlockYSize) ) ) { nBlockXSize = nXSize; bTiled = FALSE; } else { TIFFGetField( hTIFF, TIFFTAG_TILEWIDTH, &nBlockXSize ); TIFFGetField( hTIFF, TIFFTAG_TILELENGTH, &nBlockYSize ); bTiled = TRUE; } /* -------------------------------------------------------------------- */ /* Capture the pallette if there is one. */ /* -------------------------------------------------------------------- */ if( TIFFGetField( hTIFF, TIFFTAG_COLORMAP, &panRedMap, &panGreenMap, &panBlueMap ) ) { uint16 *panRed2, *panGreen2, *panBlue2; panRed2 = (uint16 *) _TIFFmalloc(2*256); panGreen2 = (uint16 *) _TIFFmalloc(2*256); panBlue2 = (uint16 *) _TIFFmalloc(2*256); memcpy( panRed2, panRedMap, 512 ); memcpy( panGreen2, panGreenMap, 512 ); memcpy( panBlue2, panBlueMap, 512 ); panRedMap = panRed2; panGreenMap = panGreen2; panBlueMap = panBlue2; } else { panRedMap = panGreenMap = panBlueMap = NULL; } /* -------------------------------------------------------------------- */ /* Initialize overviews. */ /* -------------------------------------------------------------------- */ papoRawBIs = (TIFFOvrCache **) _TIFFmalloc(nOverviews*sizeof(void*)); for( i = 0; i < nOverviews; i++ ) { int nOXSize, nOYSize, nOBlockXSize, nOBlockYSize; uint32 nDirOffset; nOXSize = (nXSize + panOvList[i] - 1) / panOvList[i]; nOYSize = (nYSize + panOvList[i] - 1) / panOvList[i]; nOBlockXSize = MIN((int)nBlockXSize,nOXSize); nOBlockYSize = MIN((int)nBlockYSize,nOYSize); if( bTiled ) { if( (nOBlockXSize % 16) != 0 ) nOBlockXSize = nOBlockXSize + 16 - (nOBlockXSize % 16); if( (nOBlockYSize % 16) != 0 ) nOBlockYSize = nOBlockYSize + 16 - (nOBlockYSize % 16); } nDirOffset = TIFF_WriteOverview( hTIFF, nOXSize, nOYSize, nBitsPerPixel, nSamples, nOBlockXSize, nOBlockYSize, bTiled, nCompressFlag, nPhotometric, nSampleFormat, panRedMap, panGreenMap, panBlueMap, bUseSubIFDs ); papoRawBIs[i] = TIFFCreateOvrCache( hTIFF, nDirOffset ); } if( panRedMap != NULL ) { _TIFFfree( panRedMap ); _TIFFfree( panGreenMap ); _TIFFfree( panBlueMap ); } /* -------------------------------------------------------------------- */ /* Allocate a buffer to hold a source block. */ /* -------------------------------------------------------------------- */ if( bTiled ) pabySrcTile = (unsigned char *) _TIFFmalloc(TIFFTileSize(hTIFF)); else pabySrcTile = (unsigned char *) _TIFFmalloc(TIFFStripSize(hTIFF)); /* -------------------------------------------------------------------- */ /* Loop over the source raster, applying data to the */ /* destination raster. */ /* -------------------------------------------------------------------- */ for( nSYOff = 0; nSYOff < (int) nYSize; nSYOff += nBlockYSize ) { for( nSXOff = 0; nSXOff < (int) nXSize; nSXOff += nBlockXSize ) { /* * Read and resample into the various overview images. */ TIFF_ProcessFullResBlock( hTIFF, nPlanarConfig, nOverviews, panOvList, nBitsPerPixel, nSamples, papoRawBIs, nSXOff, nSYOff, pabySrcTile, nBlockXSize, nBlockYSize, nSampleFormat, pszResampleMethod ); } } _TIFFfree( pabySrcTile ); /* -------------------------------------------------------------------- */ /* Cleanup the rawblockedimage files. */ /* -------------------------------------------------------------------- */ for( i = 0; i < nOverviews; i++ ) { TIFFDestroyOvrCache( papoRawBIs[i] ); } if( papoRawBIs != NULL ) _TIFFfree( papoRawBIs ); TIFFSetWarningHandler( pfnWarning ); }
void TIFFBuildOverviews( const char * pszTIFFFilename, int nOverviews, int * panOvList, int bUseSubIFDs ) { RawBlockedImage **papoRawBIs; uint32 nXSize, nYSize, nBlockXSize, nBlockYSize; uint16 nBitsPerPixel, nPhotometric, nCompressFlag, nSamples, nPlanarConfig; int bTiled, nSXOff, nSYOff, i, iSample; unsigned char *pabySrcTile; TIFF *hTIFF; uint16 *panRedMap, *panGreenMap, *panBlueMap; /* -------------------------------------------------------------------- */ /* Get the base raster size. */ /* -------------------------------------------------------------------- */ hTIFF = TIFFOpen( pszTIFFFilename, "r" ); if( hTIFF == NULL ) { fprintf( stderr, "TIFFOpen(%s) failed.\n", pszTIFFFilename ); exit( 1 ); } TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &nXSize ); TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &nYSize ); TIFFGetField( hTIFF, TIFFTAG_BITSPERSAMPLE, &nBitsPerPixel ); TIFFGetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, &nSamples ); TIFFGetField( hTIFF, TIFFTAG_PLANARCONFIG, &nPlanarConfig ); TIFFGetField( hTIFF, TIFFTAG_PHOTOMETRIC, &nPhotometric ); TIFFGetField( hTIFF, TIFFTAG_COMPRESSION, &nCompressFlag ); if( nBitsPerPixel < 8 ) { 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", pszTIFFFilename, nBitsPerPixel ); return; } /* -------------------------------------------------------------------- */ /* Get the base raster block size. */ /* -------------------------------------------------------------------- */ if( TIFFGetField( hTIFF, TIFFTAG_ROWSPERSTRIP, &(nBlockYSize) ) ) { nBlockXSize = nXSize; bTiled = FALSE; } else { TIFFGetField( hTIFF, TIFFTAG_TILEWIDTH, &nBlockXSize ); TIFFGetField( hTIFF, TIFFTAG_TILELENGTH, &nBlockYSize ); bTiled = TRUE; } /* -------------------------------------------------------------------- */ /* Capture the pallette if there is one. */ /* -------------------------------------------------------------------- */ if( TIFFGetField( hTIFF, TIFFTAG_COLORMAP, &panRedMap, &panGreenMap, &panBlueMap ) ) { uint16 *panRed2, *panGreen2, *panBlue2; panRed2 = (uint16 *) calloc(2,256); panGreen2 = (uint16 *) calloc(2,256); panBlue2 = (uint16 *) calloc(2,256); memcpy( panRed2, panRedMap, 512 ); memcpy( panGreen2, panGreenMap, 512 ); memcpy( panBlue2, panBlueMap, 512 ); panRedMap = panRed2; panGreenMap = panGreen2; panBlueMap = panBlue2; } else { panRedMap = panGreenMap = panBlueMap = NULL; } /* -------------------------------------------------------------------- */ /* Initialize the overview raw layers */ /* -------------------------------------------------------------------- */ papoRawBIs = (RawBlockedImage **) calloc(nOverviews*nSamples,sizeof(void*)); for( i = 0; i < nOverviews; i++ ) { int nOXSize, nOYSize, nOBlockXSize, nOBlockYSize; nOXSize = (nXSize + panOvList[i] - 1) / panOvList[i]; nOYSize = (nYSize + panOvList[i] - 1) / panOvList[i]; nOBlockXSize = MIN((int)nBlockXSize,nOXSize); nOBlockYSize = MIN((int)nBlockYSize,nOYSize); if( bTiled ) { if( (nOBlockXSize % 16) != 0 ) nOBlockXSize = nOBlockXSize + 16 - (nOBlockXSize % 16); if( (nOBlockYSize % 16) != 0 ) nOBlockYSize = nOBlockYSize + 16 - (nOBlockYSize % 16); } for( iSample = 0; iSample < nSamples; iSample++ ) { papoRawBIs[i*nSamples + iSample] = new RawBlockedImage( nOXSize, nOYSize, nOBlockXSize, nOBlockYSize, nBitsPerPixel ); } } /* -------------------------------------------------------------------- */ /* Allocate a buffer to hold a source block. */ /* -------------------------------------------------------------------- */ if( bTiled ) pabySrcTile = (unsigned char *) malloc(TIFFTileSize(hTIFF)); else pabySrcTile = (unsigned char *) malloc(TIFFStripSize(hTIFF)); /* -------------------------------------------------------------------- */ /* Loop over the source raster, applying data to the */ /* destination raster. */ /* -------------------------------------------------------------------- */ for( nSYOff = 0; nSYOff < (int) nYSize; nSYOff += nBlockYSize ) { for( nSXOff = 0; nSXOff < (int) nXSize; nSXOff += nBlockXSize ) { /* * Read and resample into the various overview images. */ TIFF_ProcessFullResBlock( hTIFF, nPlanarConfig, nOverviews, panOvList, nBitsPerPixel, nSamples, papoRawBIs, nSXOff, nSYOff, pabySrcTile, nBlockXSize, nBlockYSize ); } } free( pabySrcTile ); TIFFClose( hTIFF ); /* ==================================================================== */ /* We now have the overview rasters built, and held as */ /* RawBlockedImage's. Now we need to write them to new TIFF */ /* layers. */ /* ==================================================================== */ hTIFF = TIFFOpen( pszTIFFFilename, "a" ); if( hTIFF == NULL ) { fprintf( stderr, "TIFFOpen(%s,\"a\") failed. No overviews written.\n" "Do you have write permissions on that file?\n", pszTIFFFilename ); } else { for( i = 0; i < nOverviews; i++ ) { TIFF_WriteOverview( hTIFF, nSamples, papoRawBIs + i*nSamples, bTiled, nCompressFlag, nPhotometric, panRedMap, panGreenMap, panBlueMap, bUseSubIFDs ); } TIFFClose( hTIFF ); } /* -------------------------------------------------------------------- */ /* Cleanup the rawblockedimage files. */ /* -------------------------------------------------------------------- */ for( i = 0; i < nOverviews*nSamples; i++ ) { delete papoRawBIs[i]; } if( papoRawBIs != NULL ) free( papoRawBIs ); if( panRedMap != NULL ) { free( panRedMap ); free( panGreenMap ); free( panBlueMap ); } }