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