]> git.saurik.com Git - wxWidgets.git/blob - src/tiff/contrib/addtiffo/tif_overview.c
Fixed centering/right alignment of last line
[wxWidgets.git] / src / tiff / contrib / addtiffo / tif_overview.c
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 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
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
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
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
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
276 assert( nBitsPerPixel >= 8 );
277
278 padfSamples = (double *) malloc(sizeof(double) * nOMult * nOMult);
279
280 /* ==================================================================== */
281 /* Loop over scanline chunks to process, establishing where the */
282 /* data is going. */
283 /* ==================================================================== */
284 for( j = 0; j*nOMult < nBlockYSize; j++ )
285 {
286 if( j + nTYOff >= nOBlockYSize )
287 break;
288
289 pabyDst = pabyOTile + ((j+nTYOff)*nOBlockXSize + nTXOff)
290 * nPixelBytes * nPixelGroupBytes;
291
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 )
298 {
299 pabySrc = pabySrcTile + j*nOMult*nBlockXSize * nPixelGroupBytes;
300
301 for( i = 0; i*nOMult < nBlockXSize; i++ )
302 {
303 if( i + nTXOff >= nOBlockXSize )
304 break;
305
306 /*
307 * For now use simple subsampling, from the top left corner
308 * of the source block of pixels.
309 */
310
311 for( k = 0; k < nPixelBytes; k++ )
312 pabyDst[k] = pabySrc[k];
313
314 pabyDst += nPixelBytes * nPixelGroupBytes;
315 pabySrc += nOMult * nPixelGroupBytes;
316 }
317 }
318
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 )
325 {
326 pabySrc = pabySrcTile + j*nOMult*nBlockXSize * nPixelGroupBytes;
327
328 for( i = 0; i*nOMult < nBlockXSize; i++ )
329 {
330 double dfTotal;
331 uint32 nXSize, nYSize, iSample;
332
333 if( i + nTXOff >= nOBlockXSize )
334 break;
335
336 nXSize = MIN((uint32)nOMult,nBlockXSize-i);
337 nYSize = MIN((uint32)nOMult,nBlockYSize-j);
338
339 TIFF_GetSourceSamples( padfSamples, pabySrc,
340 nPixelBytes, nSampleFormat,
341 nXSize, nYSize,
342 nPixelGroupBytes,
343 nPixelGroupBytes * nBlockXSize );
344
345 dfTotal = 0;
346 for( iSample = 0; iSample < nXSize*nYSize; iSample++ )
347 {
348 dfTotal += padfSamples[iSample];
349 }
350
351 TIFF_SetSample( pabyDst, nPixelBytes, nSampleFormat,
352 dfTotal / (nXSize*nYSize) );
353
354 pabySrc += nOMult * nPixelGroupBytes;
355 pabyDst += nPixelBytes;
356 }
357 }
358 }
359
360 free( padfSamples );
361 }
362
363 /************************************************************************/
364 /* TIFF_DownSample_Subsampled() */
365 /************************************************************************/
366 static
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 )
374 {
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;
386
387 nSampleBlockSize = nHorSubsampling * nVerSubsampling + 2;
388 nSourceSampleRowSize =
389 ( ( nBlockXSize + nHorSubsampling - 1 ) / nHorSubsampling ) * nSampleBlockSize;
390 nDestSampleRowSize =
391 ( ( nOBlockXSize + nHorSubsampling - 1 ) / nHorSubsampling ) * nSampleBlockSize;
392
393 if( strncmp(pszResampling,"nearest",4) == 0
394 || strncmp(pszResampling,"NEAR",4) == 0 )
395 {
396 if( nSample == 0 )
397 {
398 for( nSourceY = 0, nDestY = nTYOff;
399 nSourceY < nBlockYSize;
400 nSourceY += nOMult, nDestY ++)
401 {
402 if( nDestY >= nOBlockYSize )
403 break;
404
405 for( nSourceX = 0, nDestX = nTXOff;
406 nSourceX < nBlockXSize;
407 nSourceX += nOMult, nDestX ++)
408 {
409 if( nDestX >= nOBlockXSize )
410 break;
411
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 ) );
420 }
421 }
422 }
423 else
424 {
425 nSampleOffsetInSampleBlock = nHorSubsampling * nVerSubsampling + nSample - 1;
426 for( nSourceY = 0, nDestY = ( nTYOff / nVerSubsampling );
427 nSourceY < ( nBlockYSize / nVerSubsampling );
428 nSourceY += nOMult, nDestY ++)
429 {
430 if( nDestY*nVerSubsampling >= nOBlockYSize )
431 break;
432
433 for( nSourceX = 0, nDestX = ( nTXOff / nHorSubsampling );
434 nSourceX < ( nBlockXSize / nHorSubsampling );
435 nSourceX += nOMult, nDestX ++)
436 {
437 if( nDestX*nHorSubsampling >= nOBlockXSize )
438 break;
439
440 * ( pabyOTile + nDestY * nDestSampleRowSize
441 + nDestX * nSampleBlockSize
442 + nSampleOffsetInSampleBlock ) =
443 * ( pabySrcTile + nSourceY * nSourceSampleRowSize
444 + nSourceX * nSampleBlockSize
445 + nSampleOffsetInSampleBlock );
446 }
447 }
448 }
449 }
450 else if( strncmp(pszResampling,"averag",6) == 0
451 || strncmp(pszResampling,"AVERAG",6) == 0 )
452 {
453 if( nSample == 0 )
454 {
455 for( nSourceY = 0, nDestY = nTYOff; nSourceY < nBlockYSize; nSourceY += nOMult, nDestY ++)
456 {
457 if( nDestY >= nOBlockYSize )
458 break;
459
460 for( nSourceX = 0, nDestX = nTXOff; nSourceX < nBlockXSize; nSourceX += nOMult, nDestX ++)
461 {
462 if( nDestX >= nOBlockXSize )
463 break;
464
465 nSourceXSecEnd = nSourceX + nOMult;
466 if( nSourceXSecEnd > nBlockXSize )
467 nSourceXSecEnd = nBlockXSize;
468 nSourceYSecEnd = nSourceY + nOMult;
469 if( nSourceYSecEnd > nBlockYSize )
470 nSourceYSecEnd = nBlockYSize;
471 nCummulator = 0;
472 for( nSourceYSec = nSourceY; nSourceYSec < nSourceYSecEnd; nSourceYSec ++)
473 {
474 for( nSourceXSec = nSourceX; nSourceXSec < nSourceXSecEnd; nSourceXSec ++)
475 {
476 nCummulator += * ( pabySrcTile + ( nSourceYSec / nVerSubsampling ) * nSourceSampleRowSize
477 + ( nSourceYSec % nVerSubsampling ) * nHorSubsampling
478 + ( nSourceXSec / nHorSubsampling ) * nSampleBlockSize
479 + ( nSourceXSec % nHorSubsampling ) );
480 }
481 }
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 );
488 }
489 }
490 }
491 else
492 {
493 nSampleOffsetInSampleBlock = nHorSubsampling * nVerSubsampling + nSample - 1;
494 for( nSourceY = 0, nDestY = ( nTYOff / nVerSubsampling ); nSourceY < ( nBlockYSize / nVerSubsampling );
495 nSourceY += nOMult, nDestY ++)
496 {
497 if( nDestY*nVerSubsampling >= nOBlockYSize )
498 break;
499
500 for( nSourceX = 0, nDestX = ( nTXOff / nHorSubsampling ); nSourceX < ( nBlockXSize / nHorSubsampling );
501 nSourceX += nOMult, nDestX ++)
502 {
503 if( nDestX*nHorSubsampling >= nOBlockXSize )
504 break;
505
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 );
512 nCummulator = 0;
513 for( nSourceYSec = nSourceY; nSourceYSec < nSourceYSecEnd; nSourceYSec ++)
514 {
515 for( nSourceXSec = nSourceX; nSourceXSec < nSourceXSecEnd; nSourceXSec ++)
516 {
517 nCummulator += * ( pabySrcTile + nSourceYSec * nSourceSampleRowSize
518 + nSourceXSec * nSampleBlockSize
519 + nSampleOffsetInSampleBlock );
520 }
521 }
522 nCummulatorCount = ( nSourceXSecEnd - nSourceX ) * ( nSourceYSecEnd - nSourceY );
523 * ( pabyOTile + nDestY * nDestSampleRowSize
524 + nDestX * nSampleBlockSize
525 + nSampleOffsetInSampleBlock ) =
526 ( ( nCummulator + ( nCummulatorCount >> 1 ) ) / nCummulatorCount );
527 }
528 }
529 }
530 }
531 }
532
533 /************************************************************************/
534 /* TIFF_ProcessFullResBlock() */
535 /* */
536 /* Process one block of full res data, downsampling into each */
537 /* of the overviews. */
538 /************************************************************************/
539
540 void TIFF_ProcessFullResBlock( TIFF *hTIFF, int nPlanarConfig,
541 int bSubsampled,
542 int nHorSubsampling, int nVerSubsampling,
543 int nOverviews, int * panOvList,
544 int nBitsPerPixel,
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 )
550
551 {
552 int iOverview, iSample;
553
554 for( iSample = 0; iSample < nSamples; iSample++ )
555 {
556 /*
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.
560 */
561 if( nPlanarConfig == PLANARCONFIG_SEPARATE || iSample == 0 )
562 {
563 if( TIFFIsTiled(hTIFF) )
564 {
565 TIFFReadEncodedTile( hTIFF,
566 TIFFComputeTile(hTIFF, nSXOff, nSYOff,
567 0, (tsample_t)iSample ),
568 pabySrcTile,
569 TIFFTileSize(hTIFF));
570 }
571 else
572 {
573 TIFFReadEncodedStrip( hTIFF,
574 TIFFComputeStrip(hTIFF, nSYOff,
575 (tsample_t) iSample),
576 pabySrcTile,
577 TIFFStripSize(hTIFF) );
578 }
579 }
580
581 /*
582 * Loop over destination overview layers
583 */
584 for( iOverview = 0; iOverview < nOverviews; iOverview++ )
585 {
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;
592
593 /*
594 * Fetch the destination overview tile
595 */
596 nOMult = panOvList[iOverview];
597 nOXOff = (nSXOff/nOMult) / nOBlockXSize;
598 nOYOff = (nSYOff/nOMult) / nOBlockYSize;
599
600 if( bSubsampled )
601 {
602 pabyOTile = TIFFGetOvrBlock_Subsampled( poRBI, nOXOff, nOYOff );
603
604 /*
605 * Establish the offset into this tile at which we should
606 * start placing data.
607 */
608 nTXOff = (nSXOff - nOXOff*nOMult*nOBlockXSize) / nOMult;
609 nTYOff = (nSYOff - nOYOff*nOMult*nOBlockYSize) / nOMult;
610
611
612 #ifdef DBMALLOC
613 malloc_chain_check( 1 );
614 #endif
615 TIFF_DownSample_Subsampled( pabySrcTile, iSample,
616 nBlockXSize, nBlockYSize,
617 pabyOTile,
618 poRBI->nBlockXSize, poRBI->nBlockYSize,
619 nTXOff, nTYOff,
620 nOMult, pszResampling,
621 nHorSubsampling, nVerSubsampling );
622 #ifdef DBMALLOC
623 malloc_chain_check( 1 );
624 #endif
625
626 }
627 else
628 {
629
630 pabyOTile = TIFFGetOvrBlock( poRBI, nOXOff, nOYOff, iSample );
631
632 /*
633 * Establish the offset into this tile at which we should
634 * start placing data.
635 */
636 nTXOff = (nSXOff - nOXOff*nOMult*nOBlockXSize) / nOMult;
637 nTYOff = (nSYOff - nOYOff*nOMult*nOBlockYSize) / nOMult;
638
639 /*
640 * Figure out the skew (extra space between ``our samples'') and
641 * the byte offset to the first sample.
642 */
643 assert( (nBitsPerPixel % 8) == 0 );
644 if( nPlanarConfig == PLANARCONFIG_SEPARATE )
645 {
646 nSkewBits = 0;
647 nSampleByteOffset = 0;
648 }
649 else
650 {
651 nSkewBits = nBitsPerPixel * (nSamples-1);
652 nSampleByteOffset = (nBitsPerPixel/8) * iSample;
653 }
654
655 /*
656 * Perform the downsampling.
657 */
658 #ifdef DBMALLOC
659 malloc_chain_check( 1 );
660 #endif
661 TIFF_DownSample( pabySrcTile + nSampleByteOffset,
662 nBlockXSize, nBlockYSize,
663 nSkewBits, nBitsPerPixel, pabyOTile,
664 poRBI->nBlockXSize, poRBI->nBlockYSize,
665 nTXOff, nTYOff,
666 nOMult, nSampleFormat, pszResampling );
667 #ifdef DBMALLOC
668 malloc_chain_check( 1 );
669 #endif
670 }
671 }
672 }
673 }
674
675 /************************************************************************/
676 /* TIFF_BuildOverviews() */
677 /* */
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 */
682 /* overviews. */
683 /************************************************************************/
684
685 void TIFFBuildOverviews( TIFF *hTIFF, int nOverviews, int * panOvList,
686 int bUseSubIFDs, const char *pszResampleMethod,
687 int (*pfnProgress)( double, void * ),
688 void * pProgressData )
689
690 {
691 TIFFOvrCache **papoRawBIs;
692 uint32 nXSize, nYSize, nBlockXSize, nBlockYSize;
693 uint16 nBitsPerPixel, nPhotometric, nCompressFlag, nSamples,
694 nPlanarConfig, nSampleFormat;
695 int bSubsampled;
696 uint16 nHorSubsampling, nVerSubsampling;
697 int bTiled, nSXOff, nSYOff, i;
698 unsigned char *pabySrcTile;
699 uint16 *panRedMap, *panGreenMap, *panBlueMap;
700 TIFFErrorHandler pfnWarning;
701
702 (void) pfnProgress;
703 (void) pProgressData;
704
705 /* -------------------------------------------------------------------- */
706 /* Get the base raster size. */
707 /* -------------------------------------------------------------------- */
708 TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &nXSize );
709 TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &nYSize );
710
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 );
715
716 TIFFGetFieldDefaulted( hTIFF, TIFFTAG_PHOTOMETRIC, &nPhotometric );
717 TIFFGetFieldDefaulted( hTIFF, TIFFTAG_COMPRESSION, &nCompressFlag );
718 TIFFGetFieldDefaulted( hTIFF, TIFFTAG_SAMPLEFORMAT, &nSampleFormat );
719
720 if( nPhotometric == PHOTOMETRIC_YCBCR || nPhotometric == PHOTOMETRIC_ITULAB )
721 {
722 if( nBitsPerPixel != 8 || nSamples != 3 || nPlanarConfig != PLANARCONFIG_CONTIG ||
723 nSampleFormat != SAMPLEFORMAT_UINT)
724 {
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
732 */
733 return;
734 }
735 bSubsampled = 1;
736 TIFFGetField( hTIFF, TIFFTAG_YCBCRSUBSAMPLING, &nHorSubsampling, &nVerSubsampling );
737 /* TODO: find out if maybe TIFFGetFieldDefaulted is better choice for YCbCrSubsampling tag */
738 }
739 else
740 {
741 if( nBitsPerPixel < 8 )
742 {
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 );
748 return;
749 }
750 bSubsampled = 0;
751 nHorSubsampling = 1;
752 nVerSubsampling = 1;
753 }
754
755 /* -------------------------------------------------------------------- */
756 /* Turn off warnings to avoid alot of repeated warnings while */
757 /* rereading directories. */
758 /* -------------------------------------------------------------------- */
759 pfnWarning = TIFFSetWarningHandler( NULL );
760
761 /* -------------------------------------------------------------------- */
762 /* Get the base raster block size. */
763 /* -------------------------------------------------------------------- */
764 if( TIFFGetField( hTIFF, TIFFTAG_ROWSPERSTRIP, &(nBlockYSize) ) )
765 {
766 nBlockXSize = nXSize;
767 bTiled = FALSE;
768 }
769 else
770 {
771 TIFFGetField( hTIFF, TIFFTAG_TILEWIDTH, &nBlockXSize );
772 TIFFGetField( hTIFF, TIFFTAG_TILELENGTH, &nBlockYSize );
773 bTiled = TRUE;
774 }
775
776 /* -------------------------------------------------------------------- */
777 /* Capture the pallette if there is one. */
778 /* -------------------------------------------------------------------- */
779 if( TIFFGetField( hTIFF, TIFFTAG_COLORMAP,
780 &panRedMap, &panGreenMap, &panBlueMap ) )
781 {
782 uint16 *panRed2, *panGreen2, *panBlue2;
783 int nColorCount = 1 << nBitsPerPixel;
784
785 panRed2 = (uint16 *) _TIFFmalloc(2*nColorCount);
786 panGreen2 = (uint16 *) _TIFFmalloc(2*nColorCount);
787 panBlue2 = (uint16 *) _TIFFmalloc(2*nColorCount);
788
789 memcpy( panRed2, panRedMap, 2 * nColorCount );
790 memcpy( panGreen2, panGreenMap, 2 * nColorCount );
791 memcpy( panBlue2, panBlueMap, 2 * nColorCount );
792
793 panRedMap = panRed2;
794 panGreenMap = panGreen2;
795 panBlueMap = panBlue2;
796 }
797 else
798 {
799 panRedMap = panGreenMap = panBlueMap = NULL;
800 }
801
802 /* -------------------------------------------------------------------- */
803 /* Initialize overviews. */
804 /* -------------------------------------------------------------------- */
805 papoRawBIs = (TIFFOvrCache **) _TIFFmalloc(nOverviews*sizeof(void*));
806
807 for( i = 0; i < nOverviews; i++ )
808 {
809 uint32 nOXSize, nOYSize, nOBlockXSize, nOBlockYSize;
810 toff_t nDirOffset;
811
812 nOXSize = (nXSize + panOvList[i] - 1) / panOvList[i];
813 nOYSize = (nYSize + panOvList[i] - 1) / panOvList[i];
814
815 nOBlockXSize = MIN(nBlockXSize,nOXSize);
816 nOBlockYSize = MIN(nBlockYSize,nOYSize);
817
818 if( bTiled )
819 {
820 if( (nOBlockXSize % 16) != 0 )
821 nOBlockXSize = nOBlockXSize + 16 - (nOBlockXSize % 16);
822
823 if( (nOBlockYSize % 16) != 0 )
824 nOBlockYSize = nOBlockYSize + 16 - (nOBlockYSize % 16);
825 }
826
827 nDirOffset = TIFF_WriteOverview( hTIFF, nOXSize, nOYSize,
828 nBitsPerPixel, nPlanarConfig,
829 nSamples, nOBlockXSize, nOBlockYSize,
830 bTiled, nCompressFlag, nPhotometric,
831 nSampleFormat,
832 panRedMap, panGreenMap, panBlueMap,
833 bUseSubIFDs,
834 nHorSubsampling, nVerSubsampling );
835
836 papoRawBIs[i] = TIFFCreateOvrCache( hTIFF, nDirOffset );
837 }
838
839 if( panRedMap != NULL )
840 {
841 _TIFFfree( panRedMap );
842 _TIFFfree( panGreenMap );
843 _TIFFfree( panBlueMap );
844 }
845
846 /* -------------------------------------------------------------------- */
847 /* Allocate a buffer to hold a source block. */
848 /* -------------------------------------------------------------------- */
849 if( bTiled )
850 pabySrcTile = (unsigned char *) _TIFFmalloc(TIFFTileSize(hTIFF));
851 else
852 pabySrcTile = (unsigned char *) _TIFFmalloc(TIFFStripSize(hTIFF));
853
854 /* -------------------------------------------------------------------- */
855 /* Loop over the source raster, applying data to the */
856 /* destination raster. */
857 /* -------------------------------------------------------------------- */
858 for( nSYOff = 0; nSYOff < (int) nYSize; nSYOff += nBlockYSize )
859 {
860 for( nSXOff = 0; nSXOff < (int) nXSize; nSXOff += nBlockXSize )
861 {
862 /*
863 * Read and resample into the various overview images.
864 */
865
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 );
873 }
874 }
875
876 _TIFFfree( pabySrcTile );
877
878 /* -------------------------------------------------------------------- */
879 /* Cleanup the rawblockedimage files. */
880 /* -------------------------------------------------------------------- */
881 for( i = 0; i < nOverviews; i++ )
882 {
883 TIFFDestroyOvrCache( papoRawBIs[i] );
884 }
885
886 if( papoRawBIs != NULL )
887 _TIFFfree( papoRawBIs );
888
889 TIFFSetWarningHandler( pfnWarning );
890 }
891
892
893 /*
894 * Local Variables:
895 * mode: c
896 * c-basic-offset: 8
897 * fill-column: 78
898 * End:
899 */