summaryrefslogtreecommitdiff
path: root/tiff/contrib/addtiffo/tif_ovrcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'tiff/contrib/addtiffo/tif_ovrcache.c')
-rw-r--r--tiff/contrib/addtiffo/tif_ovrcache.c341
1 files changed, 341 insertions, 0 deletions
diff --git a/tiff/contrib/addtiffo/tif_ovrcache.c b/tiff/contrib/addtiffo/tif_ovrcache.c
new file mode 100644
index 0000000..646b534
--- /dev/null
+++ b/tiff/contrib/addtiffo/tif_ovrcache.c
@@ -0,0 +1,341 @@
+/******************************************************************************
+ * $Id: tif_ovrcache.c,v 1.7.2.1 2010-06-08 18:50:40 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, int nDirOffset )
+
+{
+ TIFFOvrCache *psCache;
+ uint32 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;
+ uint32 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:
+ */