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