roentgen b75cab
/******************************************************************************
roentgen b75cab
 * tif_overview.c,v 1.9 2005/05/25 09:03:16 dron Exp
roentgen b75cab
 *
roentgen b75cab
 * Project:  TIFF Overview Builder
roentgen b75cab
 * Purpose:  Library function for building overviews in a TIFF file.
roentgen b75cab
 * Author:   Frank Warmerdam, warmerdam@pobox.com
roentgen b75cab
 *
roentgen b75cab
 * Notes:
roentgen b75cab
 *  o Currently only images with bits_per_sample of a multiple of eight
roentgen b75cab
 *    will work.
roentgen b75cab
 *
roentgen b75cab
 *  o The downsampler currently just takes the top left pixel from the
roentgen b75cab
 *    source rectangle.  Eventually sampling options of averaging, mode, and
roentgen b75cab
 *    ``center pixel'' should be offered.
roentgen b75cab
 *
roentgen b75cab
 *  o The code will attempt to use the same kind of compression,
roentgen b75cab
 *    photometric interpretation, and organization as the source image, but
roentgen b75cab
 *    it doesn't copy geotiff tags to the reduced resolution images.
roentgen b75cab
 *
roentgen b75cab
 *  o Reduced resolution overviews for multi-sample files will currently
roentgen b75cab
 *    always be generated as PLANARCONFIG_SEPARATE.  This could be fixed
roentgen b75cab
 *    reasonable easily if needed to improve compatibility with other
roentgen b75cab
 *    packages.  Many don't properly support PLANARCONFIG_SEPARATE. 
roentgen b75cab
 * 
roentgen b75cab
 ******************************************************************************
roentgen b75cab
 * Copyright (c) 1999, Frank Warmerdam
roentgen b75cab
 *
roentgen b75cab
 * Permission is hereby granted, free of charge, to any person obtaining a
roentgen b75cab
 * copy of this software and associated documentation files (the "Software"),
roentgen b75cab
 * to deal in the Software without restriction, including without limitation
roentgen b75cab
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
roentgen b75cab
 * and/or sell copies of the Software, and to permit persons to whom the
roentgen b75cab
 * Software is furnished to do so, subject to the following conditions:
roentgen b75cab
 *
roentgen b75cab
 * The above copyright notice and this permission notice shall be included
roentgen b75cab
 * in all copies or substantial portions of the Software.
roentgen b75cab
 *
roentgen b75cab
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
roentgen b75cab
 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
roentgen b75cab
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
roentgen b75cab
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
roentgen b75cab
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
roentgen b75cab
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
roentgen b75cab
 * DEALINGS IN THE SOFTWARE.
roentgen b75cab
 ******************************************************************************
roentgen b75cab
 */
roentgen b75cab
roentgen b75cab
/* TODO: update notes in header above */
roentgen b75cab
roentgen b75cab
#include <stdio.h></stdio.h>
roentgen b75cab
#include <assert.h></assert.h>
roentgen b75cab
#include <stdlib.h></stdlib.h>
roentgen b75cab
#include <string.h></string.h>
roentgen b75cab
roentgen b75cab
#include "tiffio.h"
roentgen b75cab
#include "tif_ovrcache.h"
roentgen b75cab
roentgen b75cab
#ifndef FALSE
roentgen b75cab
#  define FALSE 0
roentgen b75cab
#  define TRUE 1
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
#ifndef MAX
roentgen b75cab
#  define MIN(a,b)      ((a
roentgen b75cab
#  define MAX(a,b)      ((a>b) ? a : b)
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
void TIFFBuildOverviews( TIFF *, int, int *, int, const char *,
roentgen b75cab
                         int (*)(double,void*), void * );
roentgen b75cab
roentgen b75cab
/************************************************************************/
roentgen b75cab
/*                         TIFF_WriteOverview()                         */
roentgen b75cab
/*                                                                      */
roentgen b75cab
/*      Create a new directory, without any image data for an overview. */
roentgen b75cab
/*      Returns offset of newly created overview directory, but the     */
roentgen b75cab
/*      current directory is reset to be the one in used when this      */
roentgen b75cab
/*      function is called.                                             */
roentgen b75cab
/************************************************************************/
roentgen b75cab
roentgen b75cab
uint32 TIFF_WriteOverview( TIFF *hTIFF, uint32 nXSize, uint32 nYSize,
roentgen b75cab
                           int nBitsPerPixel, int nPlanarConfig, int nSamples, 
roentgen b75cab
                           int nBlockXSize, int nBlockYSize,
roentgen b75cab
                           int bTiled, int nCompressFlag, int nPhotometric,
roentgen b75cab
                           int nSampleFormat,
roentgen b75cab
                           unsigned short *panRed,
roentgen b75cab
                           unsigned short *panGreen,
roentgen b75cab
                           unsigned short *panBlue,
roentgen b75cab
                           int bUseSubIFDs,
roentgen b75cab
                           int nHorSubsampling, int nVerSubsampling )
roentgen b75cab
roentgen b75cab
{
roentgen b75cab
    toff_t	nBaseDirOffset;
roentgen b75cab
    toff_t	nOffset;
roentgen b75cab
roentgen b75cab
    (void) bUseSubIFDs;
roentgen b75cab
roentgen b75cab
    nBaseDirOffset = TIFFCurrentDirOffset( hTIFF );
roentgen b75cab
roentgen b75cab
    TIFFCreateDirectory( hTIFF );
roentgen b75cab
roentgen b75cab
/* -------------------------------------------------------------------- */
roentgen b75cab
/*      Setup TIFF fields.                                              */
roentgen b75cab
/* -------------------------------------------------------------------- */
roentgen b75cab
    TIFFSetField( hTIFF, TIFFTAG_IMAGEWIDTH, nXSize );
roentgen b75cab
    TIFFSetField( hTIFF, TIFFTAG_IMAGELENGTH, nYSize );
roentgen b75cab
    if( nSamples == 1 )
roentgen b75cab
        TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG );
roentgen b75cab
    else
roentgen b75cab
        TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG, nPlanarConfig );
roentgen b75cab
roentgen b75cab
    TIFFSetField( hTIFF, TIFFTAG_BITSPERSAMPLE, nBitsPerPixel );
roentgen b75cab
    TIFFSetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, nSamples );
roentgen b75cab
    TIFFSetField( hTIFF, TIFFTAG_COMPRESSION, nCompressFlag );
roentgen b75cab
    TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, nPhotometric );
roentgen b75cab
    TIFFSetField( hTIFF, TIFFTAG_SAMPLEFORMAT, nSampleFormat );
roentgen b75cab
roentgen b75cab
    if( bTiled )
roentgen b75cab
    {
roentgen b75cab
        TIFFSetField( hTIFF, TIFFTAG_TILEWIDTH, nBlockXSize );
roentgen b75cab
        TIFFSetField( hTIFF, TIFFTAG_TILELENGTH, nBlockYSize );
roentgen b75cab
    }
roentgen b75cab
    else
roentgen b75cab
        TIFFSetField( hTIFF, TIFFTAG_ROWSPERSTRIP, nBlockYSize );
roentgen b75cab
roentgen b75cab
    TIFFSetField( hTIFF, TIFFTAG_SUBFILETYPE, FILETYPE_REDUCEDIMAGE );
roentgen b75cab
roentgen b75cab
    if( nPhotometric == PHOTOMETRIC_YCBCR || nPhotometric == PHOTOMETRIC_ITULAB )
roentgen b75cab
    {
roentgen b75cab
        TIFFSetField( hTIFF, TIFFTAG_YCBCRSUBSAMPLING, nHorSubsampling, nVerSubsampling);
roentgen b75cab
        /* TODO: also write YCbCrPositioning and YCbCrCoefficients tag identical to source IFD */
roentgen b75cab
    }
roentgen b75cab
    /* TODO: add command-line parameter for selecting jpeg compression quality
roentgen b75cab
     * that gets ignored when compression isn't jpeg */
roentgen b75cab
roentgen b75cab
/* -------------------------------------------------------------------- */
roentgen b75cab
/*	Write color table if one is present.				*/
roentgen b75cab
/* -------------------------------------------------------------------- */
roentgen b75cab
    if( panRed != NULL )
roentgen b75cab
    {
roentgen b75cab
        TIFFSetField( hTIFF, TIFFTAG_COLORMAP, panRed, panGreen, panBlue );
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
/* -------------------------------------------------------------------- */
roentgen b75cab
/*      Write directory, and return byte offset.                        */
roentgen b75cab
/* -------------------------------------------------------------------- */
roentgen b75cab
    if( TIFFWriteCheck( hTIFF, bTiled, "TIFFBuildOverviews" ) == 0 )
roentgen b75cab
        return 0;
roentgen b75cab
roentgen b75cab
    TIFFWriteDirectory( hTIFF );
roentgen b75cab
    TIFFSetDirectory( hTIFF, (tdir_t) (TIFFNumberOfDirectories(hTIFF)-1) );
roentgen b75cab
roentgen b75cab
    nOffset = TIFFCurrentDirOffset( hTIFF );
roentgen b75cab
roentgen b75cab
    TIFFSetSubDirectory( hTIFF, nBaseDirOffset );
roentgen b75cab
roentgen b75cab
    return nOffset;
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/************************************************************************/
roentgen b75cab
/*                       TIFF_GetSourceSamples()                        */
roentgen b75cab
/************************************************************************/
roentgen b75cab
roentgen b75cab
static void 
roentgen b75cab
TIFF_GetSourceSamples( double * padfSamples, unsigned char *pabySrc, 
roentgen b75cab
                       int nPixelBytes, int nSampleFormat, 
roentgen b75cab
                       uint32 nXSize, uint32 nYSize, 
roentgen b75cab
                       int nPixelOffset, int nLineOffset )
roentgen b75cab
{
roentgen b75cab
    uint32  iXOff, iYOff;
roentgen b75cab
    int     iSample;
roentgen b75cab
roentgen b75cab
    iSample = 0;
roentgen b75cab
roentgen b75cab
    for( iYOff = 0; iYOff < nYSize; iYOff++ )
roentgen b75cab
    {
roentgen b75cab
        for( iXOff = 0; iXOff < nXSize; iXOff++ )
roentgen b75cab
        {
roentgen b75cab
            unsigned char *pabyData;
roentgen b75cab
roentgen b75cab
            pabyData = pabySrc + iYOff * nLineOffset + iXOff * nPixelOffset;
roentgen b75cab
roentgen b75cab
            if( nSampleFormat == SAMPLEFORMAT_UINT && nPixelBytes == 1 )
roentgen b75cab
            {
roentgen b75cab
                padfSamples[iSample++] = *pabyData;
roentgen b75cab
            }
roentgen b75cab
            else if( nSampleFormat == SAMPLEFORMAT_UINT && nPixelBytes == 2 )
roentgen b75cab
            {
roentgen b75cab
                padfSamples[iSample++] = ((uint16 *) pabyData)[0];
roentgen b75cab
            }
roentgen b75cab
            else if( nSampleFormat == SAMPLEFORMAT_UINT && nPixelBytes == 4 )
roentgen b75cab
            {
roentgen b75cab
                padfSamples[iSample++] = ((uint32 *) pabyData)[0];
roentgen b75cab
            }
roentgen b75cab
            else if( nSampleFormat == SAMPLEFORMAT_INT && nPixelBytes == 2 )
roentgen b75cab
            {
roentgen b75cab
                padfSamples[iSample++] = ((int16 *) pabyData)[0];
roentgen b75cab
            }
roentgen b75cab
            else if( nSampleFormat == SAMPLEFORMAT_INT && nPixelBytes == 32 )
roentgen b75cab
            {
roentgen b75cab
                padfSamples[iSample++] = ((int32 *) pabyData)[0];
roentgen b75cab
            }
roentgen b75cab
            else if( nSampleFormat == SAMPLEFORMAT_IEEEFP && nPixelBytes == 4 )
roentgen b75cab
            {
roentgen b75cab
                padfSamples[iSample++] = ((float *) pabyData)[0];
roentgen b75cab
            }
roentgen b75cab
            else if( nSampleFormat == SAMPLEFORMAT_IEEEFP && nPixelBytes == 8 )
roentgen b75cab
            {
roentgen b75cab
                padfSamples[iSample++] = ((double *) pabyData)[0];
roentgen b75cab
            }
roentgen b75cab
        }
roentgen b75cab
    }
roentgen b75cab
} 
roentgen b75cab
roentgen b75cab
/************************************************************************/
roentgen b75cab
/*                           TIFF_SetSample()                           */
roentgen b75cab
/************************************************************************/
roentgen b75cab
roentgen b75cab
static void 
roentgen b75cab
TIFF_SetSample( unsigned char * pabyData, int nPixelBytes, int nSampleFormat, 
roentgen b75cab
                double dfValue )
roentgen b75cab
roentgen b75cab
{
roentgen b75cab
    if( nSampleFormat == SAMPLEFORMAT_UINT && nPixelBytes == 1 )
roentgen b75cab
    {
roentgen b75cab
        *pabyData = (unsigned char) MAX(0,MIN(255,dfValue));
roentgen b75cab
    }
roentgen b75cab
    else if( nSampleFormat == SAMPLEFORMAT_UINT && nPixelBytes == 2 )
roentgen b75cab
    {
roentgen b75cab
        *((uint16 *)pabyData) = (uint16) MAX(0,MIN(65535,dfValue));
roentgen b75cab
    }
roentgen b75cab
    else if( nSampleFormat == SAMPLEFORMAT_UINT && nPixelBytes == 4 )
roentgen b75cab
    {
roentgen b75cab
        *((uint32 *)pabyData) = (uint32) dfValue;
roentgen b75cab
    }
roentgen b75cab
    else if( nSampleFormat == SAMPLEFORMAT_INT && nPixelBytes == 2 )
roentgen b75cab
    {
roentgen b75cab
        *((int16 *)pabyData) = (int16) MAX(-32768,MIN(32767,dfValue));
roentgen b75cab
    }
roentgen b75cab
    else if( nSampleFormat == SAMPLEFORMAT_INT && nPixelBytes == 32 )
roentgen b75cab
    {
roentgen b75cab
        *((int32 *)pabyData) = (int32) dfValue;
roentgen b75cab
    }
roentgen b75cab
    else if( nSampleFormat == SAMPLEFORMAT_IEEEFP && nPixelBytes == 4 )
roentgen b75cab
    {
roentgen b75cab
        *((float *)pabyData) = (float) dfValue;
roentgen b75cab
    }
roentgen b75cab
    else if( nSampleFormat == SAMPLEFORMAT_IEEEFP && nPixelBytes == 8 )
roentgen b75cab
    {
roentgen b75cab
        *((double *)pabyData) = dfValue;
roentgen b75cab
    }
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/************************************************************************/
roentgen b75cab
/*                          TIFF_DownSample()                           */
roentgen b75cab
/*                                                                      */
roentgen b75cab
/*      Down sample a tile of full res data into a window of a tile     */
roentgen b75cab
/*      of downsampled data.                                            */
roentgen b75cab
/************************************************************************/
roentgen b75cab
roentgen b75cab
static
roentgen b75cab
void TIFF_DownSample( unsigned char *pabySrcTile,
roentgen b75cab
                      uint32 nBlockXSize, uint32 nBlockYSize,
roentgen b75cab
                      int nPixelSkewBits, int nBitsPerPixel,
roentgen b75cab
                      unsigned char * pabyOTile,
roentgen b75cab
                      uint32 nOBlockXSize, uint32 nOBlockYSize,
roentgen b75cab
                      uint32 nTXOff, uint32 nTYOff, int nOMult,
roentgen b75cab
                      int nSampleFormat, const char * pszResampling )
roentgen b75cab
roentgen b75cab
{
roentgen b75cab
    uint32	i, j;
roentgen b75cab
    int         k, nPixelBytes = (nBitsPerPixel) / 8;
roentgen b75cab
    int		nPixelGroupBytes = (nBitsPerPixel+nPixelSkewBits)/8;
roentgen b75cab
    unsigned char *pabySrc, *pabyDst;
roentgen b75cab
    double      *padfSamples;
roentgen b75cab
roentgen b75cab
    assert( nBitsPerPixel >= 8 );
roentgen b75cab
roentgen b75cab
    padfSamples = (double *) malloc(sizeof(double) * nOMult * nOMult);
roentgen b75cab
roentgen b75cab
/* ==================================================================== */
roentgen b75cab
/*      Loop over scanline chunks to process, establishing where the    */
roentgen b75cab
/*      data is going.                                                  */
roentgen b75cab
/* ==================================================================== */
roentgen b75cab
    for( j = 0; j*nOMult < nBlockYSize; j++ )
roentgen b75cab
    {
roentgen b75cab
        if( j + nTYOff >= nOBlockYSize )
roentgen b75cab
            break;
roentgen b75cab
roentgen b75cab
        pabyDst = pabyOTile + ((j+nTYOff)*nOBlockXSize + nTXOff)
roentgen b75cab
            * nPixelBytes * nPixelGroupBytes;
roentgen b75cab
roentgen b75cab
/* -------------------------------------------------------------------- */
roentgen b75cab
/*      Handler nearest resampling ... we don't even care about the     */
roentgen b75cab
/*      data type, we just do a bytewise copy.                          */
roentgen b75cab
/* -------------------------------------------------------------------- */
roentgen b75cab
        if( strncmp(pszResampling,"nearest",4) == 0
roentgen b75cab
            || strncmp(pszResampling,"NEAR",4) == 0 )
roentgen b75cab
        {
roentgen b75cab
            pabySrc = pabySrcTile + j*nOMult*nBlockXSize * nPixelGroupBytes;
roentgen b75cab
roentgen b75cab
            for( i = 0; i*nOMult < nBlockXSize; i++ )
roentgen b75cab
            {
roentgen b75cab
                if( i + nTXOff >= nOBlockXSize )
roentgen b75cab
                    break;
roentgen b75cab
            
roentgen b75cab
                /*
roentgen b75cab
                 * For now use simple subsampling, from the top left corner
roentgen b75cab
                 * of the source block of pixels.
roentgen b75cab
                 */
roentgen b75cab
roentgen b75cab
                for( k = 0; k < nPixelBytes; k++ )
roentgen b75cab
                    pabyDst[k] = pabySrc[k];
roentgen b75cab
roentgen b75cab
                pabyDst += nPixelBytes * nPixelGroupBytes;
roentgen b75cab
                pabySrc += nOMult * nPixelGroupBytes;
roentgen b75cab
            }
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
/* -------------------------------------------------------------------- */
roentgen b75cab
/*      Handle the case of averaging.  For this we also have to         */
roentgen b75cab
/*      handle each sample format we are concerned with.                */
roentgen b75cab
/* -------------------------------------------------------------------- */
roentgen b75cab
        else if( strncmp(pszResampling,"averag",6) == 0
roentgen b75cab
                 || strncmp(pszResampling,"AVERAG",6) == 0 )
roentgen b75cab
        {
roentgen b75cab
            pabySrc = pabySrcTile + j*nOMult*nBlockXSize * nPixelGroupBytes;
roentgen b75cab
roentgen b75cab
            for( i = 0; i*nOMult < nBlockXSize; i++ )
roentgen b75cab
            {
roentgen b75cab
                double   dfTotal;
roentgen b75cab
                uint32   nXSize, nYSize, iSample;
roentgen b75cab
roentgen b75cab
                if( i + nTXOff >= nOBlockXSize )
roentgen b75cab
                    break;
roentgen b75cab
roentgen b75cab
                nXSize = MIN((uint32)nOMult,nBlockXSize-i);
roentgen b75cab
                nYSize = MIN((uint32)nOMult,nBlockYSize-j);
roentgen b75cab
roentgen b75cab
                TIFF_GetSourceSamples( padfSamples, pabySrc,
roentgen b75cab
                                       nPixelBytes, nSampleFormat,
roentgen b75cab
                                       nXSize, nYSize,
roentgen b75cab
                                       nPixelGroupBytes,
roentgen b75cab
                                       nPixelGroupBytes * nBlockXSize );
roentgen b75cab
roentgen b75cab
                dfTotal = 0;
roentgen b75cab
                for( iSample = 0; iSample < nXSize*nYSize; iSample++ )
roentgen b75cab
                {
roentgen b75cab
                    dfTotal += padfSamples[iSample];
roentgen b75cab
                }
roentgen b75cab
roentgen b75cab
                TIFF_SetSample( pabyDst, nPixelBytes, nSampleFormat, 
roentgen b75cab
                                dfTotal / (nXSize*nYSize) );
roentgen b75cab
roentgen b75cab
                pabySrc += nOMult * nPixelGroupBytes;
roentgen b75cab
                pabyDst += nPixelBytes;
roentgen b75cab
            }
roentgen b75cab
        }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
    free( padfSamples );
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/************************************************************************/
roentgen b75cab
/*                     TIFF_DownSample_Subsampled()                     */
roentgen b75cab
/************************************************************************/
roentgen b75cab
static
roentgen b75cab
void TIFF_DownSample_Subsampled( unsigned char *pabySrcTile, int nSample,
roentgen b75cab
                                 uint32 nBlockXSize, uint32 nBlockYSize,
roentgen b75cab
                                 unsigned char * pabyOTile,
roentgen b75cab
                                 uint32 nOBlockXSize, uint32 nOBlockYSize,
roentgen b75cab
                                 uint32 nTXOff, uint32 nTYOff, int nOMult,
roentgen b75cab
                                 const char *pszResampling,
roentgen b75cab
                                 int nHorSubsampling, int nVerSubsampling )
roentgen b75cab
{
roentgen b75cab
    /* TODO: test with variety of subsampling values, and incovinient tile/strip sizes */
roentgen b75cab
    int nSampleBlockSize;
roentgen b75cab
    int nSourceSampleRowSize;
roentgen b75cab
    int nDestSampleRowSize;
roentgen b75cab
    uint32  nSourceX, nSourceY;
roentgen b75cab
    uint32  nSourceXSec, nSourceYSec;
roentgen b75cab
    uint32  nSourceXSecEnd, nSourceYSecEnd;
roentgen b75cab
    uint32  nDestX, nDestY;
roentgen b75cab
    int nSampleOffsetInSampleBlock;
roentgen b75cab
    unsigned int nCummulator;
roentgen b75cab
    unsigned int nCummulatorCount;
roentgen b75cab
roentgen b75cab
    nSampleBlockSize = nHorSubsampling * nVerSubsampling + 2;
roentgen b75cab
    nSourceSampleRowSize = 
roentgen b75cab
        ( ( nBlockXSize + nHorSubsampling - 1 ) / nHorSubsampling ) * nSampleBlockSize;
roentgen b75cab
    nDestSampleRowSize = 
roentgen b75cab
        ( ( nOBlockXSize + nHorSubsampling - 1 ) / nHorSubsampling ) * nSampleBlockSize;
roentgen b75cab
roentgen b75cab
    if( strncmp(pszResampling,"nearest",4) == 0
roentgen b75cab
        || strncmp(pszResampling,"NEAR",4) == 0 )
roentgen b75cab
    {
roentgen b75cab
    	if( nSample == 0 )
roentgen b75cab
        {
roentgen b75cab
            for( nSourceY = 0, nDestY = nTYOff; 
roentgen b75cab
                 nSourceY < nBlockYSize; 
roentgen b75cab
                 nSourceY += nOMult, nDestY ++)
roentgen b75cab
            {
roentgen b75cab
                if( nDestY >= nOBlockYSize )
roentgen b75cab
                    break;
roentgen b75cab
roentgen b75cab
                for( nSourceX = 0, nDestX = nTXOff; 
roentgen b75cab
                     nSourceX < nBlockXSize; 
roentgen b75cab
                     nSourceX += nOMult, nDestX ++)
roentgen b75cab
                {
roentgen b75cab
                    if( nDestX >= nOBlockXSize )
roentgen b75cab
                        break;
roentgen b75cab
roentgen b75cab
                    * ( pabyOTile + ( nDestY / nVerSubsampling ) * nDestSampleRowSize
roentgen b75cab
                        + ( nDestY % nVerSubsampling ) * nHorSubsampling
roentgen b75cab
                        + ( nDestX / nHorSubsampling ) * nSampleBlockSize
roentgen b75cab
                        + ( nDestX % nHorSubsampling ) ) =
roentgen b75cab
                        * ( pabySrcTile + ( nSourceY / nVerSubsampling ) * nSourceSampleRowSize
roentgen b75cab
                            + ( nSourceY % nVerSubsampling ) * nHorSubsampling
roentgen b75cab
                            + ( nSourceX / nHorSubsampling ) * nSampleBlockSize
roentgen b75cab
                            + ( nSourceX % nHorSubsampling ) );
roentgen b75cab
                }
roentgen b75cab
            }
roentgen b75cab
        }
roentgen b75cab
        else
roentgen b75cab
        {
roentgen b75cab
            nSampleOffsetInSampleBlock = nHorSubsampling * nVerSubsampling + nSample - 1;
roentgen b75cab
            for( nSourceY = 0, nDestY = ( nTYOff / nVerSubsampling ); 
roentgen b75cab
                 nSourceY < ( nBlockYSize / nVerSubsampling );
roentgen b75cab
                 nSourceY += nOMult, nDestY ++)
roentgen b75cab
            {
roentgen b75cab
                if( nDestY*nVerSubsampling >= nOBlockYSize )
roentgen b75cab
                    break;
roentgen b75cab
roentgen b75cab
            	for( nSourceX = 0, nDestX = ( nTXOff / nHorSubsampling ); 
roentgen b75cab
                     nSourceX < ( nBlockXSize / nHorSubsampling );
roentgen b75cab
                     nSourceX += nOMult, nDestX ++)
roentgen b75cab
                {
roentgen b75cab
                    if( nDestX*nHorSubsampling >= nOBlockXSize )
roentgen b75cab
                        break;
roentgen b75cab
roentgen b75cab
                    * ( pabyOTile + nDestY * nDestSampleRowSize
roentgen b75cab
                        + nDestX * nSampleBlockSize
roentgen b75cab
                        + nSampleOffsetInSampleBlock ) =
roentgen b75cab
                    	* ( pabySrcTile + nSourceY * nSourceSampleRowSize
roentgen b75cab
                            + nSourceX * nSampleBlockSize
roentgen b75cab
                            + nSampleOffsetInSampleBlock );
roentgen b75cab
                }
roentgen b75cab
            }
roentgen b75cab
        }
roentgen b75cab
    }
roentgen b75cab
    else if( strncmp(pszResampling,"averag",6) == 0
roentgen b75cab
             || strncmp(pszResampling,"AVERAG",6) == 0 )
roentgen b75cab
    {
roentgen b75cab
    	if( nSample == 0 )
roentgen b75cab
        {
roentgen b75cab
            for( nSourceY = 0, nDestY = nTYOff; nSourceY < nBlockYSize; nSourceY += nOMult, nDestY ++)
roentgen b75cab
            {
roentgen b75cab
                if( nDestY >= nOBlockYSize )
roentgen b75cab
                    break;
roentgen b75cab
roentgen b75cab
                for( nSourceX = 0, nDestX = nTXOff; nSourceX < nBlockXSize; nSourceX += nOMult, nDestX ++)
roentgen b75cab
                {
roentgen b75cab
                    if( nDestX >= nOBlockXSize )
roentgen b75cab
                        break;
roentgen b75cab
roentgen b75cab
                    nSourceXSecEnd = nSourceX + nOMult;
roentgen b75cab
                    if( nSourceXSecEnd > nBlockXSize )
roentgen b75cab
                        nSourceXSecEnd = nBlockXSize;
roentgen b75cab
                    nSourceYSecEnd = nSourceY + nOMult;
roentgen b75cab
                    if( nSourceYSecEnd > nBlockYSize )
roentgen b75cab
                        nSourceYSecEnd = nBlockYSize;
roentgen b75cab
                    nCummulator = 0;
roentgen b75cab
                    for( nSourceYSec = nSourceY; nSourceYSec < nSourceYSecEnd; nSourceYSec ++)
roentgen b75cab
                    {
roentgen b75cab
                        for( nSourceXSec = nSourceX; nSourceXSec < nSourceXSecEnd; nSourceXSec ++)
roentgen b75cab
                        {
roentgen b75cab
                            nCummulator += * ( pabySrcTile + ( nSourceYSec / nVerSubsampling ) * nSourceSampleRowSize
roentgen b75cab
                                               + ( nSourceYSec % nVerSubsampling ) * nHorSubsampling
roentgen b75cab
                                               + ( nSourceXSec / nHorSubsampling ) * nSampleBlockSize
roentgen b75cab
                                               + ( nSourceXSec % nHorSubsampling ) );
roentgen b75cab
                        }
roentgen b75cab
                    }
roentgen b75cab
                    nCummulatorCount = ( nSourceXSecEnd - nSourceX ) * ( nSourceYSecEnd - nSourceY );
roentgen b75cab
                    * ( pabyOTile + ( nDestY / nVerSubsampling ) * nDestSampleRowSize
roentgen b75cab
                        + ( nDestY % nVerSubsampling ) * nHorSubsampling
roentgen b75cab
                        + ( nDestX / nHorSubsampling ) * nSampleBlockSize
roentgen b75cab
                        + ( nDestX % nHorSubsampling ) ) =
roentgen b75cab
                        ( ( nCummulator + ( nCummulatorCount >> 1 ) ) / nCummulatorCount );
roentgen b75cab
                }
roentgen b75cab
            }
roentgen b75cab
        }
roentgen b75cab
        else
roentgen b75cab
        {
roentgen b75cab
            nSampleOffsetInSampleBlock = nHorSubsampling * nVerSubsampling + nSample - 1;
roentgen b75cab
            for( nSourceY = 0, nDestY = ( nTYOff / nVerSubsampling ); nSourceY < ( nBlockYSize / nVerSubsampling );
roentgen b75cab
                 nSourceY += nOMult, nDestY ++)
roentgen b75cab
            {
roentgen b75cab
                if( nDestY*nVerSubsampling >= nOBlockYSize )
roentgen b75cab
                    break;
roentgen b75cab
roentgen b75cab
                for( nSourceX = 0, nDestX = ( nTXOff / nHorSubsampling ); nSourceX < ( nBlockXSize / nHorSubsampling );
roentgen b75cab
                     nSourceX += nOMult, nDestX ++)
roentgen b75cab
                {
roentgen b75cab
                    if( nDestX*nHorSubsampling >= nOBlockXSize )
roentgen b75cab
                        break;
roentgen b75cab
roentgen b75cab
                    nSourceXSecEnd = nSourceX + nOMult;
roentgen b75cab
                    if( nSourceXSecEnd > ( nBlockXSize / nHorSubsampling ) )
roentgen b75cab
                        nSourceXSecEnd = ( nBlockXSize / nHorSubsampling );
roentgen b75cab
                    nSourceYSecEnd = nSourceY + nOMult;
roentgen b75cab
                    if( nSourceYSecEnd > ( nBlockYSize / nVerSubsampling ) )
roentgen b75cab
                        nSourceYSecEnd = ( nBlockYSize / nVerSubsampling );
roentgen b75cab
                    nCummulator = 0;
roentgen b75cab
                    for( nSourceYSec = nSourceY; nSourceYSec < nSourceYSecEnd; nSourceYSec ++)
roentgen b75cab
                    {
roentgen b75cab
                        for( nSourceXSec = nSourceX; nSourceXSec < nSourceXSecEnd; nSourceXSec ++)
roentgen b75cab
                        {
roentgen b75cab
                            nCummulator += * ( pabySrcTile + nSourceYSec * nSourceSampleRowSize
roentgen b75cab
                                               + nSourceXSec * nSampleBlockSize
roentgen b75cab
                                               + nSampleOffsetInSampleBlock );
roentgen b75cab
                        }
roentgen b75cab
                    }
roentgen b75cab
                    nCummulatorCount = ( nSourceXSecEnd - nSourceX ) * ( nSourceYSecEnd - nSourceY );
roentgen b75cab
                    * ( pabyOTile + nDestY * nDestSampleRowSize
roentgen b75cab
                        + nDestX * nSampleBlockSize
roentgen b75cab
                        + nSampleOffsetInSampleBlock ) =
roentgen b75cab
                        ( ( nCummulator + ( nCummulatorCount >> 1 ) ) / nCummulatorCount );
roentgen b75cab
                }
roentgen b75cab
            }
roentgen b75cab
        }
roentgen b75cab
    }
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/************************************************************************/
roentgen b75cab
/*                      TIFF_ProcessFullResBlock()                      */
roentgen b75cab
/*                                                                      */
roentgen b75cab
/*      Process one block of full res data, downsampling into each      */
roentgen b75cab
/*      of the overviews.                                               */
roentgen b75cab
/************************************************************************/
roentgen b75cab
roentgen b75cab
void TIFF_ProcessFullResBlock( TIFF *hTIFF, int nPlanarConfig,
roentgen b75cab
                               int bSubsampled,
roentgen b75cab
                               int nHorSubsampling, int nVerSubsampling,
roentgen b75cab
                               int nOverviews, int * panOvList,
roentgen b75cab
                               int nBitsPerPixel,
roentgen b75cab
                               int nSamples, TIFFOvrCache ** papoRawBIs,
roentgen b75cab
                               uint32 nSXOff, uint32 nSYOff,
roentgen b75cab
                               unsigned char *pabySrcTile,
roentgen b75cab
                               uint32 nBlockXSize, uint32 nBlockYSize,
roentgen b75cab
                               int nSampleFormat, const char * pszResampling )
roentgen b75cab
    
roentgen b75cab
{
roentgen b75cab
    int		iOverview, iSample;
roentgen b75cab
roentgen b75cab
    for( iSample = 0; iSample < nSamples; iSample++ )
roentgen b75cab
    {
roentgen b75cab
        /*
roentgen b75cab
         * We have to read a tile/strip for each sample for
roentgen b75cab
         * PLANARCONFIG_SEPARATE.  Otherwise, we just read all the samples
roentgen b75cab
         * at once when handling the first sample.
roentgen b75cab
         */
roentgen b75cab
        if( nPlanarConfig == PLANARCONFIG_SEPARATE || iSample == 0 )
roentgen b75cab
        {
roentgen b75cab
            if( TIFFIsTiled(hTIFF) )
roentgen b75cab
            {
roentgen b75cab
                TIFFReadEncodedTile( hTIFF,
roentgen b75cab
                                     TIFFComputeTile(hTIFF, nSXOff, nSYOff,
roentgen b75cab
                                                     0, (tsample_t)iSample ),
roentgen b75cab
                                     pabySrcTile,
roentgen b75cab
                                     TIFFTileSize(hTIFF));
roentgen b75cab
            }
roentgen b75cab
            else
roentgen b75cab
            {
roentgen b75cab
                TIFFReadEncodedStrip( hTIFF,
roentgen b75cab
                                      TIFFComputeStrip(hTIFF, nSYOff,
roentgen b75cab
                                                       (tsample_t) iSample),
roentgen b75cab
                                      pabySrcTile,
roentgen b75cab
                                      TIFFStripSize(hTIFF) );
roentgen b75cab
            }
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
        /*        
roentgen b75cab
         * Loop over destination overview layers
roentgen b75cab
         */
roentgen b75cab
        for( iOverview = 0; iOverview < nOverviews; iOverview++ )
roentgen b75cab
        {
roentgen b75cab
            TIFFOvrCache *poRBI = papoRawBIs[iOverview];
roentgen b75cab
            unsigned char *pabyOTile;
roentgen b75cab
            uint32  nTXOff, nTYOff, nOXOff, nOYOff, nOMult;
roentgen b75cab
            uint32  nOBlockXSize = poRBI->nBlockXSize;
roentgen b75cab
            uint32  nOBlockYSize = poRBI->nBlockYSize;
roentgen b75cab
            int     nSkewBits, nSampleByteOffset; 
roentgen b75cab
roentgen b75cab
            /*
roentgen b75cab
             * Fetch the destination overview tile
roentgen b75cab
             */
roentgen b75cab
            nOMult = panOvList[iOverview];
roentgen b75cab
            nOXOff = (nSXOff/nOMult) / nOBlockXSize;
roentgen b75cab
            nOYOff = (nSYOff/nOMult) / nOBlockYSize;
roentgen b75cab
roentgen b75cab
            if( bSubsampled )
roentgen b75cab
            {
roentgen b75cab
                pabyOTile = TIFFGetOvrBlock_Subsampled( poRBI, nOXOff, nOYOff );
roentgen b75cab
roentgen b75cab
                /*
roentgen b75cab
                 * Establish the offset into this tile at which we should
roentgen b75cab
                 * start placing data.
roentgen b75cab
                 */
roentgen b75cab
                nTXOff = (nSXOff - nOXOff*nOMult*nOBlockXSize) / nOMult;
roentgen b75cab
                nTYOff = (nSYOff - nOYOff*nOMult*nOBlockYSize) / nOMult;
roentgen b75cab
roentgen b75cab
roentgen b75cab
#ifdef DBMALLOC
roentgen b75cab
                malloc_chain_check( 1 );
roentgen b75cab
#endif
roentgen b75cab
                TIFF_DownSample_Subsampled( pabySrcTile, iSample,
roentgen b75cab
                                            nBlockXSize, nBlockYSize,
roentgen b75cab
                                            pabyOTile,
roentgen b75cab
                                            poRBI->nBlockXSize, poRBI->nBlockYSize,
roentgen b75cab
                                            nTXOff, nTYOff,
roentgen b75cab
                                            nOMult, pszResampling,
roentgen b75cab
                                            nHorSubsampling, nVerSubsampling );
roentgen b75cab
#ifdef DBMALLOC
roentgen b75cab
                malloc_chain_check( 1 );
roentgen b75cab
#endif
roentgen b75cab
roentgen b75cab
            }
roentgen b75cab
            else
roentgen b75cab
            {
roentgen b75cab
roentgen b75cab
                pabyOTile = TIFFGetOvrBlock( poRBI, nOXOff, nOYOff, iSample );
roentgen b75cab
roentgen b75cab
                /*
roentgen b75cab
                 * Establish the offset into this tile at which we should
roentgen b75cab
                 * start placing data.
roentgen b75cab
                 */
roentgen b75cab
                nTXOff = (nSXOff - nOXOff*nOMult*nOBlockXSize) / nOMult;
roentgen b75cab
                nTYOff = (nSYOff - nOYOff*nOMult*nOBlockYSize) / nOMult;
roentgen b75cab
roentgen b75cab
                /*
roentgen b75cab
                 * Figure out the skew (extra space between ``our samples'') and
roentgen b75cab
                 * the byte offset to the first sample.
roentgen b75cab
                 */
roentgen b75cab
                assert( (nBitsPerPixel % 8) == 0 );
roentgen b75cab
                if( nPlanarConfig == PLANARCONFIG_SEPARATE )
roentgen b75cab
                {
roentgen b75cab
                    nSkewBits = 0;
roentgen b75cab
                    nSampleByteOffset = 0;
roentgen b75cab
                }
roentgen b75cab
                else
roentgen b75cab
                {
roentgen b75cab
                    nSkewBits = nBitsPerPixel * (nSamples-1);
roentgen b75cab
                    nSampleByteOffset = (nBitsPerPixel/8) * iSample;
roentgen b75cab
                }
roentgen b75cab
roentgen b75cab
                /*
roentgen b75cab
                 * Perform the downsampling.
roentgen b75cab
                 */
roentgen b75cab
#ifdef DBMALLOC
roentgen b75cab
                malloc_chain_check( 1 );
roentgen b75cab
#endif
roentgen b75cab
                TIFF_DownSample( pabySrcTile + nSampleByteOffset,
roentgen b75cab
                               nBlockXSize, nBlockYSize,
roentgen b75cab
                               nSkewBits, nBitsPerPixel, pabyOTile,
roentgen b75cab
                               poRBI->nBlockXSize, poRBI->nBlockYSize,
roentgen b75cab
                               nTXOff, nTYOff,
roentgen b75cab
                               nOMult, nSampleFormat, pszResampling );
roentgen b75cab
#ifdef DBMALLOC
roentgen b75cab
                malloc_chain_check( 1 );
roentgen b75cab
#endif
roentgen b75cab
            }
roentgen b75cab
        }
roentgen b75cab
    }
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/************************************************************************/
roentgen b75cab
/*                        TIFF_BuildOverviews()                         */
roentgen b75cab
/*                                                                      */
roentgen b75cab
/*      Build the requested list of overviews.  Overviews are           */
roentgen b75cab
/*      maintained in a bunch of temporary files and then these are     */
roentgen b75cab
/*      written back to the TIFF file.  Only one pass through the       */
roentgen b75cab
/*      source TIFF file is made for any number of output               */
roentgen b75cab
/*      overviews.                                                      */
roentgen b75cab
/************************************************************************/
roentgen b75cab
roentgen b75cab
void TIFFBuildOverviews( TIFF *hTIFF, int nOverviews, int * panOvList,
roentgen b75cab
                         int bUseSubIFDs, const char *pszResampleMethod,
roentgen b75cab
                         int (*pfnProgress)( double, void * ),
roentgen b75cab
                         void * pProgressData )
roentgen b75cab
roentgen b75cab
{
roentgen b75cab
    TIFFOvrCache	**papoRawBIs;
roentgen b75cab
    uint32		nXSize, nYSize, nBlockXSize, nBlockYSize;
roentgen b75cab
    uint16		nBitsPerPixel, nPhotometric, nCompressFlag, nSamples,
roentgen b75cab
        nPlanarConfig, nSampleFormat;
roentgen b75cab
    int         bSubsampled;
roentgen b75cab
    uint16      nHorSubsampling, nVerSubsampling;
roentgen b75cab
    int			bTiled, nSXOff, nSYOff, i;
roentgen b75cab
    unsigned char	*pabySrcTile;
roentgen b75cab
    uint16		*panRedMap, *panGreenMap, *panBlueMap;
roentgen b75cab
    TIFFErrorHandler    pfnWarning;
roentgen b75cab
roentgen b75cab
    (void) pfnProgress;
roentgen b75cab
    (void) pProgressData;
roentgen b75cab
roentgen b75cab
/* -------------------------------------------------------------------- */
roentgen b75cab
/*      Get the base raster size.                                       */
roentgen b75cab
/* -------------------------------------------------------------------- */
roentgen b75cab
    TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &nXSize );
roentgen b75cab
    TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &nYSize );
roentgen b75cab
roentgen b75cab
    TIFFGetField( hTIFF, TIFFTAG_BITSPERSAMPLE, &nBitsPerPixel );
roentgen b75cab
    /* TODO: nBitsPerPixel seems misnomer and may need renaming to nBitsPerSample */
roentgen b75cab
    TIFFGetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, &nSamples );
roentgen b75cab
    TIFFGetFieldDefaulted( hTIFF, TIFFTAG_PLANARCONFIG, &nPlanarConfig );
roentgen b75cab
roentgen b75cab
    TIFFGetFieldDefaulted( hTIFF, TIFFTAG_PHOTOMETRIC, &nPhotometric );
roentgen b75cab
    TIFFGetFieldDefaulted( hTIFF, TIFFTAG_COMPRESSION, &nCompressFlag );
roentgen b75cab
    TIFFGetFieldDefaulted( hTIFF, TIFFTAG_SAMPLEFORMAT, &nSampleFormat );
roentgen b75cab
roentgen b75cab
    if( nPhotometric == PHOTOMETRIC_YCBCR || nPhotometric == PHOTOMETRIC_ITULAB )
roentgen b75cab
    {
roentgen b75cab
        if( nBitsPerPixel != 8 || nSamples != 3 || nPlanarConfig != PLANARCONFIG_CONTIG ||
roentgen b75cab
            nSampleFormat != SAMPLEFORMAT_UINT)
roentgen b75cab
        {
roentgen b75cab
            /* TODO: use of TIFFError is inconsistent with use of fprintf in addtiffo.c, sort out */
roentgen b75cab
            TIFFErrorExt( TIFFClientdata(hTIFF), "TIFFBuildOverviews",
roentgen b75cab
                          "File `%s' has an unsupported subsampling configuration.\n",
roentgen b75cab
                          TIFFFileName(hTIFF) );
roentgen b75cab
            /* If you need support for this particular flavor, please contact either
roentgen b75cab
             * Frank Warmerdam warmerdam@pobox.com
roentgen b75cab
             * Joris Van Damme info@awaresystems.be
roentgen b75cab
             */
roentgen b75cab
            return;
roentgen b75cab
        }
roentgen b75cab
        bSubsampled = 1;
roentgen b75cab
        TIFFGetField( hTIFF, TIFFTAG_YCBCRSUBSAMPLING, &nHorSubsampling, &nVerSubsampling );
roentgen b75cab
        /* TODO: find out if maybe TIFFGetFieldDefaulted is better choice for YCbCrSubsampling tag */
roentgen b75cab
    }
roentgen b75cab
    else
roentgen b75cab
    {
roentgen b75cab
        if( nBitsPerPixel < 8 )
roentgen b75cab
        {
roentgen b75cab
            /* TODO: use of TIFFError is inconsistent with use of fprintf in addtiffo.c, sort out */
roentgen b75cab
            TIFFErrorExt( TIFFClientdata(hTIFF), "TIFFBuildOverviews",
roentgen b75cab
                          "File `%s' has samples of %d bits per sample.  Sample\n"
roentgen b75cab
                          "sizes of less than 8 bits per sample are not supported.\n",
roentgen b75cab
                          TIFFFileName(hTIFF), nBitsPerPixel );
roentgen b75cab
            return;
roentgen b75cab
        }
roentgen b75cab
        bSubsampled = 0;
roentgen b75cab
        nHorSubsampling = 1;
roentgen b75cab
        nVerSubsampling = 1;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
/* -------------------------------------------------------------------- */
roentgen b75cab
/*      Turn off warnings to avoid alot of repeated warnings while      */
roentgen b75cab
/*      rereading directories.                                          */
roentgen b75cab
/* -------------------------------------------------------------------- */
roentgen b75cab
    pfnWarning = TIFFSetWarningHandler( NULL );
roentgen b75cab
roentgen b75cab
/* -------------------------------------------------------------------- */
roentgen b75cab
/*      Get the base raster block size.                                 */
roentgen b75cab
/* -------------------------------------------------------------------- */
roentgen b75cab
    if( TIFFGetField( hTIFF, TIFFTAG_ROWSPERSTRIP, &(nBlockYSize) ) )
roentgen b75cab
    {
roentgen b75cab
        nBlockXSize = nXSize;
roentgen b75cab
        bTiled = FALSE;
roentgen b75cab
    }
roentgen b75cab
    else
roentgen b75cab
    {
roentgen b75cab
        TIFFGetField( hTIFF, TIFFTAG_TILEWIDTH, &nBlockXSize );
roentgen b75cab
        TIFFGetField( hTIFF, TIFFTAG_TILELENGTH, &nBlockYSize );
roentgen b75cab
        bTiled = TRUE;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
/* -------------------------------------------------------------------- */
roentgen b75cab
/*	Capture the pallette if there is one.				*/
roentgen b75cab
/* -------------------------------------------------------------------- */
roentgen b75cab
    if( TIFFGetField( hTIFF, TIFFTAG_COLORMAP,
roentgen b75cab
                      &panRedMap, &panGreenMap, &panBlueMap ) )
roentgen b75cab
    {
roentgen b75cab
        uint16		*panRed2, *panGreen2, *panBlue2;
roentgen b75cab
        int             nColorCount = 1 << nBitsPerPixel;
roentgen b75cab
roentgen b75cab
        panRed2 = (uint16 *) _TIFFmalloc(2*nColorCount);
roentgen b75cab
        panGreen2 = (uint16 *) _TIFFmalloc(2*nColorCount);
roentgen b75cab
        panBlue2 = (uint16 *) _TIFFmalloc(2*nColorCount);
roentgen b75cab
roentgen b75cab
        memcpy( panRed2, panRedMap, 2 * nColorCount );
roentgen b75cab
        memcpy( panGreen2, panGreenMap, 2 * nColorCount );
roentgen b75cab
        memcpy( panBlue2, panBlueMap, 2 * nColorCount );
roentgen b75cab
roentgen b75cab
        panRedMap = panRed2;
roentgen b75cab
        panGreenMap = panGreen2;
roentgen b75cab
        panBlueMap = panBlue2;
roentgen b75cab
    }
roentgen b75cab
    else
roentgen b75cab
    {
roentgen b75cab
        panRedMap = panGreenMap = panBlueMap = NULL;
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
/* -------------------------------------------------------------------- */
roentgen b75cab
/*      Initialize overviews.                                           */
roentgen b75cab
/* -------------------------------------------------------------------- */
roentgen b75cab
    papoRawBIs = (TIFFOvrCache **) _TIFFmalloc(nOverviews*sizeof(void*));
roentgen b75cab
roentgen b75cab
    for( i = 0; i < nOverviews; i++ )
roentgen b75cab
    {
roentgen b75cab
        uint32  nOXSize, nOYSize, nOBlockXSize, nOBlockYSize;
roentgen b75cab
        toff_t  nDirOffset;
roentgen b75cab
roentgen b75cab
        nOXSize = (nXSize + panOvList[i] - 1) / panOvList[i];
roentgen b75cab
        nOYSize = (nYSize + panOvList[i] - 1) / panOvList[i];
roentgen b75cab
roentgen b75cab
        nOBlockXSize = MIN(nBlockXSize,nOXSize);
roentgen b75cab
        nOBlockYSize = MIN(nBlockYSize,nOYSize);
roentgen b75cab
roentgen b75cab
        if( bTiled )
roentgen b75cab
        {
roentgen b75cab
            if( (nOBlockXSize % 16) != 0 )
roentgen b75cab
                nOBlockXSize = nOBlockXSize + 16 - (nOBlockXSize % 16);
roentgen b75cab
roentgen b75cab
            if( (nOBlockYSize % 16) != 0 )
roentgen b75cab
                nOBlockYSize = nOBlockYSize + 16 - (nOBlockYSize % 16);
roentgen b75cab
        }
roentgen b75cab
roentgen b75cab
        nDirOffset = TIFF_WriteOverview( hTIFF, nOXSize, nOYSize,
roentgen b75cab
                                         nBitsPerPixel, nPlanarConfig,
roentgen b75cab
                                         nSamples, nOBlockXSize, nOBlockYSize,
roentgen b75cab
                                         bTiled, nCompressFlag, nPhotometric,
roentgen b75cab
                                         nSampleFormat,
roentgen b75cab
                                         panRedMap, panGreenMap, panBlueMap,
roentgen b75cab
                                         bUseSubIFDs,
roentgen b75cab
                                         nHorSubsampling, nVerSubsampling );
roentgen b75cab
        
roentgen b75cab
        papoRawBIs[i] = TIFFCreateOvrCache( hTIFF, nDirOffset );
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
    if( panRedMap != NULL )
roentgen b75cab
    {
roentgen b75cab
        _TIFFfree( panRedMap );
roentgen b75cab
        _TIFFfree( panGreenMap );
roentgen b75cab
        _TIFFfree( panBlueMap );
roentgen b75cab
    }
roentgen b75cab
    
roentgen b75cab
/* -------------------------------------------------------------------- */
roentgen b75cab
/*      Allocate a buffer to hold a source block.                       */
roentgen b75cab
/* -------------------------------------------------------------------- */
roentgen b75cab
    if( bTiled )
roentgen b75cab
        pabySrcTile = (unsigned char *) _TIFFmalloc(TIFFTileSize(hTIFF));
roentgen b75cab
    else
roentgen b75cab
        pabySrcTile = (unsigned char *) _TIFFmalloc(TIFFStripSize(hTIFF));
roentgen b75cab
    
roentgen b75cab
/* -------------------------------------------------------------------- */
roentgen b75cab
/*      Loop over the source raster, applying data to the               */
roentgen b75cab
/*      destination raster.                                             */
roentgen b75cab
/* -------------------------------------------------------------------- */
roentgen b75cab
    for( nSYOff = 0; nSYOff < (int) nYSize; nSYOff += nBlockYSize )
roentgen b75cab
    {
roentgen b75cab
        for( nSXOff = 0; nSXOff < (int) nXSize; nSXOff += nBlockXSize )
roentgen b75cab
        {
roentgen b75cab
            /*
roentgen b75cab
             * Read and resample into the various overview images.
roentgen b75cab
             */
roentgen b75cab
            
roentgen b75cab
            TIFF_ProcessFullResBlock( hTIFF, nPlanarConfig,
roentgen b75cab
                                      bSubsampled,nHorSubsampling,nVerSubsampling,
roentgen b75cab
                                      nOverviews, panOvList,
roentgen b75cab
                                      nBitsPerPixel, nSamples, papoRawBIs,
roentgen b75cab
                                      nSXOff, nSYOff, pabySrcTile,
roentgen b75cab
                                      nBlockXSize, nBlockYSize,
roentgen b75cab
                                      nSampleFormat, pszResampleMethod );
roentgen b75cab
        }
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
    _TIFFfree( pabySrcTile );
roentgen b75cab
roentgen b75cab
/* -------------------------------------------------------------------- */
roentgen b75cab
/*      Cleanup the rawblockedimage files.                              */
roentgen b75cab
/* -------------------------------------------------------------------- */
roentgen b75cab
    for( i = 0; i < nOverviews; i++ )
roentgen b75cab
    {
roentgen b75cab
        TIFFDestroyOvrCache( papoRawBIs[i] );
roentgen b75cab
    }
roentgen b75cab
roentgen b75cab
    if( papoRawBIs != NULL )
roentgen b75cab
        _TIFFfree( papoRawBIs );
roentgen b75cab
roentgen b75cab
    TIFFSetWarningHandler( pfnWarning );
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Local Variables:
roentgen b75cab
 * mode: c
roentgen b75cab
 * c-basic-offset: 8
roentgen b75cab
 * fill-column: 78
roentgen b75cab
 * End:
roentgen b75cab
 */