summaryrefslogtreecommitdiff
path: root/contrib/addtiffo/rawblockedimage.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/addtiffo/rawblockedimage.cpp')
-rw-r--r--contrib/addtiffo/rawblockedimage.cpp403
1 files changed, 403 insertions, 0 deletions
diff --git a/contrib/addtiffo/rawblockedimage.cpp b/contrib/addtiffo/rawblockedimage.cpp
new file mode 100644
index 00000000..8a37afd5
--- /dev/null
+++ b/contrib/addtiffo/rawblockedimage.cpp
@@ -0,0 +1,403 @@
+/******************************************************************************
+ * $Id: rawblockedimage.cpp,v 1.1 1999/08/17 01:47:59 warmerda Exp $
+ *
+ * Project: GeoTIFF Overview Builder
+ * Purpose: Implement the RawBlockedImage class, for holding ``under
+ * construction'' overviews in a temporary file.
+ * Author: Frank Warmerdam, warmerda@home.com
+ *
+ ******************************************************************************
+ * Copyright (c) 1999, 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.
+ ******************************************************************************
+ *
+ * $Log: rawblockedimage.cpp,v $
+ * Revision 1.1 1999/08/17 01:47:59 warmerda
+ * New
+ *
+ * Revision 1.2 1999/03/12 17:29:34 warmerda
+ * Use _WIN32 rather than WIN32.
+ *
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include <stdlib.h>
+
+#ifndef _WIN32
+# include <unistd.h>
+#endif
+
+#include "rawblockedimage.h"
+
+#ifndef FALSE
+# define FALSE 0
+# define TRUE 1
+#endif
+
+#ifndef MAX
+# define MIN(a,b) ((a<b) ? a : b)
+# define MAX(a,b) ((a>b) ? a : b)
+#endif
+
+/************************************************************************/
+/* RawBlockedImage() */
+/************************************************************************/
+
+RawBlockedImage::RawBlockedImage( int nXSizeIn, int nYSizeIn,
+ int nBlockXSizeIn, int nBlockYSizeIn,
+ int nBitsPerPixelIn )
+
+{
+ static int nTempCounter = 0;
+ char szFilename[128];
+
+/* -------------------------------------------------------------------- */
+/* Initialize stuff. */
+/* -------------------------------------------------------------------- */
+ nXSize = nXSizeIn;
+ nYSize = nYSizeIn;
+ nBlockXSize = nBlockXSizeIn;
+ nBlockYSize = nBlockYSizeIn;
+ nBitsPerPixel = nBitsPerPixelIn;
+
+/* -------------------------------------------------------------------- */
+/* Create the raw temporary file, trying to verify first that */
+/* it doesn't already exist. */
+/* -------------------------------------------------------------------- */
+ fp = NULL;
+ while( fp == NULL )
+ {
+ sprintf( szFilename, "temp_%d.rbi", nTempCounter++ );
+ fp = fopen( szFilename, "r" );
+ if( fp != NULL )
+ fclose( fp );
+ else
+ fp = fopen( szFilename, "w+b" );
+ }
+
+ pszFilename = strdup( szFilename );
+ nCurFileSize = 0;
+
+/* -------------------------------------------------------------------- */
+/* Initialize other stuff. */
+/* -------------------------------------------------------------------- */
+ nBlocksPerRow = (nXSize + nBlockXSize - 1) / nBlockXSize;
+ nBlocksPerColumn = (nYSize + nBlockYSize - 1) / nBlockYSize;
+ nBytesPerBlock = (nBlockXSize*nBlockYSize*nBitsPerPixel + 7) / 8;
+
+ nBlocks = nBlocksPerRow * nBlocksPerColumn;
+ nBlocksInCache = 0;
+ nMaxBlocksInCache = MIN(nBlocks, 2*nBlocksPerRow);
+
+ papoBlocks = (RawBlock **) calloc(sizeof(RawBlock*),nBlocks);
+
+ poLRUHead = NULL;
+ poLRUTail = NULL;
+}
+
+/************************************************************************/
+/* ~RawBlockedImage() */
+/************************************************************************/
+
+RawBlockedImage::~RawBlockedImage()
+
+{
+ int i;
+
+ for( i = 0; i < nBlocks; i++ )
+ {
+ if( papoBlocks[i] != NULL )
+ {
+ if( papoBlocks[i]->pabyData != NULL )
+ free( papoBlocks[i]->pabyData );
+
+ delete papoBlocks[i];
+ }
+ }
+
+ if( papoBlocks != NULL)
+ free( papoBlocks );
+
+ fclose( fp );
+
+ unlink( pszFilename ); /* wrap this? */
+
+ free( pszFilename );
+}
+
+/************************************************************************/
+/* InsertInLRUList() */
+/* */
+/* Insert this link at the beginning of the LRU list. First */
+/* removed from it's current position if it is in the list. */
+/************************************************************************/
+
+void RawBlockedImage::InsertInLRUList( RawBlock * poBlock )
+
+{
+/* -------------------------------------------------------------------- */
+/* Remove from list, if it is currently in it. */
+/* -------------------------------------------------------------------- */
+ if( poBlock->poPrevLRU != NULL || poLRUHead == poBlock )
+ RemoveFromLRUList( poBlock );
+
+/* -------------------------------------------------------------------- */
+/* Add at the head. */
+/* -------------------------------------------------------------------- */
+ if( poLRUHead != NULL )
+ {
+ poLRUHead->poPrevLRU = poBlock;
+ }
+
+ poBlock->poNextLRU = poLRUHead;
+ poLRUHead = poBlock;
+
+ if( poLRUTail == NULL )
+ poLRUTail = poBlock;
+}
+
+/************************************************************************/
+/* RemoveFromLRUList() */
+/* */
+/* Remove this block from the LRU list, if present. */
+/************************************************************************/
+
+void RawBlockedImage::RemoveFromLRUList( RawBlock * poBlock )
+
+{
+/* -------------------------------------------------------------------- */
+/* Is it even in the list? */
+/* -------------------------------------------------------------------- */
+ if( poBlock->poPrevLRU == NULL && poLRUHead != poBlock )
+ return;
+
+/* -------------------------------------------------------------------- */
+/* Fix the link before this in the list (or head pointer). */
+/* -------------------------------------------------------------------- */
+ if( poBlock->poPrevLRU == NULL )
+ {
+ poLRUHead = poBlock->poNextLRU;
+ }
+ else
+ {
+ poBlock->poPrevLRU->poNextLRU = poBlock->poNextLRU;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Fix the link after this one, or the tail pointer. */
+/* -------------------------------------------------------------------- */
+ if( poBlock->poNextLRU == NULL )
+ {
+ poLRUTail = poBlock->poPrevLRU;
+ }
+ else
+ {
+ poBlock->poNextLRU->poPrevLRU = poBlock->poPrevLRU;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Update this link to indicate it isn't in the list now. */
+/* -------------------------------------------------------------------- */
+ poBlock->poPrevLRU = poBlock->poNextLRU = NULL;
+}
+
+
+/************************************************************************/
+/* FlushBlock() */
+/************************************************************************/
+
+void RawBlockedImage::FlushBlock( RawBlock * poBlock )
+
+{
+/* -------------------------------------------------------------------- */
+/* If we aren't given a particular block to flush, then select */
+/* the lest recently used one from the LRU list. */
+/* -------------------------------------------------------------------- */
+ if( poBlock == NULL )
+ {
+ if( poLRUTail == NULL )
+ return;
+
+ poBlock = poLRUTail;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Remove from the LRU list. */
+/* -------------------------------------------------------------------- */
+ RemoveFromLRUList( poBlock );
+
+/* -------------------------------------------------------------------- */
+/* If the block has no data, then it doesn't really need to be */
+/* flushed. */
+/* -------------------------------------------------------------------- */
+ if( poBlock->pabyData == NULL )
+ return;
+
+/* -------------------------------------------------------------------- */
+/* Is this block dirty? If so we will have to try and save it. */
+/* -------------------------------------------------------------------- */
+ if( poBlock->nDirty )
+ {
+ if( poBlock->nPositionInFile == -1 )
+ poBlock->nPositionInFile = nCurFileSize;
+
+ nCurFileSize += nBytesPerBlock;
+ if( fseek( fp, poBlock->nPositionInFile, SEEK_SET ) != 0 )
+ {
+ fprintf( stderr,
+ "Seek to %d in overview spill file %s failed.\n",
+ poBlock->nPositionInFile, pszFilename );
+ exit( 1 );
+ }
+
+ if( fwrite( poBlock->pabyData, 1, nBytesPerBlock, fp )
+ != (size_t) nBytesPerBlock )
+ {
+ fprintf( stderr,
+ "Write of %d bytes at %d in overview spill file %s.\n"
+ "Is the disk full?\n",
+ nBytesPerBlock, poBlock->nPositionInFile, pszFilename );
+ exit( 1 );
+ }
+
+ poBlock->nDirty = FALSE;
+ }
+
+/* -------------------------------------------------------------------- */
+/* Free the data block, and decrement used count. */
+/* -------------------------------------------------------------------- */
+ nBlocksInCache--;
+ if( poBlock->pabyData != NULL )
+ free( poBlock->pabyData );
+ poBlock->pabyData = NULL;
+}
+
+
+/************************************************************************/
+/* GetRawBlock() */
+/************************************************************************/
+
+RawBlock *RawBlockedImage::GetRawBlock( int nXOff, int nYOff )
+
+{
+ int nBlock = nXOff + nYOff * nBlocksPerRow;
+ RawBlock *poBlock;
+
+ assert( nBlock >= 0 && nBlock < nBlocks );
+
+/* -------------------------------------------------------------------- */
+/* Is this the first request? If so, create the block object, */
+/* initialize the data memory, and return it. */
+/* -------------------------------------------------------------------- */
+ poBlock = papoBlocks[nBlock];
+ if( poBlock == NULL )
+ {
+ poBlock = papoBlocks[nBlock] = new RawBlock;
+ poBlock->nDirty = FALSE;
+ poBlock->poPrevLRU = poBlock->poNextLRU = NULL;
+ poBlock->nPositionInFile = -1;
+ poBlock->pabyData = (unsigned char *) calloc(1,nBytesPerBlock);
+ nBlocksInCache++;
+
+ if( poBlock->pabyData == NULL )
+ {
+ fprintf( stderr,
+ "RawBlockedImage::GetRawBlock() - out of memory\n" );
+ exit( 1 );
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Does this block need to be read off disk? */
+/* -------------------------------------------------------------------- */
+ else if( poBlock->nPositionInFile >= 0 && poBlock->pabyData == NULL )
+ {
+ nBlocksInCache++;
+ poBlock->pabyData = (unsigned char *) calloc(1,nBytesPerBlock);
+ fseek( fp, poBlock->nPositionInFile, SEEK_SET );
+ fread( poBlock->pabyData, nBytesPerBlock, 1, fp );
+ }
+
+/* -------------------------------------------------------------------- */
+/* Does the data need to be allocated? */
+/* -------------------------------------------------------------------- */
+ else if( poBlock->pabyData == NULL )
+ {
+ poBlock->pabyData = (unsigned char *) calloc(1,nBytesPerBlock);
+ if( poBlock->pabyData == NULL )
+ {
+ fprintf( stderr,
+ "RawBlockedImage::GetRawBlock() - out of memory\n" );
+ exit( 1 );
+ }
+ }
+
+/* -------------------------------------------------------------------- */
+/* Push on the LRU stack, or pop it back to the top. */
+/* -------------------------------------------------------------------- */
+ InsertInLRUList( poBlock );
+
+/* -------------------------------------------------------------------- */
+/* If we have exceeded our self imposed caching limit, flush */
+/* one block. */
+/* -------------------------------------------------------------------- */
+ if( nBlocksInCache > nMaxBlocksInCache )
+ FlushBlock( NULL );
+
+ return( poBlock );
+}
+
+/************************************************************************/
+/* GetTile() */
+/************************************************************************/
+
+unsigned char *RawBlockedImage::GetTile( int nXOff, int nYOff )
+
+{
+ RawBlock *poBlock;
+
+ poBlock = GetRawBlock(nXOff,nYOff);
+ if( poBlock != NULL )
+ return poBlock->pabyData;
+ else
+ return NULL;
+}
+
+/************************************************************************/
+/* GetTileForUpdate() */
+/************************************************************************/
+
+unsigned char *RawBlockedImage::GetTileForUpdate( int nXOff, int nYOff )
+
+{
+ RawBlock *poBlock;
+
+ poBlock = GetRawBlock(nXOff,nYOff);
+ if( poBlock != NULL )
+ {
+ poBlock->nDirty = TRUE;
+
+ return poBlock->pabyData;
+ }
+ else
+ return NULL;
+}