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