Blame contrib/addtiffo/tif_overview.c

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