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