1 /******************************************************************************
2  * tif_overview.c,v 1.9 2005/05/25 09:03:16 dron Exp
3  *
4  * Project:  TIFF Overview Builder
5  * Purpose:  Library function for building overviews in a TIFF file.
6  * Author:   Frank Warmerdam, warmerdam@pobox.com
7  *
8  * Notes:
9  *  o Currently only images with bits_per_sample of a multiple of eight
10  *    will work.
11  *
12  *  o The downsampler currently just takes the top left pixel from the
13  *    source rectangle.  Eventually sampling options of averaging, mode, and
14  *    ``center pixel'' should be offered.
15  *
16  *  o The code will attempt to use the same kind of compression,
17  *    photometric interpretation, and organization as the source image, but
18  *    it doesn't copy geotiff tags to the reduced resolution images.
19  *
20  *  o Reduced resolution overviews for multi-sample files will currently
21  *    always be generated as PLANARCONFIG_SEPARATE.  This could be fixed
22  *    reasonable easily if needed to improve compatibility with other
23  *    packages.  Many don't properly support PLANARCONFIG_SEPARATE.
24  *
25  ******************************************************************************
26  * Copyright (c) 1999, Frank Warmerdam
27  *
28  * Permission is hereby granted, free of charge, to any person obtaining a
29  * copy of this software and associated documentation files (the "Software"),
30  * to deal in the Software without restriction, including without limitation
31  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
32  * and/or sell copies of the Software, and to permit persons to whom the
33  * Software is furnished to do so, subject to the following conditions:
34  *
35  * The above copyright notice and this permission notice shall be included
36  * in all copies or substantial portions of the Software.
37  *
38  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
39  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
40  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
41  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
42  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
43  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
44  * DEALINGS IN THE SOFTWARE.
45  ******************************************************************************
46  */
47 
48 /* TODO: update notes in header above */
49 
50 #include <stdio.h>
51 #include <assert.h>
52 #include <stdlib.h>
53 #include <string.h>
54 
55 #include "tiffio.h"
56 #include "tif_ovrcache.h"
57 
58 #ifndef FALSE
59 #  define FALSE 0
60 #  define TRUE 1
61 #endif
62 
63 #ifndef MAX
64 #  define MIN(a,b)      ((a<b) ? a : b)
65 #  define MAX(a,b)      ((a>b) ? a : b)
66 #endif
67 
68 void TIFFBuildOverviews( TIFF *, int, int *, int, const char *,
69                          int (*)(double,void*), void * );
70 
71 /************************************************************************/
72 /*                         TIFF_WriteOverview()                         */
73 /*                                                                      */
74 /*      Create a new directory, without any image data for an overview. */
75 /*      Returns offset of newly created overview directory, but the     */
76 /*      current directory is reset to be the one in used when this      */
77 /*      function is called.                                             */
78 /************************************************************************/
79 
TIFF_WriteOverview(TIFF * hTIFF,int nXSize,int nYSize,int nBitsPerPixel,int nPlanarConfig,int nSamples,int nBlockXSize,int nBlockYSize,int bTiled,int nCompressFlag,int nPhotometric,int nSampleFormat,unsigned short * panRed,unsigned short * panGreen,unsigned short * panBlue,int bUseSubIFDs,int nHorSubsampling,int nVerSubsampling)80 uint32 TIFF_WriteOverview( TIFF *hTIFF, int nXSize, int nYSize,
81                            int nBitsPerPixel, int nPlanarConfig, int nSamples,
82                            int nBlockXSize, int nBlockYSize,
83                            int bTiled, int nCompressFlag, int nPhotometric,
84                            int nSampleFormat,
85                            unsigned short *panRed,
86                            unsigned short *panGreen,
87                            unsigned short *panBlue,
88                            int bUseSubIFDs,
89                            int nHorSubsampling, int nVerSubsampling )
90 
91 {
92     uint32	nBaseDirOffset;
93     uint32	nOffset;
94 
95     nBaseDirOffset = TIFFCurrentDirOffset( hTIFF );
96 
97     TIFFCreateDirectory( hTIFF );
98 
99 /* -------------------------------------------------------------------- */
100 /*      Setup TIFF fields.                                              */
101 /* -------------------------------------------------------------------- */
102     TIFFSetField( hTIFF, TIFFTAG_IMAGEWIDTH, nXSize );
103     TIFFSetField( hTIFF, TIFFTAG_IMAGELENGTH, nYSize );
104     if( nSamples == 1 )
105         TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG );
106     else
107         TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG, nPlanarConfig );
108 
109     TIFFSetField( hTIFF, TIFFTAG_BITSPERSAMPLE, nBitsPerPixel );
110     TIFFSetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, nSamples );
111     TIFFSetField( hTIFF, TIFFTAG_COMPRESSION, nCompressFlag );
112     TIFFSetField( hTIFF, TIFFTAG_PHOTOMETRIC, nPhotometric );
113     TIFFSetField( hTIFF, TIFFTAG_SAMPLEFORMAT, nSampleFormat );
114 
115     if( bTiled )
116     {
117         TIFFSetField( hTIFF, TIFFTAG_TILEWIDTH, nBlockXSize );
118         TIFFSetField( hTIFF, TIFFTAG_TILELENGTH, nBlockYSize );
119     }
120     else
121         TIFFSetField( hTIFF, TIFFTAG_ROWSPERSTRIP, nBlockYSize );
122 
123     TIFFSetField( hTIFF, TIFFTAG_SUBFILETYPE, FILETYPE_REDUCEDIMAGE );
124 
125     if( nPhotometric == PHOTOMETRIC_YCBCR || nPhotometric == PHOTOMETRIC_ITULAB )
126     {
127         TIFFSetField( hTIFF, TIFFTAG_YCBCRSUBSAMPLING, nHorSubsampling, nVerSubsampling);
128         /* TODO: also write YCbCrPositioning and YCbCrCoefficients tag identical to source IFD */
129     }
130     /* TODO: add command-line parameter for selecting jpeg compression quality
131      * that gets ignored when compression isn't jpeg */
132 
133 /* -------------------------------------------------------------------- */
134 /*	Write color table if one is present.				*/
135 /* -------------------------------------------------------------------- */
136     if( panRed != NULL )
137     {
138         TIFFSetField( hTIFF, TIFFTAG_COLORMAP, panRed, panGreen, panBlue );
139     }
140 
141 /* -------------------------------------------------------------------- */
142 /*      Write directory, and return byte offset.                        */
143 /* -------------------------------------------------------------------- */
144     if( TIFFWriteCheck( hTIFF, bTiled, "TIFFBuildOverviews" ) == 0 )
145         return 0;
146 
147     TIFFWriteDirectory( hTIFF );
148     TIFFSetDirectory( hTIFF, (tdir_t) (TIFFNumberOfDirectories(hTIFF)-1) );
149 
150     nOffset = TIFFCurrentDirOffset( hTIFF );
151 
152     TIFFSetSubDirectory( hTIFF, nBaseDirOffset );
153 
154     return nOffset;
155 }
156 
157 /************************************************************************/
158 /*                       TIFF_GetSourceSamples()                        */
159 /************************************************************************/
160 
161 static void
TIFF_GetSourceSamples(double * padfSamples,unsigned char * pabySrc,int nPixelBytes,int nSampleFormat,int nXSize,int nYSize,int nPixelOffset,int nLineOffset)162 TIFF_GetSourceSamples( double * padfSamples, unsigned char *pabySrc,
163                        int nPixelBytes, int nSampleFormat,
164                        int nXSize, int nYSize,
165                        int nPixelOffset, int nLineOffset )
166 {
167     int  iXOff, iYOff, iSample;
168 
169     iSample = 0;
170 
171     for( iYOff = 0; iYOff < nYSize; iYOff++ )
172     {
173         for( iXOff = 0; iXOff < nXSize; iXOff++ )
174         {
175             unsigned char *pabyData;
176 
177             pabyData = pabySrc + iYOff * nLineOffset + iXOff * nPixelOffset;
178 
179             if( nSampleFormat == SAMPLEFORMAT_UINT && nPixelBytes == 1 )
180             {
181                 padfSamples[iSample++] = *pabyData;
182             }
183             else if( nSampleFormat == SAMPLEFORMAT_UINT && nPixelBytes == 2 )
184             {
185                 padfSamples[iSample++] = ((uint16 *) pabyData)[0];
186             }
187             else if( nSampleFormat == SAMPLEFORMAT_UINT && nPixelBytes == 4 )
188             {
189                 padfSamples[iSample++] = ((uint32 *) pabyData)[0];
190             }
191             else if( nSampleFormat == SAMPLEFORMAT_INT && nPixelBytes == 2 )
192             {
193                 padfSamples[iSample++] = ((int16 *) pabyData)[0];
194             }
195             else if( nSampleFormat == SAMPLEFORMAT_INT && nPixelBytes == 32 )
196             {
197                 padfSamples[iSample++] = ((int32 *) pabyData)[0];
198             }
199             else if( nSampleFormat == SAMPLEFORMAT_IEEEFP && nPixelBytes == 4 )
200             {
201                 padfSamples[iSample++] = ((float *) pabyData)[0];
202             }
203             else if( nSampleFormat == SAMPLEFORMAT_IEEEFP && nPixelBytes == 8 )
204             {
205                 padfSamples[iSample++] = ((double *) pabyData)[0];
206             }
207         }
208     }
209 }
210 
211 /************************************************************************/
212 /*                           TIFF_SetSample()                           */
213 /************************************************************************/
214 
215 static void
TIFF_SetSample(unsigned char * pabyData,int nPixelBytes,int nSampleFormat,double dfValue)216 TIFF_SetSample( unsigned char * pabyData, int nPixelBytes, int nSampleFormat,
217                 double dfValue )
218 
219 {
220     if( nSampleFormat == SAMPLEFORMAT_UINT && nPixelBytes == 1 )
221     {
222         *pabyData = (unsigned char) MAX(0,MIN(255,dfValue));
223     }
224     else if( nSampleFormat == SAMPLEFORMAT_UINT && nPixelBytes == 2 )
225     {
226         *((uint16 *)pabyData) = (uint16) MAX(0,MIN(65535,dfValue));
227     }
228     else if( nSampleFormat == SAMPLEFORMAT_UINT && nPixelBytes == 4 )
229     {
230         *((uint32 *)pabyData) = (uint32) dfValue;
231     }
232     else if( nSampleFormat == SAMPLEFORMAT_INT && nPixelBytes == 2 )
233     {
234         *((int16 *)pabyData) = (int16) MAX(-32768,MIN(32767,dfValue));
235     }
236     else if( nSampleFormat == SAMPLEFORMAT_INT && nPixelBytes == 32 )
237     {
238         *((int32 *)pabyData) = (int32) dfValue;
239     }
240     else if( nSampleFormat == SAMPLEFORMAT_IEEEFP && nPixelBytes == 4 )
241     {
242         *((float *)pabyData) = (float) dfValue;
243     }
244     else if( nSampleFormat == SAMPLEFORMAT_IEEEFP && nPixelBytes == 8 )
245     {
246         *((double *)pabyData) = dfValue;
247     }
248 }
249 
250 /************************************************************************/
251 /*                          TIFF_DownSample()                           */
252 /*                                                                      */
253 /*      Down sample a tile of full res data into a window of a tile     */
254 /*      of downsampled data.                                            */
255 /************************************************************************/
256 
257 static
TIFF_DownSample(unsigned char * pabySrcTile,int nBlockXSize,int nBlockYSize,int nPixelSkewBits,int nBitsPerPixel,unsigned char * pabyOTile,int nOBlockXSize,int nOBlockYSize,int nTXOff,int nTYOff,int nOMult,int nSampleFormat,const char * pszResampling)258 void TIFF_DownSample( unsigned char *pabySrcTile,
259                       int nBlockXSize, int nBlockYSize,
260                       int nPixelSkewBits, int nBitsPerPixel,
261                       unsigned char * pabyOTile,
262                       int nOBlockXSize, int nOBlockYSize,
263                       int nTXOff, int nTYOff, int nOMult,
264                       int nSampleFormat, const char * pszResampling )
265 
266 {
267     int		i, j, k, nPixelBytes = (nBitsPerPixel) / 8;
268     int		nPixelGroupBytes = (nBitsPerPixel+nPixelSkewBits)/8;
269     unsigned char *pabySrc, *pabyDst;
270     double      *padfSamples;
271 
272     assert( nBitsPerPixel >= 8 );
273 
274     padfSamples = (double *) malloc(sizeof(double) * nOMult * nOMult);
275 
276 /* ==================================================================== */
277 /*      Loop over scanline chunks to process, establishing where the    */
278 /*      data is going.                                                  */
279 /* ==================================================================== */
280     for( j = 0; j*nOMult < nBlockYSize; j++ )
281     {
282         if( j + nTYOff >= nOBlockYSize )
283             break;
284 
285         pabyDst = pabyOTile + ((j+nTYOff)*nOBlockXSize + nTXOff)
286             * nPixelBytes * nPixelGroupBytes;
287 
288 /* -------------------------------------------------------------------- */
289 /*      Handler nearest resampling ... we don't even care about the     */
290 /*      data type, we just do a bytewise copy.                          */
291 /* -------------------------------------------------------------------- */
292         if( strncmp(pszResampling,"nearest",4) == 0
293             || strncmp(pszResampling,"NEAR",4) == 0 )
294         {
295             pabySrc = pabySrcTile + j*nOMult*nBlockXSize * nPixelGroupBytes;
296 
297             for( i = 0; i*nOMult < nBlockXSize; i++ )
298             {
299                 if( i + nTXOff >= nOBlockXSize )
300                     break;
301 
302                 /*
303                  * For now use simple subsampling, from the top left corner
304                  * of the source block of pixels.
305                  */
306 
307                 for( k = 0; k < nPixelBytes; k++ )
308                     pabyDst[k] = pabySrc[k];
309 
310                 pabyDst += nPixelBytes * nPixelGroupBytes;
311                 pabySrc += nOMult * nPixelGroupBytes;
312             }
313         }
314 
315 /* -------------------------------------------------------------------- */
316 /*      Handle the case of averaging.  For this we also have to         */
317 /*      handle each sample format we are concerned with.                */
318 /* -------------------------------------------------------------------- */
319         else if( strncmp(pszResampling,"averag",6) == 0
320                  || strncmp(pszResampling,"AVERAG",6) == 0 )
321         {
322             pabySrc = pabySrcTile + j*nOMult*nBlockXSize * nPixelGroupBytes;
323 
324             for( i = 0; i*nOMult < nBlockXSize; i++ )
325             {
326                 double   dfTotal;
327                 int      iSample;
328                 int      nXSize, nYSize;
329 
330                 if( i + nTXOff >= nOBlockXSize )
331                     break;
332 
333                 nXSize = MIN(nOMult,nBlockXSize-i);
334                 nYSize = MIN(nOMult,nBlockYSize-j);
335 
336                 TIFF_GetSourceSamples( padfSamples, pabySrc,
337                                        nPixelBytes, nSampleFormat,
338                                        nXSize, nYSize,
339                                        nPixelGroupBytes,
340                                        nPixelGroupBytes * nBlockXSize );
341 
342                 dfTotal = 0;
343                 for( iSample = 0; iSample < nXSize*nYSize; iSample++ )
344                 {
345                     dfTotal += padfSamples[iSample];
346                 }
347 
348                 TIFF_SetSample( pabyDst, nPixelBytes, nSampleFormat,
349                                 dfTotal / (nXSize*nYSize) );
350 
351                 pabySrc += nOMult * nPixelGroupBytes;
352                 pabyDst += nPixelBytes;
353             }
354         }
355     }
356 
357     free( padfSamples );
358 }
359 
360 static
TIFF_DownSample_Subsampled(unsigned char * pabySrcTile,int nSample,int nBlockXSize,int nBlockYSize,unsigned char * pabyOTile,int nOBlockXSize,int nOBlockYSize,int nTXOff,int nTYOff,int nOMult,const char * pszResampling,int nHorSubsampling,int nVerSubsampling)361 void TIFF_DownSample_Subsampled( unsigned char *pabySrcTile, int nSample,
362                                  int nBlockXSize, int nBlockYSize,
363                                  unsigned char * pabyOTile,
364                                  int nOBlockXSize, int nOBlockYSize,
365                                  int nTXOff, int nTYOff, int nOMult,
366                                  const char * pszResampling,
367                                  int nHorSubsampling, int nVerSubsampling )
368 {
369     /* TODO: test with variety of subsampling values, and incovinient tile/strip sizes */
370 	int nSampleBlockSize;
371     int nSourceSampleRowSize;
372     int nDestSampleRowSize;
373     int nSourceX, nSourceY;
374     int nSourceXSec, nSourceYSec;
375     int nSourceXSecEnd, nSourceYSecEnd;
376     int nDestX, nDestY;
377     int nSampleOffsetInSampleBlock;
378     unsigned char * pSourceBase;
379     unsigned char * pDestBase;
380     int nSourceBaseInc;
381     unsigned char * pSourceBaseEnd;
382     unsigned int nCummulator;
383     unsigned int nCummulatorCount;
384 
385     nSampleBlockSize = nHorSubsampling * nVerSubsampling + 2;
386     nSourceSampleRowSize = ( ( nBlockXSize + nHorSubsampling - 1 ) / nHorSubsampling ) * nSampleBlockSize;
387     nDestSampleRowSize = ( ( nOBlockXSize + nHorSubsampling - 1 ) / nHorSubsampling ) * nSampleBlockSize;
388 
389     if( strncmp(pszResampling,"nearest",4) == 0
390             || strncmp(pszResampling,"NEAR",4) == 0 )
391 	{
392     	if( nSample == 0 )
393         {
394 #ifdef NOOPTIMIZATION
395         	/*
396              * This version is not optimized, and should not be used except as documentation and as more clear
397              * starting point for bug fixes (hope not) and extension
398              */
399              for( nSourceY = 0, nDestY = nTYOff; nSourceY < nBlockYSize; nSourceY += nOMult, nDestY ++)
400              {
401                 for( nSourceX = 0, nDestX = nTXOff; nSourceX < nBlockXSize; nSourceX += nOMult, nDestX ++)
402                 {
403                     * ( pabyOTile + ( nDestY / nVerSubsampling ) * nDestSampleRowSize
404                                   + ( nDestY % nVerSubsampling ) * nHorSubsampling
405                                   + ( nDestX / nHorSubsampling ) * nSampleBlockSize
406                                   + ( nDestX % nHorSubsampling ) ) =
407                         * ( pabySrcTile + ( nSourceY / nVerSubsampling ) * nSourceSampleRowSize
408                                         + ( nSourceY % nVerSubsampling ) * nHorSubsampling
409                                         + ( nSourceX / nHorSubsampling ) * nSampleBlockSize
410                                         + ( nSourceX % nHorSubsampling ) );
411                 }
412             }
413 #else
414             for( nSourceY = 0, nDestY = nTYOff; nSourceY < nBlockYSize; nSourceY += nOMult, nDestY ++)
415             {
416                 pSourceBase = pabySrcTile + ( nSourceY / nVerSubsampling ) * nSourceSampleRowSize
417                                           + ( nSourceY % nVerSubsampling ) * nHorSubsampling;
418                 pDestBase = pabyOTile + ( nDestY / nVerSubsampling ) * nDestSampleRowSize
419                                       + ( nDestY % nVerSubsampling ) * nHorSubsampling;
420                 for( nSourceX = 0, nDestX = nTXOff; nSourceX < nBlockXSize; nSourceX += nOMult, nDestX ++)
421                 {
422                     * ( pDestBase + ( nDestX / nHorSubsampling ) * nSampleBlockSize
423                                   + ( nDestX % nHorSubsampling ) ) =
424                         * ( pSourceBase + ( nSourceX / nHorSubsampling ) * nSampleBlockSize
425                                         + ( nSourceX % nHorSubsampling ) );
426                 }
427             }
428 #endif
429         }
430         else
431         {
432 #ifdef NOOPTIMIZATION
433         	/*
434              * This version is not optimized, and should not be used except as documentation and as more clear
435              * starting point for bug fixes (hope not) and extension
436              */
437             nSampleOffsetInSampleBlock = nHorSubsampling * nVerSubsampling + nSample - 1;
438             for( nSourceY = 0, nDestY = ( nTYOff / nVerSubsampling ); nSourceY < ( nBlockYSize / nVerSubsampling );
439                                 nSourceY += nOMult, nDestY ++)
440             {
441             	for( nSourceX = 0, nDestX = ( nTXOff / nHorSubsampling ); nSourceX < ( nBlockXSize / nHorSubsampling );
442                 	                 nSourceX += nOMult, nDestX ++)
443                 {
444                     * ( pabyOTile + nDestY * nDestSampleRowSize
445                                   + nDestX * nSampleBlockSize
446                                   + nSampleOffsetInSampleBlock ) =
447                     	* ( pabySrcTile + nSourceY * nSourceSampleRowSize
448                                         + nSourceX * nSampleBlockSize
449                                         + nSampleOffsetInSampleBlock );
450                 }
451             }
452 #else
453             nSampleOffsetInSampleBlock = nHorSubsampling * nVerSubsampling + nSample - 1;
454             nSourceBaseInc = nOMult * nSampleBlockSize;
455             for( nSourceY = 0, nDestY = ( nTYOff / nVerSubsampling ); nSourceY < ( nBlockYSize / nVerSubsampling);
456                                 nSourceY += nOMult, nDestY ++)
457             {
458                 pSourceBase = pabySrcTile + nSourceY * nSourceSampleRowSize
459                                           + nSampleOffsetInSampleBlock;
460                 pSourceBaseEnd = pSourceBase + ( ( ( nBlockXSize / nHorSubsampling ) + nOMult - 1 ) / nOMult ) * nSourceBaseInc;
461                 pDestBase = pabyOTile + nDestY * nDestSampleRowSize
462                                       + ( nTXOff / nHorSubsampling ) * nSampleBlockSize
463                                       + nSampleOffsetInSampleBlock;
464                 for( ; pSourceBase < pSourceBaseEnd; pSourceBase += nSourceBaseInc, pDestBase += nSampleBlockSize)
465                     * pDestBase = * pSourceBase;
466             }
467 #endif
468         }
469     }
470     else if( strncmp(pszResampling,"averag",6) == 0
471                  || strncmp(pszResampling,"AVERAG",6) == 0 )
472     {
473     	if( nSample == 0 )
474         {
475             for( nSourceY = 0, nDestY = nTYOff; nSourceY < nBlockYSize; nSourceY += nOMult, nDestY ++)
476             {
477                 for( nSourceX = 0, nDestX = nTXOff; nSourceX < nBlockXSize; nSourceX += nOMult, nDestX ++)
478                 {
479                     nSourceXSecEnd = nSourceX + nOMult;
480                     if( nSourceXSecEnd > nBlockXSize )
481                         nSourceXSecEnd = nBlockXSize;
482                     nSourceYSecEnd = nSourceY + nOMult;
483                     if( nSourceYSecEnd > nBlockYSize )
484                         nSourceYSecEnd = nBlockYSize;
485                     nCummulator = 0;
486                     for( nSourceYSec = nSourceY; nSourceYSec < nSourceYSecEnd; nSourceYSec ++)
487                     {
488                         for( nSourceXSec = nSourceX; nSourceXSec < nSourceXSecEnd; nSourceXSec ++)
489                         {
490                             nCummulator += * ( pabySrcTile + ( nSourceYSec / nVerSubsampling ) * nSourceSampleRowSize
491                                                            + ( nSourceYSec % nVerSubsampling ) * nHorSubsampling
492                                                            + ( nSourceXSec / nHorSubsampling ) * nSampleBlockSize
493                                                            + ( nSourceXSec % nHorSubsampling ) );
494                         }
495                     }
496                     nCummulatorCount = ( nSourceXSecEnd - nSourceX ) * ( nSourceYSecEnd - nSourceY );
497                     * ( pabyOTile + ( nDestY / nVerSubsampling ) * nDestSampleRowSize
498                                   + ( nDestY % nVerSubsampling ) * nHorSubsampling
499                                   + ( nDestX / nHorSubsampling ) * nSampleBlockSize
500                                   + ( nDestX % nHorSubsampling ) ) =
501                         ( ( nCummulator + ( nCummulatorCount >> 1 ) ) / nCummulatorCount );
502                 }
503             }
504         }
505         else
506         {
507             nSampleOffsetInSampleBlock = nHorSubsampling * nVerSubsampling + nSample - 1;
508             for( nSourceY = 0, nDestY = ( nTYOff / nVerSubsampling ); nSourceY < ( nBlockYSize / nVerSubsampling );
509                              nSourceY += nOMult, nDestY ++)
510             {
511                 for( nSourceX = 0, nDestX = ( nTXOff / nHorSubsampling ); nSourceX < ( nBlockXSize / nHorSubsampling );
512                                  nSourceX += nOMult, nDestX ++)
513                 {
514                     nSourceXSecEnd = nSourceX + nOMult;
515                     if( nSourceXSecEnd > ( nBlockXSize / nHorSubsampling ) )
516                         nSourceXSecEnd = ( nBlockXSize / nHorSubsampling );
517                     nSourceYSecEnd = nSourceY + nOMult;
518                     if( nSourceYSecEnd > ( nBlockYSize / nVerSubsampling ) )
519                         nSourceYSecEnd = ( nBlockYSize / nVerSubsampling );
520                     nCummulator = 0;
521                     for( nSourceYSec = nSourceY; nSourceYSec < nSourceYSecEnd; nSourceYSec ++)
522                     {
523                         for( nSourceXSec = nSourceX; nSourceXSec < nSourceXSecEnd; nSourceXSec ++)
524                         {
525                             nCummulator += * ( pabySrcTile + nSourceYSec * nSourceSampleRowSize
526                                                            + nSourceXSec * nSampleBlockSize
527                                                            + nSampleOffsetInSampleBlock );
528                         }
529                     }
530                     nCummulatorCount = ( nSourceXSecEnd - nSourceX ) * ( nSourceYSecEnd - nSourceY );
531                     * ( pabyOTile + nDestY * nDestSampleRowSize
532                                   + nDestX * nSampleBlockSize
533                                   + nSampleOffsetInSampleBlock ) =
534                         ( ( nCummulator + ( nCummulatorCount >> 1 ) ) / nCummulatorCount );
535                 }
536             }
537         }
538     }
539 }
540 
541 /************************************************************************/
542 /*                      TIFF_ProcessFullResBlock()                      */
543 /*                                                                      */
544 /*      Process one block of full res data, downsampling into each      */
545 /*      of the overviews.                                               */
546 /************************************************************************/
547 
TIFF_ProcessFullResBlock(TIFF * hTIFF,int nPlanarConfig,int bSubsampled,int nHorSubsampling,int nVerSubsampling,int nOverviews,int * panOvList,int nBitsPerPixel,int nSamples,TIFFOvrCache ** papoRawBIs,int nSXOff,int nSYOff,unsigned char * pabySrcTile,int nBlockXSize,int nBlockYSize,int nSampleFormat,const char * pszResampling)548 void TIFF_ProcessFullResBlock( TIFF *hTIFF, int nPlanarConfig,
549                                int bSubsampled, int nHorSubsampling, int nVerSubsampling,
550                                int nOverviews, int * panOvList,
551                                int nBitsPerPixel,
552                                int nSamples, TIFFOvrCache ** papoRawBIs,
553                                int nSXOff, int nSYOff,
554                                unsigned char *pabySrcTile,
555                                int nBlockXSize, int nBlockYSize,
556                                int nSampleFormat, const char * pszResampling )
557 
558 {
559     int		iOverview, iSample;
560 
561     for( iSample = 0; iSample < nSamples; iSample++ )
562     {
563         /*
564          * We have to read a tile/strip for each sample for
565          * PLANARCONFIG_SEPARATE.  Otherwise, we just read all the samples
566          * at once when handling the first sample.
567          */
568         if( nPlanarConfig == PLANARCONFIG_SEPARATE || iSample == 0 )
569         {
570             if( TIFFIsTiled(hTIFF) )
571             {
572                 TIFFReadEncodedTile( hTIFF,
573                                      TIFFComputeTile(hTIFF, nSXOff, nSYOff,
574                                                      0, (tsample_t)iSample ),
575                                      pabySrcTile,
576                                      TIFFTileSize(hTIFF));
577             }
578             else
579             {
580                 TIFFReadEncodedStrip( hTIFF,
581                                       TIFFComputeStrip(hTIFF, nSYOff,
582                                                        (tsample_t) iSample),
583                                       pabySrcTile,
584                                       TIFFStripSize(hTIFF) );
585             }
586         }
587 
588         /*
589          * Loop over destination overview layers
590          */
591         for( iOverview = 0; iOverview < nOverviews; iOverview++ )
592         {
593             TIFFOvrCache *poRBI = papoRawBIs[iOverview];
594             unsigned char *pabyOTile;
595             int	nTXOff, nTYOff, nOXOff, nOYOff, nOMult;
596             int	nOBlockXSize = poRBI->nBlockXSize;
597             int	nOBlockYSize = poRBI->nBlockYSize;
598             int	nSkewBits, nSampleByteOffset;
599 
600             /*
601              * Fetch the destination overview tile
602              */
603             nOMult = panOvList[iOverview];
604             nOXOff = (nSXOff/nOMult) / nOBlockXSize;
605             nOYOff = (nSYOff/nOMult) / nOBlockYSize;
606 
607             if( bSubsampled )
608             {
609                 pabyOTile = TIFFGetOvrBlock_Subsampled( poRBI, nOXOff, nOYOff );
610 
611                 /*
612                  * Establish the offset into this tile at which we should
613                  * start placing data.
614                  */
615                 nTXOff = (nSXOff - nOXOff*nOMult*nOBlockXSize) / nOMult;
616                 nTYOff = (nSYOff - nOYOff*nOMult*nOBlockYSize) / nOMult;
617 
618 
619 #ifdef DBMALLOC
620                 malloc_chain_check( 1 );
621 #endif
622                 TIFF_DownSample_Subsampled( pabySrcTile, iSample,
623                                             nBlockXSize, nBlockYSize,
624                                             pabyOTile,
625                                             poRBI->nBlockXSize, poRBI->nBlockYSize,
626                                             nTXOff, nTYOff,
627                                             nOMult, pszResampling,
628                                             nHorSubsampling, nVerSubsampling );
629 #ifdef DBMALLOC
630                 malloc_chain_check( 1 );
631 #endif
632 
633             }
634             else
635             {
636 
637                 pabyOTile = TIFFGetOvrBlock( poRBI, nOXOff, nOYOff, iSample );
638 
639                 /*
640                  * Establish the offset into this tile at which we should
641                  * start placing data.
642                  */
643                 nTXOff = (nSXOff - nOXOff*nOMult*nOBlockXSize) / nOMult;
644                 nTYOff = (nSYOff - nOYOff*nOMult*nOBlockYSize) / nOMult;
645 
646                 /*
647                  * Figure out the skew (extra space between ``our samples'') and
648                  * the byte offset to the first sample.
649                  */
650                 assert( (nBitsPerPixel % 8) == 0 );
651                 if( nPlanarConfig == PLANARCONFIG_SEPARATE )
652                 {
653                     nSkewBits = 0;
654                     nSampleByteOffset = 0;
655                 }
656                 else
657                 {
658                     nSkewBits = nBitsPerPixel * (nSamples-1);
659                     nSampleByteOffset = (nBitsPerPixel/8) * iSample;
660                 }
661 
662                 /*
663                  * Perform the downsampling.
664                  */
665 #ifdef DBMALLOC
666                 malloc_chain_check( 1 );
667 #endif
668                 TIFF_DownSample( pabySrcTile + nSampleByteOffset,
669                                nBlockXSize, nBlockYSize,
670                                nSkewBits, nBitsPerPixel, pabyOTile,
671                                poRBI->nBlockXSize, poRBI->nBlockYSize,
672                                nTXOff, nTYOff,
673                                nOMult, nSampleFormat, pszResampling );
674 #ifdef DBMALLOC
675                 malloc_chain_check( 1 );
676 #endif
677             }
678         }
679     }
680 }
681 
682 /************************************************************************/
683 /*                        TIFF_BuildOverviews()                         */
684 /*                                                                      */
685 /*      Build the requested list of overviews.  Overviews are           */
686 /*      maintained in a bunch of temporary files and then these are     */
687 /*      written back to the TIFF file.  Only one pass through the       */
688 /*      source TIFF file is made for any number of output               */
689 /*      overviews.                                                      */
690 /************************************************************************/
691 
TIFFBuildOverviews(TIFF * hTIFF,int nOverviews,int * panOvList,int bUseSubIFDs,const char * pszResampleMethod,int (* pfnProgress)(double,void *),void * pProgressData)692 void TIFFBuildOverviews( TIFF *hTIFF, int nOverviews, int * panOvList,
693                          int bUseSubIFDs, const char *pszResampleMethod,
694                          int (*pfnProgress)( double, void * ),
695                          void * pProgressData )
696 
697 {
698     TIFFOvrCache	**papoRawBIs;
699     uint32		nXSize, nYSize, nBlockXSize, nBlockYSize;
700     uint16		nBitsPerPixel, nPhotometric, nCompressFlag, nSamples,
701         nPlanarConfig, nSampleFormat;
702     int         bSubsampled;
703     uint16      nHorSubsampling, nVerSubsampling;
704     int			bTiled, nSXOff, nSYOff, i;
705     unsigned char	*pabySrcTile;
706     uint16		*panRedMap, *panGreenMap, *panBlueMap;
707     TIFFErrorHandler    pfnWarning;
708 
709 /* -------------------------------------------------------------------- */
710 /*      Get the base raster size.                                       */
711 /* -------------------------------------------------------------------- */
712     TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &nXSize );
713     TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &nYSize );
714 
715     TIFFGetField( hTIFF, TIFFTAG_BITSPERSAMPLE, &nBitsPerPixel );
716     /* TODO: nBitsPerPixel seems misnomer and may need renaming to nBitsPerSample */
717     TIFFGetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, &nSamples );
718     TIFFGetFieldDefaulted( hTIFF, TIFFTAG_PLANARCONFIG, &nPlanarConfig );
719 
720     TIFFGetFieldDefaulted( hTIFF, TIFFTAG_PHOTOMETRIC, &nPhotometric );
721     TIFFGetFieldDefaulted( hTIFF, TIFFTAG_COMPRESSION, &nCompressFlag );
722     TIFFGetFieldDefaulted( hTIFF, TIFFTAG_SAMPLEFORMAT, &nSampleFormat );
723 
724     if( nPhotometric == PHOTOMETRIC_YCBCR || nPhotometric == PHOTOMETRIC_ITULAB )
725     {
726         if( nBitsPerPixel != 8 || nSamples != 3 || nPlanarConfig != PLANARCONFIG_CONTIG ||
727             nSampleFormat != SAMPLEFORMAT_UINT)
728         {
729             /* TODO: use of TIFFError is inconsistent with use of fprintf in addtiffo.c, sort out */
730             TIFFErrorExt( TIFFClientdata(hTIFF), "TIFFBuildOverviews",
731                           "File `%s' has an unsupported subsampling configuration.\n",
732                           TIFFFileName(hTIFF) );
733             /* If you need support for this particular flavor, please contact either
734              * Frank Warmerdam warmerdam@pobox.com
735              * Joris Van Damme info@awaresystems.be
736              */
737             return;
738         }
739         bSubsampled = 1;
740         TIFFGetField( hTIFF, TIFFTAG_YCBCRSUBSAMPLING, &nHorSubsampling, &nVerSubsampling );
741         /* TODO: find out if maybe TIFFGetFieldDefaulted is better choice for YCbCrSubsampling tag */
742     }
743     else
744     {
745         if( nBitsPerPixel < 8 )
746         {
747             /* TODO: use of TIFFError is inconsistent with use of fprintf in addtiffo.c, sort out */
748             TIFFErrorExt( TIFFClientdata(hTIFF), "TIFFBuildOverviews",
749                           "File `%s' has samples of %d bits per sample.  Sample\n"
750                           "sizes of less than 8 bits per sample are not supported.\n",
751                           TIFFFileName(hTIFF), nBitsPerPixel );
752             return;
753         }
754         bSubsampled = 0;
755         nHorSubsampling = 1;
756         nVerSubsampling = 1;
757     }
758 
759 /* -------------------------------------------------------------------- */
760 /*      Turn off warnings to avoid alot of repeated warnings while      */
761 /*      rereading directories.                                          */
762 /* -------------------------------------------------------------------- */
763     pfnWarning = TIFFSetWarningHandler( NULL );
764 
765 /* -------------------------------------------------------------------- */
766 /*      Get the base raster block size.                                 */
767 /* -------------------------------------------------------------------- */
768     if( TIFFGetField( hTIFF, TIFFTAG_ROWSPERSTRIP, &(nBlockYSize) ) )
769     {
770         nBlockXSize = nXSize;
771         bTiled = FALSE;
772     }
773     else
774     {
775         TIFFGetField( hTIFF, TIFFTAG_TILEWIDTH, &nBlockXSize );
776         TIFFGetField( hTIFF, TIFFTAG_TILELENGTH, &nBlockYSize );
777         bTiled = TRUE;
778     }
779 
780 /* -------------------------------------------------------------------- */
781 /*	Capture the pallette if there is one.				*/
782 /* -------------------------------------------------------------------- */
783     if( TIFFGetField( hTIFF, TIFFTAG_COLORMAP,
784                       &panRedMap, &panGreenMap, &panBlueMap ) )
785     {
786         uint16		*panRed2, *panGreen2, *panBlue2;
787         int             nColorCount = 1 << nBitsPerPixel;
788 
789         panRed2 = (uint16 *) _TIFFmalloc(2*nColorCount);
790         panGreen2 = (uint16 *) _TIFFmalloc(2*nColorCount);
791         panBlue2 = (uint16 *) _TIFFmalloc(2*nColorCount);
792 
793         memcpy( panRed2, panRedMap, 2 * nColorCount );
794         memcpy( panGreen2, panGreenMap, 2 * nColorCount );
795         memcpy( panBlue2, panBlueMap, 2 * nColorCount );
796 
797         panRedMap = panRed2;
798         panGreenMap = panGreen2;
799         panBlueMap = panBlue2;
800     }
801     else
802     {
803         panRedMap = panGreenMap = panBlueMap = NULL;
804     }
805 
806 /* -------------------------------------------------------------------- */
807 /*      Initialize overviews.                                           */
808 /* -------------------------------------------------------------------- */
809     papoRawBIs = (TIFFOvrCache **) _TIFFmalloc(nOverviews*sizeof(void*));
810 
811     for( i = 0; i < nOverviews; i++ )
812     {
813         int	nOXSize, nOYSize, nOBlockXSize, nOBlockYSize;
814         uint32  nDirOffset;
815 
816         nOXSize = (nXSize + panOvList[i] - 1) / panOvList[i];
817         nOYSize = (nYSize + panOvList[i] - 1) / panOvList[i];
818 
819         nOBlockXSize = MIN((int)nBlockXSize,nOXSize);
820         nOBlockYSize = MIN((int)nBlockYSize,nOYSize);
821 
822         if( bTiled )
823         {
824             if( (nOBlockXSize % 16) != 0 )
825                 nOBlockXSize = nOBlockXSize + 16 - (nOBlockXSize % 16);
826 
827             if( (nOBlockYSize % 16) != 0 )
828                 nOBlockYSize = nOBlockYSize + 16 - (nOBlockYSize % 16);
829         }
830 
831         nDirOffset = TIFF_WriteOverview( hTIFF, nOXSize, nOYSize,
832                                          nBitsPerPixel, nPlanarConfig,
833                                          nSamples, nOBlockXSize, nOBlockYSize,
834                                          bTiled, nCompressFlag, nPhotometric,
835                                          nSampleFormat,
836                                          panRedMap, panGreenMap, panBlueMap,
837                                          bUseSubIFDs,
838                                          nHorSubsampling, nVerSubsampling );
839 
840         papoRawBIs[i] = TIFFCreateOvrCache( hTIFF, nDirOffset );
841     }
842 
843     if( panRedMap != NULL )
844     {
845         _TIFFfree( panRedMap );
846         _TIFFfree( panGreenMap );
847         _TIFFfree( panBlueMap );
848     }
849 
850 /* -------------------------------------------------------------------- */
851 /*      Allocate a buffer to hold a source block.                       */
852 /* -------------------------------------------------------------------- */
853     if( bTiled )
854         pabySrcTile = (unsigned char *) _TIFFmalloc(TIFFTileSize(hTIFF));
855     else
856         pabySrcTile = (unsigned char *) _TIFFmalloc(TIFFStripSize(hTIFF));
857 
858 /* -------------------------------------------------------------------- */
859 /*      Loop over the source raster, applying data to the               */
860 /*      destination raster.                                             */
861 /* -------------------------------------------------------------------- */
862     for( nSYOff = 0; nSYOff < (int) nYSize; nSYOff += nBlockYSize )
863     {
864         for( nSXOff = 0; nSXOff < (int) nXSize; nSXOff += nBlockXSize )
865         {
866             /*
867              * Read and resample into the various overview images.
868              */
869 
870             TIFF_ProcessFullResBlock( hTIFF, nPlanarConfig,
871                                       bSubsampled,nHorSubsampling,nVerSubsampling,
872                                       nOverviews, panOvList,
873                                       nBitsPerPixel, nSamples, papoRawBIs,
874                                       nSXOff, nSYOff, pabySrcTile,
875                                       nBlockXSize, nBlockYSize,
876                                       nSampleFormat, pszResampleMethod );
877         }
878     }
879 
880     _TIFFfree( pabySrcTile );
881 
882 /* -------------------------------------------------------------------- */
883 /*      Cleanup the rawblockedimage files.                              */
884 /* -------------------------------------------------------------------- */
885     for( i = 0; i < nOverviews; i++ )
886     {
887         TIFFDestroyOvrCache( papoRawBIs[i] );
888     }
889 
890     if( papoRawBIs != NULL )
891         _TIFFfree( papoRawBIs );
892 
893     TIFFSetWarningHandler( pfnWarning );
894 }
895 
896 
897