Blame contrib/addtiffo/tif_overview.c

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