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, [email protected]
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     size_t      tpadfSamples_size, padfSamples_size;
276 
277     assert( nBitsPerPixel >= 8 );
278 
279     /* sizeof(double) * nOMult * nOMult */
280     tpadfSamples_size=nOMult*nOMult;
281     if ((nOMult != 0) && (tpadfSamples_size/nOMult == (size_t) nOMult)) {
282         padfSamples_size=tpadfSamples_size;
283         tpadfSamples_size=padfSamples_size*sizeof(double);
284         if ((tpadfSamples_size / padfSamples_size) == sizeof(double))
285             padfSamples_size=tpadfSamples_size;
286         else
287             padfSamples_size=0;
288     } else {
289         padfSamples_size=0;
290     }
291     if (padfSamples_size == 0) {
292         /* TODO: This is an error condition */
293         return;
294     }
295     padfSamples = (double *) malloc(padfSamples_size);
296 
297 /* ==================================================================== */
298 /*      Loop over scanline chunks to process, establishing where the    */
299 /*      data is going.                                                  */
300 /* ==================================================================== */
301     for( j = 0; j*nOMult < nBlockYSize; j++ )
302     {
303         if( j + nTYOff >= nOBlockYSize )
304             break;
305 
306         pabyDst = pabyOTile + ((j+nTYOff)*nOBlockXSize + nTXOff)
307             * nPixelBytes * nPixelGroupBytes;
308 
309 /* -------------------------------------------------------------------- */
310 /*      Handler nearest resampling ... we don't even care about the     */
311 /*      data type, we just do a bytewise copy.                          */
312 /* -------------------------------------------------------------------- */
313         if( strncmp(pszResampling,"nearest",4) == 0
314             || strncmp(pszResampling,"NEAR",4) == 0 )
315         {
316             pabySrc = pabySrcTile + j*nOMult*nBlockXSize * nPixelGroupBytes;
317 
318             for( i = 0; i*nOMult < nBlockXSize; i++ )
319             {
320                 if( i + nTXOff >= nOBlockXSize )
321                     break;
322 
323                 /*
324                  * For now use simple subsampling, from the top left corner
325                  * of the source block of pixels.
326                  */
327 
328                 for( k = 0; k < nPixelBytes; k++ )
329                     pabyDst[k] = pabySrc[k];
330 
331                 pabyDst += nPixelBytes * nPixelGroupBytes;
332                 pabySrc += nOMult * nPixelGroupBytes;
333             }
334         }
335 
336 /* -------------------------------------------------------------------- */
337 /*      Handle the case of averaging.  For this we also have to         */
338 /*      handle each sample format we are concerned with.                */
339 /* -------------------------------------------------------------------- */
340         else if( strncmp(pszResampling,"averag",6) == 0
341                  || strncmp(pszResampling,"AVERAG",6) == 0 )
342         {
343             pabySrc = pabySrcTile + j*nOMult*nBlockXSize * nPixelGroupBytes;
344 
345             for( i = 0; i*nOMult < nBlockXSize; i++ )
346             {
347                 double   dfTotal;
348                 uint32   nXSize, nYSize, iSample;
349 
350                 if( i + nTXOff >= nOBlockXSize )
351                     break;
352 
353                 nXSize = MIN((uint32)nOMult,nBlockXSize-i);
354                 nYSize = MIN((uint32)nOMult,nBlockYSize-j);
355 
356                 TIFF_GetSourceSamples( padfSamples, pabySrc,
357                                        nPixelBytes, nSampleFormat,
358                                        nXSize, nYSize,
359                                        nPixelGroupBytes,
360                                        nPixelGroupBytes * nBlockXSize );
361 
362                 dfTotal = 0;
363                 for( iSample = 0; iSample < nXSize*nYSize; iSample++ )
364                 {
365                     dfTotal += padfSamples[iSample];
366                 }
367 
368                 TIFF_SetSample( pabyDst, nPixelBytes, nSampleFormat,
369                                 dfTotal / (nXSize*nYSize) );
370 
371                 pabySrc += nOMult * nPixelGroupBytes;
372                 pabyDst += nPixelBytes;
373             }
374         }
375     }
376 
377     free( padfSamples );
378 }
379 
380 /************************************************************************/
381 /*                     TIFF_DownSample_Subsampled()                     */
382 /************************************************************************/
383 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)384 void TIFF_DownSample_Subsampled( unsigned char *pabySrcTile, int nSample,
385                                  uint32 nBlockXSize, uint32 nBlockYSize,
386                                  unsigned char * pabyOTile,
387                                  uint32 nOBlockXSize, uint32 nOBlockYSize,
388                                  uint32 nTXOff, uint32 nTYOff, int nOMult,
389                                  const char *pszResampling,
390                                  int nHorSubsampling, int nVerSubsampling )
391 {
392     /* TODO: test with variety of subsampling values, and incovinient tile/strip sizes */
393     int nSampleBlockSize;
394     int nSourceSampleRowSize;
395     int nDestSampleRowSize;
396     uint32  nSourceX, nSourceY;
397     uint32  nSourceXSec, nSourceYSec;
398     uint32  nSourceXSecEnd, nSourceYSecEnd;
399     uint32  nDestX, nDestY;
400     int nSampleOffsetInSampleBlock;
401     unsigned int nCummulator;
402     unsigned int nCummulatorCount;
403 
404     nSampleBlockSize = nHorSubsampling * nVerSubsampling + 2;
405     nSourceSampleRowSize =
406         ( ( nBlockXSize + nHorSubsampling - 1 ) / nHorSubsampling ) * nSampleBlockSize;
407     nDestSampleRowSize =
408         ( ( nOBlockXSize + nHorSubsampling - 1 ) / nHorSubsampling ) * nSampleBlockSize;
409 
410     if( strncmp(pszResampling,"nearest",4) == 0
411         || strncmp(pszResampling,"NEAR",4) == 0 )
412     {
413     	if( nSample == 0 )
414         {
415             for( nSourceY = 0, nDestY = nTYOff;
416                  nSourceY < nBlockYSize;
417                  nSourceY += nOMult, nDestY ++)
418             {
419                 if( nDestY >= nOBlockYSize )
420                     break;
421 
422                 for( nSourceX = 0, nDestX = nTXOff;
423                      nSourceX < nBlockXSize;
424                      nSourceX += nOMult, nDestX ++)
425                 {
426                     if( nDestX >= nOBlockXSize )
427                         break;
428 
429                     * ( pabyOTile + ( nDestY / nVerSubsampling ) * nDestSampleRowSize
430                         + ( nDestY % nVerSubsampling ) * nHorSubsampling
431                         + ( nDestX / nHorSubsampling ) * nSampleBlockSize
432                         + ( nDestX % nHorSubsampling ) ) =
433                         * ( pabySrcTile + ( nSourceY / nVerSubsampling ) * nSourceSampleRowSize
434                             + ( nSourceY % nVerSubsampling ) * nHorSubsampling
435                             + ( nSourceX / nHorSubsampling ) * nSampleBlockSize
436                             + ( nSourceX % nHorSubsampling ) );
437                 }
438             }
439         }
440         else
441         {
442             nSampleOffsetInSampleBlock = nHorSubsampling * nVerSubsampling + nSample - 1;
443             for( nSourceY = 0, nDestY = ( nTYOff / nVerSubsampling );
444                  nSourceY < ( nBlockYSize / nVerSubsampling );
445                  nSourceY += nOMult, nDestY ++)
446             {
447                 if( nDestY*nVerSubsampling >= nOBlockYSize )
448                     break;
449 
450             	for( nSourceX = 0, nDestX = ( nTXOff / nHorSubsampling );
451                      nSourceX < ( nBlockXSize / nHorSubsampling );
452                      nSourceX += nOMult, nDestX ++)
453                 {
454                     if( nDestX*nHorSubsampling >= nOBlockXSize )
455                         break;
456 
457                     * ( pabyOTile + nDestY * nDestSampleRowSize
458                         + nDestX * nSampleBlockSize
459                         + nSampleOffsetInSampleBlock ) =
460                     	* ( pabySrcTile + nSourceY * nSourceSampleRowSize
461                             + nSourceX * nSampleBlockSize
462                             + nSampleOffsetInSampleBlock );
463                 }
464             }
465         }
466     }
467     else if( strncmp(pszResampling,"averag",6) == 0
468              || strncmp(pszResampling,"AVERAG",6) == 0 )
469     {
470     	if( nSample == 0 )
471         {
472             for( nSourceY = 0, nDestY = nTYOff; nSourceY < nBlockYSize; nSourceY += nOMult, nDestY ++)
473             {
474                 if( nDestY >= nOBlockYSize )
475                     break;
476 
477                 for( nSourceX = 0, nDestX = nTXOff; nSourceX < nBlockXSize; nSourceX += nOMult, nDestX ++)
478                 {
479                     if( nDestX >= nOBlockXSize )
480                         break;
481 
482                     nSourceXSecEnd = nSourceX + nOMult;
483                     if( nSourceXSecEnd > nBlockXSize )
484                         nSourceXSecEnd = nBlockXSize;
485                     nSourceYSecEnd = nSourceY + nOMult;
486                     if( nSourceYSecEnd > nBlockYSize )
487                         nSourceYSecEnd = nBlockYSize;
488                     nCummulator = 0;
489                     for( nSourceYSec = nSourceY; nSourceYSec < nSourceYSecEnd; nSourceYSec ++)
490                     {
491                         for( nSourceXSec = nSourceX; nSourceXSec < nSourceXSecEnd; nSourceXSec ++)
492                         {
493                             nCummulator += * ( pabySrcTile + ( nSourceYSec / nVerSubsampling ) * nSourceSampleRowSize
494                                                + ( nSourceYSec % nVerSubsampling ) * nHorSubsampling
495                                                + ( nSourceXSec / nHorSubsampling ) * nSampleBlockSize
496                                                + ( nSourceXSec % nHorSubsampling ) );
497                         }
498                     }
499                     nCummulatorCount = ( nSourceXSecEnd - nSourceX ) * ( nSourceYSecEnd - nSourceY );
500                     * ( pabyOTile + ( nDestY / nVerSubsampling ) * nDestSampleRowSize
501                         + ( nDestY % nVerSubsampling ) * nHorSubsampling
502                         + ( nDestX / nHorSubsampling ) * nSampleBlockSize
503                         + ( nDestX % nHorSubsampling ) ) =
504                         ( ( nCummulator + ( nCummulatorCount >> 1 ) ) / nCummulatorCount );
505                 }
506             }
507         }
508         else
509         {
510             nSampleOffsetInSampleBlock = nHorSubsampling * nVerSubsampling + nSample - 1;
511             for( nSourceY = 0, nDestY = ( nTYOff / nVerSubsampling ); nSourceY < ( nBlockYSize / nVerSubsampling );
512                  nSourceY += nOMult, nDestY ++)
513             {
514                 if( nDestY*nVerSubsampling >= nOBlockYSize )
515                     break;
516 
517                 for( nSourceX = 0, nDestX = ( nTXOff / nHorSubsampling ); nSourceX < ( nBlockXSize / nHorSubsampling );
518                      nSourceX += nOMult, nDestX ++)
519                 {
520                     if( nDestX*nHorSubsampling >= nOBlockXSize )
521                         break;
522 
523                     nSourceXSecEnd = nSourceX + nOMult;
524                     if( nSourceXSecEnd > ( nBlockXSize / nHorSubsampling ) )
525                         nSourceXSecEnd = ( nBlockXSize / nHorSubsampling );
526                     nSourceYSecEnd = nSourceY + nOMult;
527                     if( nSourceYSecEnd > ( nBlockYSize / nVerSubsampling ) )
528                         nSourceYSecEnd = ( nBlockYSize / nVerSubsampling );
529                     nCummulator = 0;
530                     for( nSourceYSec = nSourceY; nSourceYSec < nSourceYSecEnd; nSourceYSec ++)
531                     {
532                         for( nSourceXSec = nSourceX; nSourceXSec < nSourceXSecEnd; nSourceXSec ++)
533                         {
534                             nCummulator += * ( pabySrcTile + nSourceYSec * nSourceSampleRowSize
535                                                + nSourceXSec * nSampleBlockSize
536                                                + nSampleOffsetInSampleBlock );
537                         }
538                     }
539                     nCummulatorCount = ( nSourceXSecEnd - nSourceX ) * ( nSourceYSecEnd - nSourceY );
540                     * ( pabyOTile + nDestY * nDestSampleRowSize
541                         + nDestX * nSampleBlockSize
542                         + nSampleOffsetInSampleBlock ) =
543                         ( ( nCummulator + ( nCummulatorCount >> 1 ) ) / nCummulatorCount );
544                 }
545             }
546         }
547     }
548 }
549 
550 /************************************************************************/
551 /*                      TIFF_ProcessFullResBlock()                      */
552 /*                                                                      */
553 /*      Process one block of full res data, downsampling into each      */
554 /*      of the overviews.                                               */
555 /************************************************************************/
556 
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)557 void TIFF_ProcessFullResBlock( TIFF *hTIFF, int nPlanarConfig,
558                                int bSubsampled,
559                                int nHorSubsampling, int nVerSubsampling,
560                                int nOverviews, int * panOvList,
561                                int nBitsPerPixel,
562                                int nSamples, TIFFOvrCache ** papoRawBIs,
563                                uint32 nSXOff, uint32 nSYOff,
564                                unsigned char *pabySrcTile,
565                                uint32 nBlockXSize, uint32 nBlockYSize,
566                                int nSampleFormat, const char * pszResampling )
567 
568 {
569     int		iOverview, iSample;
570 
571     for( iSample = 0; iSample < nSamples; iSample++ )
572     {
573         /*
574          * We have to read a tile/strip for each sample for
575          * PLANARCONFIG_SEPARATE.  Otherwise, we just read all the samples
576          * at once when handling the first sample.
577          */
578         if( nPlanarConfig == PLANARCONFIG_SEPARATE || iSample == 0 )
579         {
580             if( TIFFIsTiled(hTIFF) )
581             {
582                 TIFFReadEncodedTile( hTIFF,
583                                      TIFFComputeTile(hTIFF, nSXOff, nSYOff,
584                                                      0, (tsample_t)iSample ),
585                                      pabySrcTile,
586                                      TIFFTileSize(hTIFF));
587             }
588             else
589             {
590                 TIFFReadEncodedStrip( hTIFF,
591                                       TIFFComputeStrip(hTIFF, nSYOff,
592                                                        (tsample_t) iSample),
593                                       pabySrcTile,
594                                       TIFFStripSize(hTIFF) );
595             }
596         }
597 
598         /*
599          * Loop over destination overview layers
600          */
601         for( iOverview = 0; iOverview < nOverviews; iOverview++ )
602         {
603             TIFFOvrCache *poRBI = papoRawBIs[iOverview];
604             unsigned char *pabyOTile;
605             uint32  nTXOff, nTYOff, nOXOff, nOYOff, nOMult;
606             uint32  nOBlockXSize = poRBI->nBlockXSize;
607             uint32  nOBlockYSize = poRBI->nBlockYSize;
608             int     nSkewBits, nSampleByteOffset;
609 
610             /*
611              * Fetch the destination overview tile
612              */
613             nOMult = panOvList[iOverview];
614             nOXOff = (nSXOff/nOMult) / nOBlockXSize;
615             nOYOff = (nSYOff/nOMult) / nOBlockYSize;
616 
617             if( bSubsampled )
618             {
619                 pabyOTile = TIFFGetOvrBlock_Subsampled( poRBI, nOXOff, nOYOff );
620 
621                 /*
622                  * Establish the offset into this tile at which we should
623                  * start placing data.
624                  */
625                 nTXOff = (nSXOff - nOXOff*nOMult*nOBlockXSize) / nOMult;
626                 nTYOff = (nSYOff - nOYOff*nOMult*nOBlockYSize) / nOMult;
627 
628 
629 #ifdef DBMALLOC
630                 malloc_chain_check( 1 );
631 #endif
632                 TIFF_DownSample_Subsampled( pabySrcTile, iSample,
633                                             nBlockXSize, nBlockYSize,
634                                             pabyOTile,
635                                             poRBI->nBlockXSize, poRBI->nBlockYSize,
636                                             nTXOff, nTYOff,
637                                             nOMult, pszResampling,
638                                             nHorSubsampling, nVerSubsampling );
639 #ifdef DBMALLOC
640                 malloc_chain_check( 1 );
641 #endif
642 
643             }
644             else
645             {
646 
647                 pabyOTile = TIFFGetOvrBlock( poRBI, nOXOff, nOYOff, iSample );
648 
649                 /*
650                  * Establish the offset into this tile at which we should
651                  * start placing data.
652                  */
653                 nTXOff = (nSXOff - nOXOff*nOMult*nOBlockXSize) / nOMult;
654                 nTYOff = (nSYOff - nOYOff*nOMult*nOBlockYSize) / nOMult;
655 
656                 /*
657                  * Figure out the skew (extra space between ``our samples'') and
658                  * the byte offset to the first sample.
659                  */
660                 assert( (nBitsPerPixel % 8) == 0 );
661                 if( nPlanarConfig == PLANARCONFIG_SEPARATE )
662                 {
663                     nSkewBits = 0;
664                     nSampleByteOffset = 0;
665                 }
666                 else
667                 {
668                     nSkewBits = nBitsPerPixel * (nSamples-1);
669                     nSampleByteOffset = (nBitsPerPixel/8) * iSample;
670                 }
671 
672                 /*
673                  * Perform the downsampling.
674                  */
675 #ifdef DBMALLOC
676                 malloc_chain_check( 1 );
677 #endif
678                 TIFF_DownSample( pabySrcTile + nSampleByteOffset,
679                                nBlockXSize, nBlockYSize,
680                                nSkewBits, nBitsPerPixel, pabyOTile,
681                                poRBI->nBlockXSize, poRBI->nBlockYSize,
682                                nTXOff, nTYOff,
683                                nOMult, nSampleFormat, pszResampling );
684 #ifdef DBMALLOC
685                 malloc_chain_check( 1 );
686 #endif
687             }
688         }
689     }
690 }
691 
692 /************************************************************************/
693 /*                        TIFF_BuildOverviews()                         */
694 /*                                                                      */
695 /*      Build the requested list of overviews.  Overviews are           */
696 /*      maintained in a bunch of temporary files and then these are     */
697 /*      written back to the TIFF file.  Only one pass through the       */
698 /*      source TIFF file is made for any number of output               */
699 /*      overviews.                                                      */
700 /************************************************************************/
701 
TIFFBuildOverviews(TIFF * hTIFF,int nOverviews,int * panOvList,int bUseSubIFDs,const char * pszResampleMethod,int (* pfnProgress)(double,void *),void * pProgressData)702 void TIFFBuildOverviews( TIFF *hTIFF, int nOverviews, int * panOvList,
703                          int bUseSubIFDs, const char *pszResampleMethod,
704                          int (*pfnProgress)( double, void * ),
705                          void * pProgressData )
706 
707 {
708     TIFFOvrCache	**papoRawBIs;
709     uint32		nXSize, nYSize, nBlockXSize, nBlockYSize;
710     uint16		nBitsPerPixel, nPhotometric, nCompressFlag, nSamples,
711         nPlanarConfig, nSampleFormat;
712     int         bSubsampled;
713     uint16      nHorSubsampling, nVerSubsampling;
714     int			bTiled, nSXOff, nSYOff, i;
715     unsigned char	*pabySrcTile;
716     uint16		*panRedMap, *panGreenMap, *panBlueMap;
717     TIFFErrorHandler    pfnWarning;
718 
719     (void) pfnProgress;
720     (void) pProgressData;
721 
722 /* -------------------------------------------------------------------- */
723 /*      Get the base raster size.                                       */
724 /* -------------------------------------------------------------------- */
725     TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &nXSize );
726     TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &nYSize );
727 
728     TIFFGetField( hTIFF, TIFFTAG_BITSPERSAMPLE, &nBitsPerPixel );
729     /* TODO: nBitsPerPixel seems misnomer and may need renaming to nBitsPerSample */
730     TIFFGetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, &nSamples );
731     TIFFGetFieldDefaulted( hTIFF, TIFFTAG_PLANARCONFIG, &nPlanarConfig );
732 
733     TIFFGetFieldDefaulted( hTIFF, TIFFTAG_PHOTOMETRIC, &nPhotometric );
734     TIFFGetFieldDefaulted( hTIFF, TIFFTAG_COMPRESSION, &nCompressFlag );
735     TIFFGetFieldDefaulted( hTIFF, TIFFTAG_SAMPLEFORMAT, &nSampleFormat );
736 
737     if( nPhotometric == PHOTOMETRIC_YCBCR || nPhotometric == PHOTOMETRIC_ITULAB )
738     {
739         if( nBitsPerPixel != 8 || nSamples != 3 || nPlanarConfig != PLANARCONFIG_CONTIG ||
740             nSampleFormat != SAMPLEFORMAT_UINT)
741         {
742             /* TODO: use of TIFFError is inconsistent with use of fprintf in addtiffo.c, sort out */
743             TIFFErrorExt( TIFFClientdata(hTIFF), "TIFFBuildOverviews",
744                           "File `%s' has an unsupported subsampling configuration.\n",
745                           TIFFFileName(hTIFF) );
746             /* If you need support for this particular flavor, please contact either
747              * Frank Warmerdam [email protected]
748              * Joris Van Damme [email protected]
749              */
750             return;
751         }
752         bSubsampled = 1;
753         TIFFGetField( hTIFF, TIFFTAG_YCBCRSUBSAMPLING, &nHorSubsampling, &nVerSubsampling );
754         /* TODO: find out if maybe TIFFGetFieldDefaulted is better choice for YCbCrSubsampling tag */
755     }
756     else
757     {
758         if( nBitsPerPixel < 8 )
759         {
760             /* TODO: use of TIFFError is inconsistent with use of fprintf in addtiffo.c, sort out */
761             TIFFErrorExt( TIFFClientdata(hTIFF), "TIFFBuildOverviews",
762                           "File `%s' has samples of %d bits per sample.  Sample\n"
763                           "sizes of less than 8 bits per sample are not supported.\n",
764                           TIFFFileName(hTIFF), nBitsPerPixel );
765             return;
766         }
767         bSubsampled = 0;
768         nHorSubsampling = 1;
769         nVerSubsampling = 1;
770     }
771 
772 /* -------------------------------------------------------------------- */
773 /*      Turn off warnings to avoid alot of repeated warnings while      */
774 /*      rereading directories.                                          */
775 /* -------------------------------------------------------------------- */
776     pfnWarning = TIFFSetWarningHandler( NULL );
777 
778 /* -------------------------------------------------------------------- */
779 /*      Get the base raster block size.                                 */
780 /* -------------------------------------------------------------------- */
781     if( TIFFGetField( hTIFF, TIFFTAG_ROWSPERSTRIP, &(nBlockYSize) ) )
782     {
783         nBlockXSize = nXSize;
784         bTiled = FALSE;
785     }
786     else
787     {
788         TIFFGetField( hTIFF, TIFFTAG_TILEWIDTH, &nBlockXSize );
789         TIFFGetField( hTIFF, TIFFTAG_TILELENGTH, &nBlockYSize );
790         bTiled = TRUE;
791     }
792 
793 /* -------------------------------------------------------------------- */
794 /*	Capture the pallette if there is one.				*/
795 /* -------------------------------------------------------------------- */
796     if( TIFFGetField( hTIFF, TIFFTAG_COLORMAP,
797                       &panRedMap, &panGreenMap, &panBlueMap ) )
798     {
799         uint16		*panRed2, *panGreen2, *panBlue2;
800         int             nColorCount = 1 << nBitsPerPixel;
801 
802         panRed2 = (uint16 *) _TIFFmalloc(2*nColorCount);
803         panGreen2 = (uint16 *) _TIFFmalloc(2*nColorCount);
804         panBlue2 = (uint16 *) _TIFFmalloc(2*nColorCount);
805 
806         memcpy( panRed2, panRedMap, 2 * nColorCount );
807         memcpy( panGreen2, panGreenMap, 2 * nColorCount );
808         memcpy( panBlue2, panBlueMap, 2 * nColorCount );
809 
810         panRedMap = panRed2;
811         panGreenMap = panGreen2;
812         panBlueMap = panBlue2;
813     }
814     else
815     {
816         panRedMap = panGreenMap = panBlueMap = NULL;
817     }
818 
819 /* -------------------------------------------------------------------- */
820 /*      Initialize overviews.                                           */
821 /* -------------------------------------------------------------------- */
822     papoRawBIs = (TIFFOvrCache **) _TIFFmalloc(nOverviews*sizeof(void*));
823 
824     for( i = 0; i < nOverviews; i++ )
825     {
826         uint32  nOXSize, nOYSize, nOBlockXSize, nOBlockYSize;
827         toff_t  nDirOffset;
828 
829         nOXSize = (nXSize + panOvList[i] - 1) / panOvList[i];
830         nOYSize = (nYSize + panOvList[i] - 1) / panOvList[i];
831 
832         nOBlockXSize = MIN(nBlockXSize,nOXSize);
833         nOBlockYSize = MIN(nBlockYSize,nOYSize);
834 
835         if( bTiled )
836         {
837             if( (nOBlockXSize % 16) != 0 )
838                 nOBlockXSize = nOBlockXSize + 16 - (nOBlockXSize % 16);
839 
840             if( (nOBlockYSize % 16) != 0 )
841                 nOBlockYSize = nOBlockYSize + 16 - (nOBlockYSize % 16);
842         }
843 
844         nDirOffset = TIFF_WriteOverview( hTIFF, nOXSize, nOYSize,
845                                          nBitsPerPixel, nPlanarConfig,
846                                          nSamples, nOBlockXSize, nOBlockYSize,
847                                          bTiled, nCompressFlag, nPhotometric,
848                                          nSampleFormat,
849                                          panRedMap, panGreenMap, panBlueMap,
850                                          bUseSubIFDs,
851                                          nHorSubsampling, nVerSubsampling );
852 
853         papoRawBIs[i] = TIFFCreateOvrCache( hTIFF, nDirOffset );
854     }
855 
856     if( panRedMap != NULL )
857     {
858         _TIFFfree( panRedMap );
859         _TIFFfree( panGreenMap );
860         _TIFFfree( panBlueMap );
861     }
862 
863 /* -------------------------------------------------------------------- */
864 /*      Allocate a buffer to hold a source block.                       */
865 /* -------------------------------------------------------------------- */
866     if( bTiled )
867         pabySrcTile = (unsigned char *) _TIFFmalloc(TIFFTileSize(hTIFF));
868     else
869         pabySrcTile = (unsigned char *) _TIFFmalloc(TIFFStripSize(hTIFF));
870 
871 /* -------------------------------------------------------------------- */
872 /*      Loop over the source raster, applying data to the               */
873 /*      destination raster.                                             */
874 /* -------------------------------------------------------------------- */
875     for( nSYOff = 0; nSYOff < (int) nYSize; nSYOff += nBlockYSize )
876     {
877         for( nSXOff = 0; nSXOff < (int) nXSize; nSXOff += nBlockXSize )
878         {
879             /*
880              * Read and resample into the various overview images.
881              */
882 
883             TIFF_ProcessFullResBlock( hTIFF, nPlanarConfig,
884                                       bSubsampled,nHorSubsampling,nVerSubsampling,
885                                       nOverviews, panOvList,
886                                       nBitsPerPixel, nSamples, papoRawBIs,
887                                       nSXOff, nSYOff, pabySrcTile,
888                                       nBlockXSize, nBlockYSize,
889                                       nSampleFormat, pszResampleMethod );
890         }
891     }
892 
893     _TIFFfree( pabySrcTile );
894 
895 /* -------------------------------------------------------------------- */
896 /*      Cleanup the rawblockedimage files.                              */
897 /* -------------------------------------------------------------------- */
898     for( i = 0; i < nOverviews; i++ )
899     {
900         TIFFDestroyOvrCache( papoRawBIs[i] );
901     }
902 
903     if( papoRawBIs != NULL )
904         _TIFFfree( papoRawBIs );
905 
906     TIFFSetWarningHandler( pfnWarning );
907 }
908 
909 
910 /*
911  * Local Variables:
912  * mode: c
913  * c-basic-offset: 4
914  * fill-column: 78
915  * End:
916  */
917