123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341 |
- /******************************************************************************
- * $Id: tif_ovrcache.c,v 1.9 2010-06-08 18:55:15 bfriesen 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, warmerdam@pobox.com
- *
- ******************************************************************************
- * Copyright (c) 2000, Frank Warmerdam
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, sublicense,
- * and/or sell copies of the Software, and to permit persons to whom the
- * Software is furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included
- * in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- * DEALINGS IN THE SOFTWARE.
- ******************************************************************************
- */
- #include "tiffiop.h"
- #include "tif_ovrcache.h"
- #include <assert.h>
- /************************************************************************/
- /* TIFFCreateOvrCache() */
- /* */
- /* Create an overview cache to hold two rows of blocks from an */
- /* existing TIFF directory. */
- /************************************************************************/
- TIFFOvrCache *TIFFCreateOvrCache( TIFF *hTIFF, toff_t nDirOffset )
- {
- TIFFOvrCache *psCache;
- toff_t nBaseDirOffset;
- psCache = (TIFFOvrCache *) _TIFFmalloc(sizeof(TIFFOvrCache));
- psCache->nDirOffset = nDirOffset;
- psCache->hTIFF = hTIFF;
-
- /* -------------------------------------------------------------------- */
- /* Get definition of this raster from the TIFF file itself. */
- /* -------------------------------------------------------------------- */
- nBaseDirOffset = TIFFCurrentDirOffset( psCache->hTIFF );
- TIFFSetSubDirectory( hTIFF, nDirOffset );
-
- TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &(psCache->nXSize) );
- TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &(psCache->nYSize) );
- TIFFGetField( hTIFF, TIFFTAG_BITSPERSAMPLE, &(psCache->nBitsPerPixel) );
- TIFFGetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, &(psCache->nSamples) );
- TIFFGetField( hTIFF, TIFFTAG_PLANARCONFIG, &(psCache->nPlanarConfig) );
- if( !TIFFIsTiled( hTIFF ) )
- {
- TIFFGetField( hTIFF, TIFFTAG_ROWSPERSTRIP, &(psCache->nBlockYSize) );
- psCache->nBlockXSize = psCache->nXSize;
- psCache->nBytesPerBlock = TIFFStripSize(hTIFF);
- psCache->bTiled = FALSE;
- }
- else
- {
- TIFFGetField( hTIFF, TIFFTAG_TILEWIDTH, &(psCache->nBlockXSize) );
- TIFFGetField( hTIFF, TIFFTAG_TILELENGTH, &(psCache->nBlockYSize) );
- psCache->nBytesPerBlock = TIFFTileSize(hTIFF);
- psCache->bTiled = TRUE;
- }
- /* -------------------------------------------------------------------- */
- /* Compute some values from this. */
- /* -------------------------------------------------------------------- */
- psCache->nBlocksPerRow = (psCache->nXSize + psCache->nBlockXSize - 1)
- / psCache->nBlockXSize;
- psCache->nBlocksPerColumn = (psCache->nYSize + psCache->nBlockYSize - 1)
- / psCache->nBlockYSize;
- if (psCache->nPlanarConfig == PLANARCONFIG_SEPARATE)
- psCache->nBytesPerRow = psCache->nBytesPerBlock
- * psCache->nBlocksPerRow * psCache->nSamples;
- else
- psCache->nBytesPerRow =
- psCache->nBytesPerBlock * psCache->nBlocksPerRow;
- /* -------------------------------------------------------------------- */
- /* Allocate and initialize the data buffers. */
- /* -------------------------------------------------------------------- */
- psCache->pabyRow1Blocks =
- (unsigned char *) _TIFFmalloc(psCache->nBytesPerRow);
- psCache->pabyRow2Blocks =
- (unsigned char *) _TIFFmalloc(psCache->nBytesPerRow);
- if( psCache->pabyRow1Blocks == NULL
- || psCache->pabyRow2Blocks == NULL )
- {
- TIFFErrorExt( hTIFF->tif_clientdata, 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;
- }
- _TIFFmemset( psCache->pabyRow1Blocks, 0, psCache->nBytesPerRow );
- _TIFFmemset( psCache->pabyRow2Blocks, 0, psCache->nBytesPerRow );
- psCache->nBlockOffset = 0;
- TIFFSetSubDirectory( psCache->hTIFF, nBaseDirOffset );
-
- return psCache;
- }
- /************************************************************************/
- /* TIFFWriteOvrRow() */
- /* */
- /* Write one entire row of blocks (row 1) to the tiff file, and */
- /* then rotate the block buffers, essentially moving things */
- /* down by one block. */
- /************************************************************************/
- static void TIFFWriteOvrRow( TIFFOvrCache * psCache )
- {
- int nRet, iTileX, iTileY = psCache->nBlockOffset;
- unsigned char *pabyData;
- toff_t nBaseDirOffset;
- uint32 RowsInStrip;
- /* -------------------------------------------------------------------- */
- /* 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) )
- {
- if( psCache->nBitsPerPixel == 16 )
- TIFFSwabArrayOfShort( (uint16 *) psCache->pabyRow1Blocks,
- (psCache->nBytesPerBlock * psCache->nSamples) / 2 );
- else if( psCache->nBitsPerPixel == 32 )
- TIFFSwabArrayOfLong( (uint32 *) psCache->pabyRow1Blocks,
- (psCache->nBytesPerBlock * psCache->nSamples) / 4 );
- else if( psCache->nBitsPerPixel == 64 )
- TIFFSwabArrayOfDouble( (double *) psCache->pabyRow1Blocks,
- (psCache->nBytesPerBlock * psCache->nSamples) / 8 );
- }
- /* -------------------------------------------------------------------- */
- /* Record original directory position, so we can restore it at */
- /* end. */
- /* -------------------------------------------------------------------- */
- nBaseDirOffset = TIFFCurrentDirOffset( psCache->hTIFF );
- nRet = TIFFSetSubDirectory( psCache->hTIFF, psCache->nDirOffset );
- assert( nRet == 1 );
- /* -------------------------------------------------------------------- */
- /* Write blocks to TIFF file. */
- /* -------------------------------------------------------------------- */
- for( iTileX = 0; iTileX < psCache->nBlocksPerRow; iTileX++ )
- {
- int nTileID;
- if (psCache->nPlanarConfig == PLANARCONFIG_SEPARATE)
- {
- int iSample;
- for( iSample = 0; iSample < psCache->nSamples; iSample++ )
- {
- pabyData = TIFFGetOvrBlock( psCache, iTileX, iTileY, iSample );
- if( psCache->bTiled )
- {
- nTileID = TIFFComputeTile( psCache->hTIFF,
- iTileX * psCache->nBlockXSize,
- iTileY * psCache->nBlockYSize,
- 0, (tsample_t) iSample );
- TIFFWriteEncodedTile( psCache->hTIFF, nTileID,
- pabyData,
- TIFFTileSize(psCache->hTIFF) );
- }
- else
- {
- nTileID = TIFFComputeStrip( psCache->hTIFF,
- iTileY * psCache->nBlockYSize,
- (tsample_t) iSample );
- RowsInStrip=psCache->nBlockYSize;
- if ((iTileY+1)*psCache->nBlockYSize>psCache->nYSize)
- RowsInStrip=psCache->nYSize-iTileY*psCache->nBlockYSize;
- TIFFWriteEncodedStrip( psCache->hTIFF, nTileID,
- pabyData,
- TIFFVStripSize(psCache->hTIFF,RowsInStrip) );
- }
- }
- }
- else
- {
- pabyData = TIFFGetOvrBlock( psCache, iTileX, iTileY, 0 );
- if( psCache->bTiled )
- {
- nTileID = TIFFComputeTile( psCache->hTIFF,
- iTileX * psCache->nBlockXSize,
- iTileY * psCache->nBlockYSize,
- 0, 0 );
- TIFFWriteEncodedTile( psCache->hTIFF, nTileID,
- pabyData,
- TIFFTileSize(psCache->hTIFF) );
- }
- else
- {
- nTileID = TIFFComputeStrip( psCache->hTIFF,
- iTileY * psCache->nBlockYSize,
- 0 );
- RowsInStrip=psCache->nBlockYSize;
- if ((iTileY+1)*psCache->nBlockYSize>psCache->nYSize)
- RowsInStrip=psCache->nYSize-iTileY*psCache->nBlockYSize;
- TIFFWriteEncodedStrip( psCache->hTIFF, nTileID,
- pabyData,
- TIFFVStripSize(psCache->hTIFF,RowsInStrip) );
- }
- }
- }
- /* TODO: add checks on error status return of TIFFWriteEncodedTile and TIFFWriteEncodedStrip */
- /* -------------------------------------------------------------------- */
- /* Rotate buffers. */
- /* -------------------------------------------------------------------- */
- pabyData = psCache->pabyRow1Blocks;
- psCache->pabyRow1Blocks = psCache->pabyRow2Blocks;
- psCache->pabyRow2Blocks = pabyData;
- _TIFFmemset( pabyData, 0, psCache->nBytesPerRow );
- psCache->nBlockOffset++;
- /* -------------------------------------------------------------------- */
- /* 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 );
- assert( iTileX >= 0 && iTileX < psCache->nBlocksPerRow );
- assert( iTileY >= 0 && iTileY < psCache->nBlocksPerColumn );
- assert( iTileY >= psCache->nBlockOffset
- && iTileY < psCache->nBlockOffset+2 );
- assert( iSample >= 0 && iSample < psCache->nSamples );
- if (psCache->nPlanarConfig == PLANARCONFIG_SEPARATE)
- nRowOffset = ((iTileX * psCache->nSamples) + iSample)
- * psCache->nBytesPerBlock;
- else
- nRowOffset = iTileX * psCache->nBytesPerBlock +
- (psCache->nBitsPerPixel + 7) / 8 * iSample;
- if( iTileY == psCache->nBlockOffset )
- return psCache->pabyRow1Blocks + nRowOffset;
- else
- return psCache->pabyRow2Blocks + nRowOffset;
- }
- /************************************************************************/
- /* 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() */
- /************************************************************************/
- void TIFFDestroyOvrCache( TIFFOvrCache * psCache )
- {
- while( psCache->nBlockOffset < psCache->nBlocksPerColumn )
- TIFFWriteOvrRow( psCache );
- _TIFFfree( psCache->pabyRow1Blocks );
- _TIFFfree( psCache->pabyRow2Blocks );
- _TIFFfree( psCache );
- }
- /*
- * Local Variables:
- * mode: c
- * c-basic-offset: 8
- * fill-column: 78
- * End:
- */
|