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
, uint32 nXSize
, uint32 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 toff_t nBaseDirOffset
;
97 nBaseDirOffset
= TIFFCurrentDirOffset( hTIFF
);
99 TIFFCreateDirectory( hTIFF
);
101 /* -------------------------------------------------------------------- */
102 /* Setup TIFF fields. */
103 /* -------------------------------------------------------------------- */
104 TIFFSetField( hTIFF
, TIFFTAG_IMAGEWIDTH
, nXSize
);
105 TIFFSetField( hTIFF
, TIFFTAG_IMAGELENGTH
, nYSize
);
107 TIFFSetField( hTIFF
, TIFFTAG_PLANARCONFIG
, PLANARCONFIG_CONTIG
);
109 TIFFSetField( hTIFF
, TIFFTAG_PLANARCONFIG
, nPlanarConfig
);
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
);
119 TIFFSetField( hTIFF
, TIFFTAG_TILEWIDTH
, nBlockXSize
);
120 TIFFSetField( hTIFF
, TIFFTAG_TILELENGTH
, nBlockYSize
);
123 TIFFSetField( hTIFF
, TIFFTAG_ROWSPERSTRIP
, nBlockYSize
);
125 TIFFSetField( hTIFF
, TIFFTAG_SUBFILETYPE
, FILETYPE_REDUCEDIMAGE
);
127 if( nPhotometric
== PHOTOMETRIC_YCBCR
|| nPhotometric
== PHOTOMETRIC_ITULAB
)
129 TIFFSetField( hTIFF
, TIFFTAG_YCBCRSUBSAMPLING
, nHorSubsampling
, nVerSubsampling
);
130 /* TODO: also write YCbCrPositioning and YCbCrCoefficients tag identical to source IFD */
132 /* TODO: add command-line parameter for selecting jpeg compression quality
133 * that gets ignored when compression isn't jpeg */
135 /* -------------------------------------------------------------------- */
136 /* Write color table if one is present. */
137 /* -------------------------------------------------------------------- */
140 TIFFSetField( hTIFF
, TIFFTAG_COLORMAP
, panRed
, panGreen
, panBlue
);
143 /* -------------------------------------------------------------------- */
144 /* Write directory, and return byte offset. */
145 /* -------------------------------------------------------------------- */
146 if( TIFFWriteCheck( hTIFF
, bTiled
, "TIFFBuildOverviews" ) == 0 )
149 TIFFWriteDirectory( hTIFF
);
150 TIFFSetDirectory( hTIFF
, (tdir_t
) (TIFFNumberOfDirectories(hTIFF
)-1) );
152 nOffset
= TIFFCurrentDirOffset( hTIFF
);
154 TIFFSetSubDirectory( hTIFF
, nBaseDirOffset
);
159 /************************************************************************/
160 /* TIFF_GetSourceSamples() */
161 /************************************************************************/
164 TIFF_GetSourceSamples( double * padfSamples
, unsigned char *pabySrc
,
165 int nPixelBytes
, int nSampleFormat
,
166 uint32 nXSize
, uint32 nYSize
,
167 int nPixelOffset
, int nLineOffset
)
174 for( iYOff
= 0; iYOff
< nYSize
; iYOff
++ )
176 for( iXOff
= 0; iXOff
< nXSize
; iXOff
++ )
178 unsigned char *pabyData
;
180 pabyData
= pabySrc
+ iYOff
* nLineOffset
+ iXOff
* nPixelOffset
;
182 if( nSampleFormat
== SAMPLEFORMAT_UINT
&& nPixelBytes
== 1 )
184 padfSamples
[iSample
++] = *pabyData
;
186 else if( nSampleFormat
== SAMPLEFORMAT_UINT
&& nPixelBytes
== 2 )
188 padfSamples
[iSample
++] = ((uint16
*) pabyData
)[0];
190 else if( nSampleFormat
== SAMPLEFORMAT_UINT
&& nPixelBytes
== 4 )
192 padfSamples
[iSample
++] = ((uint32
*) pabyData
)[0];
194 else if( nSampleFormat
== SAMPLEFORMAT_INT
&& nPixelBytes
== 2 )
196 padfSamples
[iSample
++] = ((int16
*) pabyData
)[0];
198 else if( nSampleFormat
== SAMPLEFORMAT_INT
&& nPixelBytes
== 32 )
200 padfSamples
[iSample
++] = ((int32
*) pabyData
)[0];
202 else if( nSampleFormat
== SAMPLEFORMAT_IEEEFP
&& nPixelBytes
== 4 )
204 padfSamples
[iSample
++] = ((float *) pabyData
)[0];
206 else if( nSampleFormat
== SAMPLEFORMAT_IEEEFP
&& nPixelBytes
== 8 )
208 padfSamples
[iSample
++] = ((double *) pabyData
)[0];
214 /************************************************************************/
215 /* TIFF_SetSample() */
216 /************************************************************************/
219 TIFF_SetSample( unsigned char * pabyData
, int nPixelBytes
, int nSampleFormat
,
223 if( nSampleFormat
== SAMPLEFORMAT_UINT
&& nPixelBytes
== 1 )
225 *pabyData
= (unsigned char) MAX(0,MIN(255,dfValue
));
227 else if( nSampleFormat
== SAMPLEFORMAT_UINT
&& nPixelBytes
== 2 )
229 *((uint16
*)pabyData
) = (uint16
) MAX(0,MIN(65535,dfValue
));
231 else if( nSampleFormat
== SAMPLEFORMAT_UINT
&& nPixelBytes
== 4 )
233 *((uint32
*)pabyData
) = (uint32
) dfValue
;
235 else if( nSampleFormat
== SAMPLEFORMAT_INT
&& nPixelBytes
== 2 )
237 *((int16
*)pabyData
) = (int16
) MAX(-32768,MIN(32767,dfValue
));
239 else if( nSampleFormat
== SAMPLEFORMAT_INT
&& nPixelBytes
== 32 )
241 *((int32
*)pabyData
) = (int32
) dfValue
;
243 else if( nSampleFormat
== SAMPLEFORMAT_IEEEFP
&& nPixelBytes
== 4 )
245 *((float *)pabyData
) = (float) dfValue
;
247 else if( nSampleFormat
== SAMPLEFORMAT_IEEEFP
&& nPixelBytes
== 8 )
249 *((double *)pabyData
) = dfValue
;
253 /************************************************************************/
254 /* TIFF_DownSample() */
256 /* Down sample a tile of full res data into a window of a tile */
257 /* of downsampled data. */
258 /************************************************************************/
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
)
271 int k
, nPixelBytes
= (nBitsPerPixel
) / 8;
272 int nPixelGroupBytes
= (nBitsPerPixel
+nPixelSkewBits
)/8;
273 unsigned char *pabySrc
, *pabyDst
;
276 assert( nBitsPerPixel
>= 8 );
278 padfSamples
= (double *) malloc(sizeof(double) * nOMult
* nOMult
);
280 /* ==================================================================== */
281 /* Loop over scanline chunks to process, establishing where the */
283 /* ==================================================================== */
284 for( j
= 0; j
*nOMult
< nBlockYSize
; j
++ )
286 if( j
+ nTYOff
>= nOBlockYSize
)
289 pabyDst
= pabyOTile
+ ((j
+nTYOff
)*nOBlockXSize
+ nTXOff
)
290 * nPixelBytes
* nPixelGroupBytes
;
292 /* -------------------------------------------------------------------- */
293 /* Handler nearest resampling ... we don't even care about the */
294 /* data type, we just do a bytewise copy. */
295 /* -------------------------------------------------------------------- */
296 if( strncmp(pszResampling
,"nearest",4) == 0
297 || strncmp(pszResampling
,"NEAR",4) == 0 )
299 pabySrc
= pabySrcTile
+ j
*nOMult
*nBlockXSize
* nPixelGroupBytes
;
301 for( i
= 0; i
*nOMult
< nBlockXSize
; i
++ )
303 if( i
+ nTXOff
>= nOBlockXSize
)
307 * For now use simple subsampling, from the top left corner
308 * of the source block of pixels.
311 for( k
= 0; k
< nPixelBytes
; k
++ )
312 pabyDst
[k
] = pabySrc
[k
];
314 pabyDst
+= nPixelBytes
* nPixelGroupBytes
;
315 pabySrc
+= nOMult
* nPixelGroupBytes
;
319 /* -------------------------------------------------------------------- */
320 /* Handle the case of averaging. For this we also have to */
321 /* handle each sample format we are concerned with. */
322 /* -------------------------------------------------------------------- */
323 else if( strncmp(pszResampling
,"averag",6) == 0
324 || strncmp(pszResampling
,"AVERAG",6) == 0 )
326 pabySrc
= pabySrcTile
+ j
*nOMult
*nBlockXSize
* nPixelGroupBytes
;
328 for( i
= 0; i
*nOMult
< nBlockXSize
; i
++ )
331 uint32 nXSize
, nYSize
, iSample
;
333 if( i
+ nTXOff
>= nOBlockXSize
)
336 nXSize
= MIN((uint32
)nOMult
,nBlockXSize
-i
);
337 nYSize
= MIN((uint32
)nOMult
,nBlockYSize
-j
);
339 TIFF_GetSourceSamples( padfSamples
, pabySrc
,
340 nPixelBytes
, nSampleFormat
,
343 nPixelGroupBytes
* nBlockXSize
);
346 for( iSample
= 0; iSample
< nXSize
*nYSize
; iSample
++ )
348 dfTotal
+= padfSamples
[iSample
];
351 TIFF_SetSample( pabyDst
, nPixelBytes
, nSampleFormat
,
352 dfTotal
/ (nXSize
*nYSize
) );
354 pabySrc
+= nOMult
* nPixelGroupBytes
;
355 pabyDst
+= nPixelBytes
;
363 /************************************************************************/
364 /* TIFF_DownSample_Subsampled() */
365 /************************************************************************/
367 void TIFF_DownSample_Subsampled( unsigned char *pabySrcTile
, int nSample
,
368 uint32 nBlockXSize
, uint32 nBlockYSize
,
369 unsigned char * pabyOTile
,
370 uint32 nOBlockXSize
, uint32 nOBlockYSize
,
371 uint32 nTXOff
, uint32 nTYOff
, int nOMult
,
372 const char *pszResampling
,
373 int nHorSubsampling
, int nVerSubsampling
)
375 /* TODO: test with variety of subsampling values, and incovinient tile/strip sizes */
376 int nSampleBlockSize
;
377 int nSourceSampleRowSize
;
378 int nDestSampleRowSize
;
379 uint32 nSourceX
, nSourceY
;
380 uint32 nSourceXSec
, nSourceYSec
;
381 uint32 nSourceXSecEnd
, nSourceYSecEnd
;
382 uint32 nDestX
, nDestY
;
383 int nSampleOffsetInSampleBlock
;
384 unsigned int nCummulator
;
385 unsigned int nCummulatorCount
;
387 nSampleBlockSize
= nHorSubsampling
* nVerSubsampling
+ 2;
388 nSourceSampleRowSize
=
389 ( ( nBlockXSize
+ nHorSubsampling
- 1 ) / nHorSubsampling
) * nSampleBlockSize
;
391 ( ( nOBlockXSize
+ nHorSubsampling
- 1 ) / nHorSubsampling
) * nSampleBlockSize
;
393 if( strncmp(pszResampling
,"nearest",4) == 0
394 || strncmp(pszResampling
,"NEAR",4) == 0 )
398 for( nSourceY
= 0, nDestY
= nTYOff
;
399 nSourceY
< nBlockYSize
;
400 nSourceY
+= nOMult
, nDestY
++)
402 if( nDestY
>= nOBlockYSize
)
405 for( nSourceX
= 0, nDestX
= nTXOff
;
406 nSourceX
< nBlockXSize
;
407 nSourceX
+= nOMult
, nDestX
++)
409 if( nDestX
>= nOBlockXSize
)
412 * ( pabyOTile
+ ( nDestY
/ nVerSubsampling
) * nDestSampleRowSize
413 + ( nDestY
% nVerSubsampling
) * nHorSubsampling
414 + ( nDestX
/ nHorSubsampling
) * nSampleBlockSize
415 + ( nDestX
% nHorSubsampling
) ) =
416 * ( pabySrcTile
+ ( nSourceY
/ nVerSubsampling
) * nSourceSampleRowSize
417 + ( nSourceY
% nVerSubsampling
) * nHorSubsampling
418 + ( nSourceX
/ nHorSubsampling
) * nSampleBlockSize
419 + ( nSourceX
% nHorSubsampling
) );
425 nSampleOffsetInSampleBlock
= nHorSubsampling
* nVerSubsampling
+ nSample
- 1;
426 for( nSourceY
= 0, nDestY
= ( nTYOff
/ nVerSubsampling
);
427 nSourceY
< ( nBlockYSize
/ nVerSubsampling
);
428 nSourceY
+= nOMult
, nDestY
++)
430 if( nDestY
*nVerSubsampling
>= nOBlockYSize
)
433 for( nSourceX
= 0, nDestX
= ( nTXOff
/ nHorSubsampling
);
434 nSourceX
< ( nBlockXSize
/ nHorSubsampling
);
435 nSourceX
+= nOMult
, nDestX
++)
437 if( nDestX
*nHorSubsampling
>= nOBlockXSize
)
440 * ( pabyOTile
+ nDestY
* nDestSampleRowSize
441 + nDestX
* nSampleBlockSize
442 + nSampleOffsetInSampleBlock
) =
443 * ( pabySrcTile
+ nSourceY
* nSourceSampleRowSize
444 + nSourceX
* nSampleBlockSize
445 + nSampleOffsetInSampleBlock
);
450 else if( strncmp(pszResampling
,"averag",6) == 0
451 || strncmp(pszResampling
,"AVERAG",6) == 0 )
455 for( nSourceY
= 0, nDestY
= nTYOff
; nSourceY
< nBlockYSize
; nSourceY
+= nOMult
, nDestY
++)
457 if( nDestY
>= nOBlockYSize
)
460 for( nSourceX
= 0, nDestX
= nTXOff
; nSourceX
< nBlockXSize
; nSourceX
+= nOMult
, nDestX
++)
462 if( nDestX
>= nOBlockXSize
)
465 nSourceXSecEnd
= nSourceX
+ nOMult
;
466 if( nSourceXSecEnd
> nBlockXSize
)
467 nSourceXSecEnd
= nBlockXSize
;
468 nSourceYSecEnd
= nSourceY
+ nOMult
;
469 if( nSourceYSecEnd
> nBlockYSize
)
470 nSourceYSecEnd
= nBlockYSize
;
472 for( nSourceYSec
= nSourceY
; nSourceYSec
< nSourceYSecEnd
; nSourceYSec
++)
474 for( nSourceXSec
= nSourceX
; nSourceXSec
< nSourceXSecEnd
; nSourceXSec
++)
476 nCummulator
+= * ( pabySrcTile
+ ( nSourceYSec
/ nVerSubsampling
) * nSourceSampleRowSize
477 + ( nSourceYSec
% nVerSubsampling
) * nHorSubsampling
478 + ( nSourceXSec
/ nHorSubsampling
) * nSampleBlockSize
479 + ( nSourceXSec
% nHorSubsampling
) );
482 nCummulatorCount
= ( nSourceXSecEnd
- nSourceX
) * ( nSourceYSecEnd
- nSourceY
);
483 * ( pabyOTile
+ ( nDestY
/ nVerSubsampling
) * nDestSampleRowSize
484 + ( nDestY
% nVerSubsampling
) * nHorSubsampling
485 + ( nDestX
/ nHorSubsampling
) * nSampleBlockSize
486 + ( nDestX
% nHorSubsampling
) ) =
487 ( ( nCummulator
+ ( nCummulatorCount
>> 1 ) ) / nCummulatorCount
);
493 nSampleOffsetInSampleBlock
= nHorSubsampling
* nVerSubsampling
+ nSample
- 1;
494 for( nSourceY
= 0, nDestY
= ( nTYOff
/ nVerSubsampling
); nSourceY
< ( nBlockYSize
/ nVerSubsampling
);
495 nSourceY
+= nOMult
, nDestY
++)
497 if( nDestY
*nVerSubsampling
>= nOBlockYSize
)
500 for( nSourceX
= 0, nDestX
= ( nTXOff
/ nHorSubsampling
); nSourceX
< ( nBlockXSize
/ nHorSubsampling
);
501 nSourceX
+= nOMult
, nDestX
++)
503 if( nDestX
*nHorSubsampling
>= nOBlockXSize
)
506 nSourceXSecEnd
= nSourceX
+ nOMult
;
507 if( nSourceXSecEnd
> ( nBlockXSize
/ nHorSubsampling
) )
508 nSourceXSecEnd
= ( nBlockXSize
/ nHorSubsampling
);
509 nSourceYSecEnd
= nSourceY
+ nOMult
;
510 if( nSourceYSecEnd
> ( nBlockYSize
/ nVerSubsampling
) )
511 nSourceYSecEnd
= ( nBlockYSize
/ nVerSubsampling
);
513 for( nSourceYSec
= nSourceY
; nSourceYSec
< nSourceYSecEnd
; nSourceYSec
++)
515 for( nSourceXSec
= nSourceX
; nSourceXSec
< nSourceXSecEnd
; nSourceXSec
++)
517 nCummulator
+= * ( pabySrcTile
+ nSourceYSec
* nSourceSampleRowSize
518 + nSourceXSec
* nSampleBlockSize
519 + nSampleOffsetInSampleBlock
);
522 nCummulatorCount
= ( nSourceXSecEnd
- nSourceX
) * ( nSourceYSecEnd
- nSourceY
);
523 * ( pabyOTile
+ nDestY
* nDestSampleRowSize
524 + nDestX
* nSampleBlockSize
525 + nSampleOffsetInSampleBlock
) =
526 ( ( nCummulator
+ ( nCummulatorCount
>> 1 ) ) / nCummulatorCount
);
533 /************************************************************************/
534 /* TIFF_ProcessFullResBlock() */
536 /* Process one block of full res data, downsampling into each */
537 /* of the overviews. */
538 /************************************************************************/
540 void TIFF_ProcessFullResBlock( TIFF
*hTIFF
, int nPlanarConfig
,
542 int nHorSubsampling
, int nVerSubsampling
,
543 int nOverviews
, int * panOvList
,
545 int nSamples
, TIFFOvrCache
** papoRawBIs
,
546 uint32 nSXOff
, uint32 nSYOff
,
547 unsigned char *pabySrcTile
,
548 uint32 nBlockXSize
, uint32 nBlockYSize
,
549 int nSampleFormat
, const char * pszResampling
)
552 int iOverview
, iSample
;
554 for( iSample
= 0; iSample
< nSamples
; iSample
++ )
557 * We have to read a tile/strip for each sample for
558 * PLANARCONFIG_SEPARATE. Otherwise, we just read all the samples
559 * at once when handling the first sample.
561 if( nPlanarConfig
== PLANARCONFIG_SEPARATE
|| iSample
== 0 )
563 if( TIFFIsTiled(hTIFF
) )
565 TIFFReadEncodedTile( hTIFF
,
566 TIFFComputeTile(hTIFF
, nSXOff
, nSYOff
,
567 0, (tsample_t
)iSample
),
569 TIFFTileSize(hTIFF
));
573 TIFFReadEncodedStrip( hTIFF
,
574 TIFFComputeStrip(hTIFF
, nSYOff
,
575 (tsample_t
) iSample
),
577 TIFFStripSize(hTIFF
) );
582 * Loop over destination overview layers
584 for( iOverview
= 0; iOverview
< nOverviews
; iOverview
++ )
586 TIFFOvrCache
*poRBI
= papoRawBIs
[iOverview
];
587 unsigned char *pabyOTile
;
588 uint32 nTXOff
, nTYOff
, nOXOff
, nOYOff
, nOMult
;
589 uint32 nOBlockXSize
= poRBI
->nBlockXSize
;
590 uint32 nOBlockYSize
= poRBI
->nBlockYSize
;
591 int nSkewBits
, nSampleByteOffset
;
594 * Fetch the destination overview tile
596 nOMult
= panOvList
[iOverview
];
597 nOXOff
= (nSXOff
/nOMult
) / nOBlockXSize
;
598 nOYOff
= (nSYOff
/nOMult
) / nOBlockYSize
;
602 pabyOTile
= TIFFGetOvrBlock_Subsampled( poRBI
, nOXOff
, nOYOff
);
605 * Establish the offset into this tile at which we should
606 * start placing data.
608 nTXOff
= (nSXOff
- nOXOff
*nOMult
*nOBlockXSize
) / nOMult
;
609 nTYOff
= (nSYOff
- nOYOff
*nOMult
*nOBlockYSize
) / nOMult
;
613 malloc_chain_check( 1 );
615 TIFF_DownSample_Subsampled( pabySrcTile
, iSample
,
616 nBlockXSize
, nBlockYSize
,
618 poRBI
->nBlockXSize
, poRBI
->nBlockYSize
,
620 nOMult
, pszResampling
,
621 nHorSubsampling
, nVerSubsampling
);
623 malloc_chain_check( 1 );
630 pabyOTile
= TIFFGetOvrBlock( poRBI
, nOXOff
, nOYOff
, iSample
);
633 * Establish the offset into this tile at which we should
634 * start placing data.
636 nTXOff
= (nSXOff
- nOXOff
*nOMult
*nOBlockXSize
) / nOMult
;
637 nTYOff
= (nSYOff
- nOYOff
*nOMult
*nOBlockYSize
) / nOMult
;
640 * Figure out the skew (extra space between ``our samples'') and
641 * the byte offset to the first sample.
643 assert( (nBitsPerPixel
% 8) == 0 );
644 if( nPlanarConfig
== PLANARCONFIG_SEPARATE
)
647 nSampleByteOffset
= 0;
651 nSkewBits
= nBitsPerPixel
* (nSamples
-1);
652 nSampleByteOffset
= (nBitsPerPixel
/8) * iSample
;
656 * Perform the downsampling.
659 malloc_chain_check( 1 );
661 TIFF_DownSample( pabySrcTile
+ nSampleByteOffset
,
662 nBlockXSize
, nBlockYSize
,
663 nSkewBits
, nBitsPerPixel
, pabyOTile
,
664 poRBI
->nBlockXSize
, poRBI
->nBlockYSize
,
666 nOMult
, nSampleFormat
, pszResampling
);
668 malloc_chain_check( 1 );
675 /************************************************************************/
676 /* TIFF_BuildOverviews() */
678 /* Build the requested list of overviews. Overviews are */
679 /* maintained in a bunch of temporary files and then these are */
680 /* written back to the TIFF file. Only one pass through the */
681 /* source TIFF file is made for any number of output */
683 /************************************************************************/
685 void TIFFBuildOverviews( TIFF
*hTIFF
, int nOverviews
, int * panOvList
,
686 int bUseSubIFDs
, const char *pszResampleMethod
,
687 int (*pfnProgress
)( double, void * ),
688 void * pProgressData
)
691 TIFFOvrCache
**papoRawBIs
;
692 uint32 nXSize
, nYSize
, nBlockXSize
, nBlockYSize
;
693 uint16 nBitsPerPixel
, nPhotometric
, nCompressFlag
, nSamples
,
694 nPlanarConfig
, nSampleFormat
;
696 uint16 nHorSubsampling
, nVerSubsampling
;
697 int bTiled
, nSXOff
, nSYOff
, i
;
698 unsigned char *pabySrcTile
;
699 uint16
*panRedMap
, *panGreenMap
, *panBlueMap
;
700 TIFFErrorHandler pfnWarning
;
703 (void) pProgressData
;
705 /* -------------------------------------------------------------------- */
706 /* Get the base raster size. */
707 /* -------------------------------------------------------------------- */
708 TIFFGetField( hTIFF
, TIFFTAG_IMAGEWIDTH
, &nXSize
);
709 TIFFGetField( hTIFF
, TIFFTAG_IMAGELENGTH
, &nYSize
);
711 TIFFGetField( hTIFF
, TIFFTAG_BITSPERSAMPLE
, &nBitsPerPixel
);
712 /* TODO: nBitsPerPixel seems misnomer and may need renaming to nBitsPerSample */
713 TIFFGetField( hTIFF
, TIFFTAG_SAMPLESPERPIXEL
, &nSamples
);
714 TIFFGetFieldDefaulted( hTIFF
, TIFFTAG_PLANARCONFIG
, &nPlanarConfig
);
716 TIFFGetFieldDefaulted( hTIFF
, TIFFTAG_PHOTOMETRIC
, &nPhotometric
);
717 TIFFGetFieldDefaulted( hTIFF
, TIFFTAG_COMPRESSION
, &nCompressFlag
);
718 TIFFGetFieldDefaulted( hTIFF
, TIFFTAG_SAMPLEFORMAT
, &nSampleFormat
);
720 if( nPhotometric
== PHOTOMETRIC_YCBCR
|| nPhotometric
== PHOTOMETRIC_ITULAB
)
722 if( nBitsPerPixel
!= 8 || nSamples
!= 3 || nPlanarConfig
!= PLANARCONFIG_CONTIG
||
723 nSampleFormat
!= SAMPLEFORMAT_UINT
)
725 /* TODO: use of TIFFError is inconsistent with use of fprintf in addtiffo.c, sort out */
726 TIFFErrorExt( TIFFClientdata(hTIFF
), "TIFFBuildOverviews",
727 "File `%s' has an unsupported subsampling configuration.\n",
728 TIFFFileName(hTIFF
) );
729 /* If you need support for this particular flavor, please contact either
730 * Frank Warmerdam warmerdam@pobox.com
731 * Joris Van Damme info@awaresystems.be
736 TIFFGetField( hTIFF
, TIFFTAG_YCBCRSUBSAMPLING
, &nHorSubsampling
, &nVerSubsampling
);
737 /* TODO: find out if maybe TIFFGetFieldDefaulted is better choice for YCbCrSubsampling tag */
741 if( nBitsPerPixel
< 8 )
743 /* TODO: use of TIFFError is inconsistent with use of fprintf in addtiffo.c, sort out */
744 TIFFErrorExt( TIFFClientdata(hTIFF
), "TIFFBuildOverviews",
745 "File `%s' has samples of %d bits per sample. Sample\n"
746 "sizes of less than 8 bits per sample are not supported.\n",
747 TIFFFileName(hTIFF
), nBitsPerPixel
);
755 /* -------------------------------------------------------------------- */
756 /* Turn off warnings to avoid alot of repeated warnings while */
757 /* rereading directories. */
758 /* -------------------------------------------------------------------- */
759 pfnWarning
= TIFFSetWarningHandler( NULL
);
761 /* -------------------------------------------------------------------- */
762 /* Get the base raster block size. */
763 /* -------------------------------------------------------------------- */
764 if( TIFFGetField( hTIFF
, TIFFTAG_ROWSPERSTRIP
, &(nBlockYSize
) ) )
766 nBlockXSize
= nXSize
;
771 TIFFGetField( hTIFF
, TIFFTAG_TILEWIDTH
, &nBlockXSize
);
772 TIFFGetField( hTIFF
, TIFFTAG_TILELENGTH
, &nBlockYSize
);
776 /* -------------------------------------------------------------------- */
777 /* Capture the pallette if there is one. */
778 /* -------------------------------------------------------------------- */
779 if( TIFFGetField( hTIFF
, TIFFTAG_COLORMAP
,
780 &panRedMap
, &panGreenMap
, &panBlueMap
) )
782 uint16
*panRed2
, *panGreen2
, *panBlue2
;
783 int nColorCount
= 1 << nBitsPerPixel
;
785 panRed2
= (uint16
*) _TIFFmalloc(2*nColorCount
);
786 panGreen2
= (uint16
*) _TIFFmalloc(2*nColorCount
);
787 panBlue2
= (uint16
*) _TIFFmalloc(2*nColorCount
);
789 memcpy( panRed2
, panRedMap
, 2 * nColorCount
);
790 memcpy( panGreen2
, panGreenMap
, 2 * nColorCount
);
791 memcpy( panBlue2
, panBlueMap
, 2 * nColorCount
);
794 panGreenMap
= panGreen2
;
795 panBlueMap
= panBlue2
;
799 panRedMap
= panGreenMap
= panBlueMap
= NULL
;
802 /* -------------------------------------------------------------------- */
803 /* Initialize overviews. */
804 /* -------------------------------------------------------------------- */
805 papoRawBIs
= (TIFFOvrCache
**) _TIFFmalloc(nOverviews
*sizeof(void*));
807 for( i
= 0; i
< nOverviews
; i
++ )
809 uint32 nOXSize
, nOYSize
, nOBlockXSize
, nOBlockYSize
;
812 nOXSize
= (nXSize
+ panOvList
[i
] - 1) / panOvList
[i
];
813 nOYSize
= (nYSize
+ panOvList
[i
] - 1) / panOvList
[i
];
815 nOBlockXSize
= MIN(nBlockXSize
,nOXSize
);
816 nOBlockYSize
= MIN(nBlockYSize
,nOYSize
);
820 if( (nOBlockXSize
% 16) != 0 )
821 nOBlockXSize
= nOBlockXSize
+ 16 - (nOBlockXSize
% 16);
823 if( (nOBlockYSize
% 16) != 0 )
824 nOBlockYSize
= nOBlockYSize
+ 16 - (nOBlockYSize
% 16);
827 nDirOffset
= TIFF_WriteOverview( hTIFF
, nOXSize
, nOYSize
,
828 nBitsPerPixel
, nPlanarConfig
,
829 nSamples
, nOBlockXSize
, nOBlockYSize
,
830 bTiled
, nCompressFlag
, nPhotometric
,
832 panRedMap
, panGreenMap
, panBlueMap
,
834 nHorSubsampling
, nVerSubsampling
);
836 papoRawBIs
[i
] = TIFFCreateOvrCache( hTIFF
, nDirOffset
);
839 if( panRedMap
!= NULL
)
841 _TIFFfree( panRedMap
);
842 _TIFFfree( panGreenMap
);
843 _TIFFfree( panBlueMap
);
846 /* -------------------------------------------------------------------- */
847 /* Allocate a buffer to hold a source block. */
848 /* -------------------------------------------------------------------- */
850 pabySrcTile
= (unsigned char *) _TIFFmalloc(TIFFTileSize(hTIFF
));
852 pabySrcTile
= (unsigned char *) _TIFFmalloc(TIFFStripSize(hTIFF
));
854 /* -------------------------------------------------------------------- */
855 /* Loop over the source raster, applying data to the */
856 /* destination raster. */
857 /* -------------------------------------------------------------------- */
858 for( nSYOff
= 0; nSYOff
< (int) nYSize
; nSYOff
+= nBlockYSize
)
860 for( nSXOff
= 0; nSXOff
< (int) nXSize
; nSXOff
+= nBlockXSize
)
863 * Read and resample into the various overview images.
866 TIFF_ProcessFullResBlock( hTIFF
, nPlanarConfig
,
867 bSubsampled
,nHorSubsampling
,nVerSubsampling
,
868 nOverviews
, panOvList
,
869 nBitsPerPixel
, nSamples
, papoRawBIs
,
870 nSXOff
, nSYOff
, pabySrcTile
,
871 nBlockXSize
, nBlockYSize
,
872 nSampleFormat
, pszResampleMethod
);
876 _TIFFfree( pabySrcTile
);
878 /* -------------------------------------------------------------------- */
879 /* Cleanup the rawblockedimage files. */
880 /* -------------------------------------------------------------------- */
881 for( i
= 0; i
< nOverviews
; i
++ )
883 TIFFDestroyOvrCache( papoRawBIs
[i
] );
886 if( papoRawBIs
!= NULL
)
887 _TIFFfree( papoRawBIs
);
889 TIFFSetWarningHandler( pfnWarning
);