1 /******************************************************************************
2 * tif_overview.c,v 1.9 2005/05/25 09:03:16 dron Exp
4 * Project: TIFF Overview Builder
5 * Purpose: Library function for building overviews in a TIFF file.
6 * Author: Frank Warmerdam, warmerdam@pobox.com
9 * o Currently only images with bits_per_sample of a multiple of eight
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.
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.
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.
25 ******************************************************************************
26 * Copyright (c) 1999, Frank Warmerdam
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:
35 * The above copyright notice and this permission notice shall be included
36 * in all copies or substantial portions of the Software.
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 ******************************************************************************
48 /* TODO: update notes in header above */
56 #include "tif_ovrcache.h"
64 # define MIN(a,b) ((a<b) ? a : b)
65 # define MAX(a,b) ((a>b) ? a : b)
68 void TIFFBuildOverviews( TIFF
*, int, int *, int, const char *,
69 int (*)(double,void*), void * );
71 /************************************************************************/
72 /* TIFF_WriteOverview() */
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 /************************************************************************/
80 uint32
TIFF_WriteOverview( TIFF
*hTIFF
, int nXSize
, int nYSize
,
81 int nBitsPerPixel
, int nPlanarConfig
, int nSamples
,
82 int nBlockXSize
, int nBlockYSize
,
83 int bTiled
, int nCompressFlag
, int nPhotometric
,
85 unsigned short *panRed
,
86 unsigned short *panGreen
,
87 unsigned short *panBlue
,
89 int nHorSubsampling
, int nVerSubsampling
)
92 uint32 nBaseDirOffset
;
95 nBaseDirOffset
= TIFFCurrentDirOffset( hTIFF
);
97 TIFFCreateDirectory( hTIFF
);
99 /* -------------------------------------------------------------------- */
100 /* Setup TIFF fields. */
101 /* -------------------------------------------------------------------- */
102 TIFFSetField( hTIFF
, TIFFTAG_IMAGEWIDTH
, nXSize
);
103 TIFFSetField( hTIFF
, TIFFTAG_IMAGELENGTH
, nYSize
);
105 TIFFSetField( hTIFF
, TIFFTAG_PLANARCONFIG
, PLANARCONFIG_CONTIG
);
107 TIFFSetField( hTIFF
, TIFFTAG_PLANARCONFIG
, nPlanarConfig
);
109 TIFFSetField( hTIFF
, TIFFTAG_BITSPERSAMPLE
, nBitsPerPixel
);
110 TIFFSetField( hTIFF
, TIFFTAG_SAMPLESPERPIXEL
, nSamples
);
111 TIFFSetField( hTIFF
, TIFFTAG_COMPRESSION
, nCompressFlag
);
112 TIFFSetField( hTIFF
, TIFFTAG_PHOTOMETRIC
, nPhotometric
);
113 TIFFSetField( hTIFF
, TIFFTAG_SAMPLEFORMAT
, nSampleFormat
);
117 TIFFSetField( hTIFF
, TIFFTAG_TILEWIDTH
, nBlockXSize
);
118 TIFFSetField( hTIFF
, TIFFTAG_TILELENGTH
, nBlockYSize
);
121 TIFFSetField( hTIFF
, TIFFTAG_ROWSPERSTRIP
, nBlockYSize
);
123 TIFFSetField( hTIFF
, TIFFTAG_SUBFILETYPE
, FILETYPE_REDUCEDIMAGE
);
125 if( nPhotometric
== PHOTOMETRIC_YCBCR
|| nPhotometric
== PHOTOMETRIC_ITULAB
)
127 TIFFSetField( hTIFF
, TIFFTAG_YCBCRSUBSAMPLING
, nHorSubsampling
, nVerSubsampling
);
128 /* TODO: also write YCbCrPositioning and YCbCrCoefficients tag identical to source IFD */
130 /* TODO: add command-line parameter for selecting jpeg compression quality
131 * that gets ignored when compression isn't jpeg */
133 /* -------------------------------------------------------------------- */
134 /* Write color table if one is present. */
135 /* -------------------------------------------------------------------- */
138 TIFFSetField( hTIFF
, TIFFTAG_COLORMAP
, panRed
, panGreen
, panBlue
);
141 /* -------------------------------------------------------------------- */
142 /* Write directory, and return byte offset. */
143 /* -------------------------------------------------------------------- */
144 if( TIFFWriteCheck( hTIFF
, bTiled
, "TIFFBuildOverviews" ) == 0 )
147 TIFFWriteDirectory( hTIFF
);
148 TIFFSetDirectory( hTIFF
, (tdir_t
) (TIFFNumberOfDirectories(hTIFF
)-1) );
150 nOffset
= TIFFCurrentDirOffset( hTIFF
);
152 TIFFSetSubDirectory( hTIFF
, nBaseDirOffset
);
157 /************************************************************************/
158 /* TIFF_GetSourceSamples() */
159 /************************************************************************/
162 TIFF_GetSourceSamples( double * padfSamples
, unsigned char *pabySrc
,
163 int nPixelBytes
, int nSampleFormat
,
164 int nXSize
, int nYSize
,
165 int nPixelOffset
, int nLineOffset
)
167 int iXOff
, iYOff
, iSample
;
171 for( iYOff
= 0; iYOff
< nYSize
; iYOff
++ )
173 for( iXOff
= 0; iXOff
< nXSize
; iXOff
++ )
175 unsigned char *pabyData
;
177 pabyData
= pabySrc
+ iYOff
* nLineOffset
+ iXOff
* nPixelOffset
;
179 if( nSampleFormat
== SAMPLEFORMAT_UINT
&& nPixelBytes
== 1 )
181 padfSamples
[iSample
++] = *pabyData
;
183 else if( nSampleFormat
== SAMPLEFORMAT_UINT
&& nPixelBytes
== 2 )
185 padfSamples
[iSample
++] = ((uint16
*) pabyData
)[0];
187 else if( nSampleFormat
== SAMPLEFORMAT_UINT
&& nPixelBytes
== 4 )
189 padfSamples
[iSample
++] = ((uint32
*) pabyData
)[0];
191 else if( nSampleFormat
== SAMPLEFORMAT_INT
&& nPixelBytes
== 2 )
193 padfSamples
[iSample
++] = ((int16
*) pabyData
)[0];
195 else if( nSampleFormat
== SAMPLEFORMAT_INT
&& nPixelBytes
== 32 )
197 padfSamples
[iSample
++] = ((int32
*) pabyData
)[0];
199 else if( nSampleFormat
== SAMPLEFORMAT_IEEEFP
&& nPixelBytes
== 4 )
201 padfSamples
[iSample
++] = ((float *) pabyData
)[0];
203 else if( nSampleFormat
== SAMPLEFORMAT_IEEEFP
&& nPixelBytes
== 8 )
205 padfSamples
[iSample
++] = ((double *) pabyData
)[0];
211 /************************************************************************/
212 /* TIFF_SetSample() */
213 /************************************************************************/
216 TIFF_SetSample( unsigned char * pabyData
, int nPixelBytes
, int nSampleFormat
,
220 if( nSampleFormat
== SAMPLEFORMAT_UINT
&& nPixelBytes
== 1 )
222 *pabyData
= (unsigned char) MAX(0,MIN(255,dfValue
));
224 else if( nSampleFormat
== SAMPLEFORMAT_UINT
&& nPixelBytes
== 2 )
226 *((uint16
*)pabyData
) = (uint16
) MAX(0,MIN(65535,dfValue
));
228 else if( nSampleFormat
== SAMPLEFORMAT_UINT
&& nPixelBytes
== 4 )
230 *((uint32
*)pabyData
) = (uint32
) dfValue
;
232 else if( nSampleFormat
== SAMPLEFORMAT_INT
&& nPixelBytes
== 2 )
234 *((int16
*)pabyData
) = (int16
) MAX(-32768,MIN(32767,dfValue
));
236 else if( nSampleFormat
== SAMPLEFORMAT_INT
&& nPixelBytes
== 32 )
238 *((int32
*)pabyData
) = (int32
) dfValue
;
240 else if( nSampleFormat
== SAMPLEFORMAT_IEEEFP
&& nPixelBytes
== 4 )
242 *((float *)pabyData
) = (float) dfValue
;
244 else if( nSampleFormat
== SAMPLEFORMAT_IEEEFP
&& nPixelBytes
== 8 )
246 *((double *)pabyData
) = dfValue
;
250 /************************************************************************/
251 /* TIFF_DownSample() */
253 /* Down sample a tile of full res data into a window of a tile */
254 /* of downsampled data. */
255 /************************************************************************/
258 void TIFF_DownSample( unsigned char *pabySrcTile
,
259 int nBlockXSize
, int nBlockYSize
,
260 int nPixelSkewBits
, int nBitsPerPixel
,
261 unsigned char * pabyOTile
,
262 int nOBlockXSize
, int nOBlockYSize
,
263 int nTXOff
, int nTYOff
, int nOMult
,
264 int nSampleFormat
, const char * pszResampling
)
267 int i
, j
, k
, nPixelBytes
= (nBitsPerPixel
) / 8;
268 int nPixelGroupBytes
= (nBitsPerPixel
+nPixelSkewBits
)/8;
269 unsigned char *pabySrc
, *pabyDst
;
272 assert( nBitsPerPixel
>= 8 );
274 padfSamples
= (double *) malloc(sizeof(double) * nOMult
* nOMult
);
276 /* ==================================================================== */
277 /* Loop over scanline chunks to process, establishing where the */
279 /* ==================================================================== */
280 for( j
= 0; j
*nOMult
< nBlockYSize
; j
++ )
282 if( j
+ nTYOff
>= nOBlockYSize
)
285 pabyDst
= pabyOTile
+ ((j
+nTYOff
)*nOBlockXSize
+ nTXOff
)
286 * nPixelBytes
* nPixelGroupBytes
;
288 /* -------------------------------------------------------------------- */
289 /* Handler nearest resampling ... we don't even care about the */
290 /* data type, we just do a bytewise copy. */
291 /* -------------------------------------------------------------------- */
292 if( strncmp(pszResampling
,"nearest",4) == 0
293 || strncmp(pszResampling
,"NEAR",4) == 0 )
295 pabySrc
= pabySrcTile
+ j
*nOMult
*nBlockXSize
* nPixelGroupBytes
;
297 for( i
= 0; i
*nOMult
< nBlockXSize
; i
++ )
299 if( i
+ nTXOff
>= nOBlockXSize
)
303 * For now use simple subsampling, from the top left corner
304 * of the source block of pixels.
307 for( k
= 0; k
< nPixelBytes
; k
++ )
308 pabyDst
[k
] = pabySrc
[k
];
310 pabyDst
+= nPixelBytes
* nPixelGroupBytes
;
311 pabySrc
+= nOMult
* nPixelGroupBytes
;
315 /* -------------------------------------------------------------------- */
316 /* Handle the case of averaging. For this we also have to */
317 /* handle each sample format we are concerned with. */
318 /* -------------------------------------------------------------------- */
319 else if( strncmp(pszResampling
,"averag",6) == 0
320 || strncmp(pszResampling
,"AVERAG",6) == 0 )
322 pabySrc
= pabySrcTile
+ j
*nOMult
*nBlockXSize
* nPixelGroupBytes
;
324 for( i
= 0; i
*nOMult
< nBlockXSize
; i
++ )
330 if( i
+ nTXOff
>= nOBlockXSize
)
333 nXSize
= MIN(nOMult
,nBlockXSize
-i
);
334 nYSize
= MIN(nOMult
,nBlockYSize
-j
);
336 TIFF_GetSourceSamples( padfSamples
, pabySrc
,
337 nPixelBytes
, nSampleFormat
,
340 nPixelGroupBytes
* nBlockXSize
);
343 for( iSample
= 0; iSample
< nXSize
*nYSize
; iSample
++ )
345 dfTotal
+= padfSamples
[iSample
];
348 TIFF_SetSample( pabyDst
, nPixelBytes
, nSampleFormat
,
349 dfTotal
/ (nXSize
*nYSize
) );
351 pabySrc
+= nOMult
* nPixelGroupBytes
;
352 pabyDst
+= nPixelBytes
;
361 void TIFF_DownSample_Subsampled( unsigned char *pabySrcTile
, int nSample
,
362 int nBlockXSize
, int nBlockYSize
,
363 unsigned char * pabyOTile
,
364 int nOBlockXSize
, int nOBlockYSize
,
365 int nTXOff
, int nTYOff
, int nOMult
,
366 const char * pszResampling
,
367 int nHorSubsampling
, int nVerSubsampling
)
369 /* TODO: test with variety of subsampling values, and incovinient tile/strip sizes */
370 int nSampleBlockSize
;
371 int nSourceSampleRowSize
;
372 int nDestSampleRowSize
;
373 int nSourceX
, nSourceY
;
374 int nSourceXSec
, nSourceYSec
;
375 int nSourceXSecEnd
, nSourceYSecEnd
;
377 int nSampleOffsetInSampleBlock
;
378 unsigned char * pSourceBase
;
379 unsigned char * pDestBase
;
381 unsigned char * pSourceBaseEnd
;
382 unsigned int nCummulator
;
383 unsigned int nCummulatorCount
;
385 nSampleBlockSize
= nHorSubsampling
* nVerSubsampling
+ 2;
386 nSourceSampleRowSize
= ( ( nBlockXSize
+ nHorSubsampling
- 1 ) / nHorSubsampling
) * nSampleBlockSize
;
387 nDestSampleRowSize
= ( ( nOBlockXSize
+ nHorSubsampling
- 1 ) / nHorSubsampling
) * nSampleBlockSize
;
389 if( strncmp(pszResampling
,"nearest",4) == 0
390 || strncmp(pszResampling
,"NEAR",4) == 0 )
394 #ifdef NOOPTIMIZATION
396 * This version is not optimized, and should not be used except as documentation and as more clear
397 * starting point for bug fixes (hope not) and extension
399 for( nSourceY
= 0, nDestY
= nTYOff
; nSourceY
< nBlockYSize
; nSourceY
+= nOMult
, nDestY
++)
401 for( nSourceX
= 0, nDestX
= nTXOff
; nSourceX
< nBlockXSize
; nSourceX
+= nOMult
, nDestX
++)
403 * ( pabyOTile
+ ( nDestY
/ nVerSubsampling
) * nDestSampleRowSize
404 + ( nDestY
% nVerSubsampling
) * nHorSubsampling
405 + ( nDestX
/ nHorSubsampling
) * nSampleBlockSize
406 + ( nDestX
% nHorSubsampling
) ) =
407 * ( pabySrcTile
+ ( nSourceY
/ nVerSubsampling
) * nSourceSampleRowSize
408 + ( nSourceY
% nVerSubsampling
) * nHorSubsampling
409 + ( nSourceX
/ nHorSubsampling
) * nSampleBlockSize
410 + ( nSourceX
% nHorSubsampling
) );
414 for( nSourceY
= 0, nDestY
= nTYOff
; nSourceY
< nBlockYSize
; nSourceY
+= nOMult
, nDestY
++)
416 pSourceBase
= pabySrcTile
+ ( nSourceY
/ nVerSubsampling
) * nSourceSampleRowSize
417 + ( nSourceY
% nVerSubsampling
) * nHorSubsampling
;
418 pDestBase
= pabyOTile
+ ( nDestY
/ nVerSubsampling
) * nDestSampleRowSize
419 + ( nDestY
% nVerSubsampling
) * nHorSubsampling
;
420 for( nSourceX
= 0, nDestX
= nTXOff
; nSourceX
< nBlockXSize
; nSourceX
+= nOMult
, nDestX
++)
422 * ( pDestBase
+ ( nDestX
/ nHorSubsampling
) * nSampleBlockSize
423 + ( nDestX
% nHorSubsampling
) ) =
424 * ( pSourceBase
+ ( nSourceX
/ nHorSubsampling
) * nSampleBlockSize
425 + ( nSourceX
% nHorSubsampling
) );
432 #ifdef NOOPTIMIZATION
434 * This version is not optimized, and should not be used except as documentation and as more clear
435 * starting point for bug fixes (hope not) and extension
437 nSampleOffsetInSampleBlock
= nHorSubsampling
* nVerSubsampling
+ nSample
- 1;
438 for( nSourceY
= 0, nDestY
= ( nTYOff
/ nVerSubsampling
); nSourceY
< ( nBlockYSize
/ nVerSubsampling
);
439 nSourceY
+= nOMult
, nDestY
++)
441 for( nSourceX
= 0, nDestX
= ( nTXOff
/ nHorSubsampling
); nSourceX
< ( nBlockXSize
/ nHorSubsampling
);
442 nSourceX
+= nOMult
, nDestX
++)
444 * ( pabyOTile
+ nDestY
* nDestSampleRowSize
445 + nDestX
* nSampleBlockSize
446 + nSampleOffsetInSampleBlock
) =
447 * ( pabySrcTile
+ nSourceY
* nSourceSampleRowSize
448 + nSourceX
* nSampleBlockSize
449 + nSampleOffsetInSampleBlock
);
453 nSampleOffsetInSampleBlock
= nHorSubsampling
* nVerSubsampling
+ nSample
- 1;
454 nSourceBaseInc
= nOMult
* nSampleBlockSize
;
455 for( nSourceY
= 0, nDestY
= ( nTYOff
/ nVerSubsampling
); nSourceY
< ( nBlockYSize
/ nVerSubsampling
);
456 nSourceY
+= nOMult
, nDestY
++)
458 pSourceBase
= pabySrcTile
+ nSourceY
* nSourceSampleRowSize
459 + nSampleOffsetInSampleBlock
;
460 pSourceBaseEnd
= pSourceBase
+ ( ( ( nBlockXSize
/ nHorSubsampling
) + nOMult
- 1 ) / nOMult
) * nSourceBaseInc
;
461 pDestBase
= pabyOTile
+ nDestY
* nDestSampleRowSize
462 + ( nTXOff
/ nHorSubsampling
) * nSampleBlockSize
463 + nSampleOffsetInSampleBlock
;
464 for( ; pSourceBase
< pSourceBaseEnd
; pSourceBase
+= nSourceBaseInc
, pDestBase
+= nSampleBlockSize
)
465 * pDestBase
= * pSourceBase
;
470 else if( strncmp(pszResampling
,"averag",6) == 0
471 || strncmp(pszResampling
,"AVERAG",6) == 0 )
475 for( nSourceY
= 0, nDestY
= nTYOff
; nSourceY
< nBlockYSize
; nSourceY
+= nOMult
, nDestY
++)
477 for( nSourceX
= 0, nDestX
= nTXOff
; nSourceX
< nBlockXSize
; nSourceX
+= nOMult
, nDestX
++)
479 nSourceXSecEnd
= nSourceX
+ nOMult
;
480 if( nSourceXSecEnd
> nBlockXSize
)
481 nSourceXSecEnd
= nBlockXSize
;
482 nSourceYSecEnd
= nSourceY
+ nOMult
;
483 if( nSourceYSecEnd
> nBlockYSize
)
484 nSourceYSecEnd
= nBlockYSize
;
486 for( nSourceYSec
= nSourceY
; nSourceYSec
< nSourceYSecEnd
; nSourceYSec
++)
488 for( nSourceXSec
= nSourceX
; nSourceXSec
< nSourceXSecEnd
; nSourceXSec
++)
490 nCummulator
+= * ( pabySrcTile
+ ( nSourceYSec
/ nVerSubsampling
) * nSourceSampleRowSize
491 + ( nSourceYSec
% nVerSubsampling
) * nHorSubsampling
492 + ( nSourceXSec
/ nHorSubsampling
) * nSampleBlockSize
493 + ( nSourceXSec
% nHorSubsampling
) );
496 nCummulatorCount
= ( nSourceXSecEnd
- nSourceX
) * ( nSourceYSecEnd
- nSourceY
);
497 * ( pabyOTile
+ ( nDestY
/ nVerSubsampling
) * nDestSampleRowSize
498 + ( nDestY
% nVerSubsampling
) * nHorSubsampling
499 + ( nDestX
/ nHorSubsampling
) * nSampleBlockSize
500 + ( nDestX
% nHorSubsampling
) ) =
501 ( ( nCummulator
+ ( nCummulatorCount
>> 1 ) ) / nCummulatorCount
);
507 nSampleOffsetInSampleBlock
= nHorSubsampling
* nVerSubsampling
+ nSample
- 1;
508 for( nSourceY
= 0, nDestY
= ( nTYOff
/ nVerSubsampling
); nSourceY
< ( nBlockYSize
/ nVerSubsampling
);
509 nSourceY
+= nOMult
, nDestY
++)
511 for( nSourceX
= 0, nDestX
= ( nTXOff
/ nHorSubsampling
); nSourceX
< ( nBlockXSize
/ nHorSubsampling
);
512 nSourceX
+= nOMult
, nDestX
++)
514 nSourceXSecEnd
= nSourceX
+ nOMult
;
515 if( nSourceXSecEnd
> ( nBlockXSize
/ nHorSubsampling
) )
516 nSourceXSecEnd
= ( nBlockXSize
/ nHorSubsampling
);
517 nSourceYSecEnd
= nSourceY
+ nOMult
;
518 if( nSourceYSecEnd
> ( nBlockYSize
/ nVerSubsampling
) )
519 nSourceYSecEnd
= ( nBlockYSize
/ nVerSubsampling
);
521 for( nSourceYSec
= nSourceY
; nSourceYSec
< nSourceYSecEnd
; nSourceYSec
++)
523 for( nSourceXSec
= nSourceX
; nSourceXSec
< nSourceXSecEnd
; nSourceXSec
++)
525 nCummulator
+= * ( pabySrcTile
+ nSourceYSec
* nSourceSampleRowSize
526 + nSourceXSec
* nSampleBlockSize
527 + nSampleOffsetInSampleBlock
);
530 nCummulatorCount
= ( nSourceXSecEnd
- nSourceX
) * ( nSourceYSecEnd
- nSourceY
);
531 * ( pabyOTile
+ nDestY
* nDestSampleRowSize
532 + nDestX
* nSampleBlockSize
533 + nSampleOffsetInSampleBlock
) =
534 ( ( nCummulator
+ ( nCummulatorCount
>> 1 ) ) / nCummulatorCount
);
541 /************************************************************************/
542 /* TIFF_ProcessFullResBlock() */
544 /* Process one block of full res data, downsampling into each */
545 /* of the overviews. */
546 /************************************************************************/
548 void TIFF_ProcessFullResBlock( TIFF
*hTIFF
, int nPlanarConfig
,
549 int bSubsampled
, int nHorSubsampling
, int nVerSubsampling
,
550 int nOverviews
, int * panOvList
,
552 int nSamples
, TIFFOvrCache
** papoRawBIs
,
553 int nSXOff
, int nSYOff
,
554 unsigned char *pabySrcTile
,
555 int nBlockXSize
, int nBlockYSize
,
556 int nSampleFormat
, const char * pszResampling
)
559 int iOverview
, iSample
;
561 for( iSample
= 0; iSample
< nSamples
; iSample
++ )
564 * We have to read a tile/strip for each sample for
565 * PLANARCONFIG_SEPARATE. Otherwise, we just read all the samples
566 * at once when handling the first sample.
568 if( nPlanarConfig
== PLANARCONFIG_SEPARATE
|| iSample
== 0 )
570 if( TIFFIsTiled(hTIFF
) )
572 TIFFReadEncodedTile( hTIFF
,
573 TIFFComputeTile(hTIFF
, nSXOff
, nSYOff
,
574 0, (tsample_t
)iSample
),
576 TIFFTileSize(hTIFF
));
580 TIFFReadEncodedStrip( hTIFF
,
581 TIFFComputeStrip(hTIFF
, nSYOff
,
582 (tsample_t
) iSample
),
584 TIFFStripSize(hTIFF
) );
589 * Loop over destination overview layers
591 for( iOverview
= 0; iOverview
< nOverviews
; iOverview
++ )
593 TIFFOvrCache
*poRBI
= papoRawBIs
[iOverview
];
594 unsigned char *pabyOTile
;
595 int nTXOff
, nTYOff
, nOXOff
, nOYOff
, nOMult
;
596 int nOBlockXSize
= poRBI
->nBlockXSize
;
597 int nOBlockYSize
= poRBI
->nBlockYSize
;
598 int nSkewBits
, nSampleByteOffset
;
601 * Fetch the destination overview tile
603 nOMult
= panOvList
[iOverview
];
604 nOXOff
= (nSXOff
/nOMult
) / nOBlockXSize
;
605 nOYOff
= (nSYOff
/nOMult
) / nOBlockYSize
;
609 pabyOTile
= TIFFGetOvrBlock_Subsampled( poRBI
, nOXOff
, nOYOff
);
612 * Establish the offset into this tile at which we should
613 * start placing data.
615 nTXOff
= (nSXOff
- nOXOff
*nOMult
*nOBlockXSize
) / nOMult
;
616 nTYOff
= (nSYOff
- nOYOff
*nOMult
*nOBlockYSize
) / nOMult
;
620 malloc_chain_check( 1 );
622 TIFF_DownSample_Subsampled( pabySrcTile
, iSample
,
623 nBlockXSize
, nBlockYSize
,
625 poRBI
->nBlockXSize
, poRBI
->nBlockYSize
,
627 nOMult
, pszResampling
,
628 nHorSubsampling
, nVerSubsampling
);
630 malloc_chain_check( 1 );
637 pabyOTile
= TIFFGetOvrBlock( poRBI
, nOXOff
, nOYOff
, iSample
);
640 * Establish the offset into this tile at which we should
641 * start placing data.
643 nTXOff
= (nSXOff
- nOXOff
*nOMult
*nOBlockXSize
) / nOMult
;
644 nTYOff
= (nSYOff
- nOYOff
*nOMult
*nOBlockYSize
) / nOMult
;
647 * Figure out the skew (extra space between ``our samples'') and
648 * the byte offset to the first sample.
650 assert( (nBitsPerPixel
% 8) == 0 );
651 if( nPlanarConfig
== PLANARCONFIG_SEPARATE
)
654 nSampleByteOffset
= 0;
658 nSkewBits
= nBitsPerPixel
* (nSamples
-1);
659 nSampleByteOffset
= (nBitsPerPixel
/8) * iSample
;
663 * Perform the downsampling.
666 malloc_chain_check( 1 );
668 TIFF_DownSample( pabySrcTile
+ nSampleByteOffset
,
669 nBlockXSize
, nBlockYSize
,
670 nSkewBits
, nBitsPerPixel
, pabyOTile
,
671 poRBI
->nBlockXSize
, poRBI
->nBlockYSize
,
673 nOMult
, nSampleFormat
, pszResampling
);
675 malloc_chain_check( 1 );
682 /************************************************************************/
683 /* TIFF_BuildOverviews() */
685 /* Build the requested list of overviews. Overviews are */
686 /* maintained in a bunch of temporary files and then these are */
687 /* written back to the TIFF file. Only one pass through the */
688 /* source TIFF file is made for any number of output */
690 /************************************************************************/
692 void TIFFBuildOverviews( TIFF
*hTIFF
, int nOverviews
, int * panOvList
,
693 int bUseSubIFDs
, const char *pszResampleMethod
,
694 int (*pfnProgress
)( double, void * ),
695 void * pProgressData
)
698 TIFFOvrCache
**papoRawBIs
;
699 uint32 nXSize
, nYSize
, nBlockXSize
, nBlockYSize
;
700 uint16 nBitsPerPixel
, nPhotometric
, nCompressFlag
, nSamples
,
701 nPlanarConfig
, nSampleFormat
;
703 uint16 nHorSubsampling
, nVerSubsampling
;
704 int bTiled
, nSXOff
, nSYOff
, i
;
705 unsigned char *pabySrcTile
;
706 uint16
*panRedMap
, *panGreenMap
, *panBlueMap
;
707 TIFFErrorHandler pfnWarning
;
709 /* -------------------------------------------------------------------- */
710 /* Get the base raster size. */
711 /* -------------------------------------------------------------------- */
712 TIFFGetField( hTIFF
, TIFFTAG_IMAGEWIDTH
, &nXSize
);
713 TIFFGetField( hTIFF
, TIFFTAG_IMAGELENGTH
, &nYSize
);
715 TIFFGetField( hTIFF
, TIFFTAG_BITSPERSAMPLE
, &nBitsPerPixel
);
716 /* TODO: nBitsPerPixel seems misnomer and may need renaming to nBitsPerSample */
717 TIFFGetField( hTIFF
, TIFFTAG_SAMPLESPERPIXEL
, &nSamples
);
718 TIFFGetFieldDefaulted( hTIFF
, TIFFTAG_PLANARCONFIG
, &nPlanarConfig
);
720 TIFFGetFieldDefaulted( hTIFF
, TIFFTAG_PHOTOMETRIC
, &nPhotometric
);
721 TIFFGetFieldDefaulted( hTIFF
, TIFFTAG_COMPRESSION
, &nCompressFlag
);
722 TIFFGetFieldDefaulted( hTIFF
, TIFFTAG_SAMPLEFORMAT
, &nSampleFormat
);
724 if( nPhotometric
== PHOTOMETRIC_YCBCR
|| nPhotometric
== PHOTOMETRIC_ITULAB
)
726 if( nBitsPerPixel
!= 8 || nSamples
!= 3 || nPlanarConfig
!= PLANARCONFIG_CONTIG
||
727 nSampleFormat
!= SAMPLEFORMAT_UINT
)
729 /* TODO: use of TIFFError is inconsistent with use of fprintf in addtiffo.c, sort out */
730 TIFFErrorExt( TIFFClientdata(hTIFF
), "TIFFBuildOverviews",
731 "File `%s' has an unsupported subsampling configuration.\n",
732 TIFFFileName(hTIFF
) );
733 /* If you need support for this particular flavor, please contact either
734 * Frank Warmerdam warmerdam@pobox.com
735 * Joris Van Damme info@awaresystems.be
740 TIFFGetField( hTIFF
, TIFFTAG_YCBCRSUBSAMPLING
, &nHorSubsampling
, &nVerSubsampling
);
741 /* TODO: find out if maybe TIFFGetFieldDefaulted is better choice for YCbCrSubsampling tag */
745 if( nBitsPerPixel
< 8 )
747 /* TODO: use of TIFFError is inconsistent with use of fprintf in addtiffo.c, sort out */
748 TIFFErrorExt( TIFFClientdata(hTIFF
), "TIFFBuildOverviews",
749 "File `%s' has samples of %d bits per sample. Sample\n"
750 "sizes of less than 8 bits per sample are not supported.\n",
751 TIFFFileName(hTIFF
), nBitsPerPixel
);
759 /* -------------------------------------------------------------------- */
760 /* Turn off warnings to avoid alot of repeated warnings while */
761 /* rereading directories. */
762 /* -------------------------------------------------------------------- */
763 pfnWarning
= TIFFSetWarningHandler( NULL
);
765 /* -------------------------------------------------------------------- */
766 /* Get the base raster block size. */
767 /* -------------------------------------------------------------------- */
768 if( TIFFGetField( hTIFF
, TIFFTAG_ROWSPERSTRIP
, &(nBlockYSize
) ) )
770 nBlockXSize
= nXSize
;
775 TIFFGetField( hTIFF
, TIFFTAG_TILEWIDTH
, &nBlockXSize
);
776 TIFFGetField( hTIFF
, TIFFTAG_TILELENGTH
, &nBlockYSize
);
780 /* -------------------------------------------------------------------- */
781 /* Capture the pallette if there is one. */
782 /* -------------------------------------------------------------------- */
783 if( TIFFGetField( hTIFF
, TIFFTAG_COLORMAP
,
784 &panRedMap
, &panGreenMap
, &panBlueMap
) )
786 uint16
*panRed2
, *panGreen2
, *panBlue2
;
787 int nColorCount
= 1 << nBitsPerPixel
;
789 panRed2
= (uint16
*) _TIFFmalloc(2*nColorCount
);
790 panGreen2
= (uint16
*) _TIFFmalloc(2*nColorCount
);
791 panBlue2
= (uint16
*) _TIFFmalloc(2*nColorCount
);
793 memcpy( panRed2
, panRedMap
, 2 * nColorCount
);
794 memcpy( panGreen2
, panGreenMap
, 2 * nColorCount
);
795 memcpy( panBlue2
, panBlueMap
, 2 * nColorCount
);
798 panGreenMap
= panGreen2
;
799 panBlueMap
= panBlue2
;
803 panRedMap
= panGreenMap
= panBlueMap
= NULL
;
806 /* -------------------------------------------------------------------- */
807 /* Initialize overviews. */
808 /* -------------------------------------------------------------------- */
809 papoRawBIs
= (TIFFOvrCache
**) _TIFFmalloc(nOverviews
*sizeof(void*));
811 for( i
= 0; i
< nOverviews
; i
++ )
813 int nOXSize
, nOYSize
, nOBlockXSize
, nOBlockYSize
;
816 nOXSize
= (nXSize
+ panOvList
[i
] - 1) / panOvList
[i
];
817 nOYSize
= (nYSize
+ panOvList
[i
] - 1) / panOvList
[i
];
819 nOBlockXSize
= MIN((int)nBlockXSize
,nOXSize
);
820 nOBlockYSize
= MIN((int)nBlockYSize
,nOYSize
);
824 if( (nOBlockXSize
% 16) != 0 )
825 nOBlockXSize
= nOBlockXSize
+ 16 - (nOBlockXSize
% 16);
827 if( (nOBlockYSize
% 16) != 0 )
828 nOBlockYSize
= nOBlockYSize
+ 16 - (nOBlockYSize
% 16);
831 nDirOffset
= TIFF_WriteOverview( hTIFF
, nOXSize
, nOYSize
,
832 nBitsPerPixel
, nPlanarConfig
,
833 nSamples
, nOBlockXSize
, nOBlockYSize
,
834 bTiled
, nCompressFlag
, nPhotometric
,
836 panRedMap
, panGreenMap
, panBlueMap
,
838 nHorSubsampling
, nVerSubsampling
);
840 papoRawBIs
[i
] = TIFFCreateOvrCache( hTIFF
, nDirOffset
);
843 if( panRedMap
!= NULL
)
845 _TIFFfree( panRedMap
);
846 _TIFFfree( panGreenMap
);
847 _TIFFfree( panBlueMap
);
850 /* -------------------------------------------------------------------- */
851 /* Allocate a buffer to hold a source block. */
852 /* -------------------------------------------------------------------- */
854 pabySrcTile
= (unsigned char *) _TIFFmalloc(TIFFTileSize(hTIFF
));
856 pabySrcTile
= (unsigned char *) _TIFFmalloc(TIFFStripSize(hTIFF
));
858 /* -------------------------------------------------------------------- */
859 /* Loop over the source raster, applying data to the */
860 /* destination raster. */
861 /* -------------------------------------------------------------------- */
862 for( nSYOff
= 0; nSYOff
< (int) nYSize
; nSYOff
+= nBlockYSize
)
864 for( nSXOff
= 0; nSXOff
< (int) nXSize
; nSXOff
+= nBlockXSize
)
867 * Read and resample into the various overview images.
870 TIFF_ProcessFullResBlock( hTIFF
, nPlanarConfig
,
871 bSubsampled
,nHorSubsampling
,nVerSubsampling
,
872 nOverviews
, panOvList
,
873 nBitsPerPixel
, nSamples
, papoRawBIs
,
874 nSXOff
, nSYOff
, pabySrcTile
,
875 nBlockXSize
, nBlockYSize
,
876 nSampleFormat
, pszResampleMethod
);
880 _TIFFfree( pabySrcTile
);
882 /* -------------------------------------------------------------------- */
883 /* Cleanup the rawblockedimage files. */
884 /* -------------------------------------------------------------------- */
885 for( i
= 0; i
< nOverviews
; i
++ )
887 TIFFDestroyOvrCache( papoRawBIs
[i
] );
890 if( papoRawBIs
!= NULL
)
891 _TIFFfree( papoRawBIs
);
893 TIFFSetWarningHandler( pfnWarning
);