Blame contrib/addtiffo/tif_ovrcache.c

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