]> git.saurik.com Git - wxWidgets.git/blob - src/tiff/contrib/addtiffo/tif_overview.c
Correct bug in the wxSpinCtrlGeneric sub-controls resizing.
[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, int nXSize, int 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 uint32 nBaseDirOffset;
93 uint32 nOffset;
94
95 nBaseDirOffset = TIFFCurrentDirOffset( hTIFF );
96
97 TIFFCreateDirectory( hTIFF );
98
99 /* -------------------------------------------------------------------- */
100 /* Setup TIFF fields. */
101 /* -------------------------------------------------------------------- */
102 TIFFSetField( hTIFF, TIFFTAG_IMAGEWIDTH, nXSize );
103 TIFFSetField( hTIFF, TIFFTAG_IMAGELENGTH, nYSize );
104 if( nSamples == 1 )
105 TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG );
106 else
107 TIFFSetField( hTIFF, TIFFTAG_PLANARCONFIG, nPlanarConfig );
108
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 );
114
115 if( bTiled )
116 {
117 TIFFSetField( hTIFF, TIFFTAG_TILEWIDTH, nBlockXSize );
118 TIFFSetField( hTIFF, TIFFTAG_TILELENGTH, nBlockYSize );
119 }
120 else
121 TIFFSetField( hTIFF, TIFFTAG_ROWSPERSTRIP, nBlockYSize );
122
123 TIFFSetField( hTIFF, TIFFTAG_SUBFILETYPE, FILETYPE_REDUCEDIMAGE );
124
125 if( nPhotometric == PHOTOMETRIC_YCBCR || nPhotometric == PHOTOMETRIC_ITULAB )
126 {
127 TIFFSetField( hTIFF, TIFFTAG_YCBCRSUBSAMPLING, nHorSubsampling, nVerSubsampling);
128 /* TODO: also write YCbCrPositioning and YCbCrCoefficients tag identical to source IFD */
129 }
130 /* TODO: add command-line parameter for selecting jpeg compression quality
131 * that gets ignored when compression isn't jpeg */
132
133 /* -------------------------------------------------------------------- */
134 /* Write color table if one is present. */
135 /* -------------------------------------------------------------------- */
136 if( panRed != NULL )
137 {
138 TIFFSetField( hTIFF, TIFFTAG_COLORMAP, panRed, panGreen, panBlue );
139 }
140
141 /* -------------------------------------------------------------------- */
142 /* Write directory, and return byte offset. */
143 /* -------------------------------------------------------------------- */
144 if( TIFFWriteCheck( hTIFF, bTiled, "TIFFBuildOverviews" ) == 0 )
145 return 0;
146
147 TIFFWriteDirectory( hTIFF );
148 TIFFSetDirectory( hTIFF, (tdir_t) (TIFFNumberOfDirectories(hTIFF)-1) );
149
150 nOffset = TIFFCurrentDirOffset( hTIFF );
151
152 TIFFSetSubDirectory( hTIFF, nBaseDirOffset );
153
154 return nOffset;
155 }
156
157 /************************************************************************/
158 /* TIFF_GetSourceSamples() */
159 /************************************************************************/
160
161 static void
162 TIFF_GetSourceSamples( double * padfSamples, unsigned char *pabySrc,
163 int nPixelBytes, int nSampleFormat,
164 int nXSize, int nYSize,
165 int nPixelOffset, int nLineOffset )
166 {
167 int iXOff, iYOff, iSample;
168
169 iSample = 0;
170
171 for( iYOff = 0; iYOff < nYSize; iYOff++ )
172 {
173 for( iXOff = 0; iXOff < nXSize; iXOff++ )
174 {
175 unsigned char *pabyData;
176
177 pabyData = pabySrc + iYOff * nLineOffset + iXOff * nPixelOffset;
178
179 if( nSampleFormat == SAMPLEFORMAT_UINT && nPixelBytes == 1 )
180 {
181 padfSamples[iSample++] = *pabyData;
182 }
183 else if( nSampleFormat == SAMPLEFORMAT_UINT && nPixelBytes == 2 )
184 {
185 padfSamples[iSample++] = ((uint16 *) pabyData)[0];
186 }
187 else if( nSampleFormat == SAMPLEFORMAT_UINT && nPixelBytes == 4 )
188 {
189 padfSamples[iSample++] = ((uint32 *) pabyData)[0];
190 }
191 else if( nSampleFormat == SAMPLEFORMAT_INT && nPixelBytes == 2 )
192 {
193 padfSamples[iSample++] = ((int16 *) pabyData)[0];
194 }
195 else if( nSampleFormat == SAMPLEFORMAT_INT && nPixelBytes == 32 )
196 {
197 padfSamples[iSample++] = ((int32 *) pabyData)[0];
198 }
199 else if( nSampleFormat == SAMPLEFORMAT_IEEEFP && nPixelBytes == 4 )
200 {
201 padfSamples[iSample++] = ((float *) pabyData)[0];
202 }
203 else if( nSampleFormat == SAMPLEFORMAT_IEEEFP && nPixelBytes == 8 )
204 {
205 padfSamples[iSample++] = ((double *) pabyData)[0];
206 }
207 }
208 }
209 }
210
211 /************************************************************************/
212 /* TIFF_SetSample() */
213 /************************************************************************/
214
215 static void
216 TIFF_SetSample( unsigned char * pabyData, int nPixelBytes, int nSampleFormat,
217 double dfValue )
218
219 {
220 if( nSampleFormat == SAMPLEFORMAT_UINT && nPixelBytes == 1 )
221 {
222 *pabyData = (unsigned char) MAX(0,MIN(255,dfValue));
223 }
224 else if( nSampleFormat == SAMPLEFORMAT_UINT && nPixelBytes == 2 )
225 {
226 *((uint16 *)pabyData) = (uint16) MAX(0,MIN(65535,dfValue));
227 }
228 else if( nSampleFormat == SAMPLEFORMAT_UINT && nPixelBytes == 4 )
229 {
230 *((uint32 *)pabyData) = (uint32) dfValue;
231 }
232 else if( nSampleFormat == SAMPLEFORMAT_INT && nPixelBytes == 2 )
233 {
234 *((int16 *)pabyData) = (int16) MAX(-32768,MIN(32767,dfValue));
235 }
236 else if( nSampleFormat == SAMPLEFORMAT_INT && nPixelBytes == 32 )
237 {
238 *((int32 *)pabyData) = (int32) dfValue;
239 }
240 else if( nSampleFormat == SAMPLEFORMAT_IEEEFP && nPixelBytes == 4 )
241 {
242 *((float *)pabyData) = (float) dfValue;
243 }
244 else if( nSampleFormat == SAMPLEFORMAT_IEEEFP && nPixelBytes == 8 )
245 {
246 *((double *)pabyData) = dfValue;
247 }
248 }
249
250 /************************************************************************/
251 /* TIFF_DownSample() */
252 /* */
253 /* Down sample a tile of full res data into a window of a tile */
254 /* of downsampled data. */
255 /************************************************************************/
256
257 static
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 )
265
266 {
267 int i, j, k, nPixelBytes = (nBitsPerPixel) / 8;
268 int nPixelGroupBytes = (nBitsPerPixel+nPixelSkewBits)/8;
269 unsigned char *pabySrc, *pabyDst;
270 double *padfSamples;
271
272 assert( nBitsPerPixel >= 8 );
273
274 padfSamples = (double *) malloc(sizeof(double) * nOMult * nOMult);
275
276 /* ==================================================================== */
277 /* Loop over scanline chunks to process, establishing where the */
278 /* data is going. */
279 /* ==================================================================== */
280 for( j = 0; j*nOMult < nBlockYSize; j++ )
281 {
282 if( j + nTYOff >= nOBlockYSize )
283 break;
284
285 pabyDst = pabyOTile + ((j+nTYOff)*nOBlockXSize + nTXOff)
286 * nPixelBytes * nPixelGroupBytes;
287
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 )
294 {
295 pabySrc = pabySrcTile + j*nOMult*nBlockXSize * nPixelGroupBytes;
296
297 for( i = 0; i*nOMult < nBlockXSize; i++ )
298 {
299 if( i + nTXOff >= nOBlockXSize )
300 break;
301
302 /*
303 * For now use simple subsampling, from the top left corner
304 * of the source block of pixels.
305 */
306
307 for( k = 0; k < nPixelBytes; k++ )
308 pabyDst[k] = pabySrc[k];
309
310 pabyDst += nPixelBytes * nPixelGroupBytes;
311 pabySrc += nOMult * nPixelGroupBytes;
312 }
313 }
314
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 )
321 {
322 pabySrc = pabySrcTile + j*nOMult*nBlockXSize * nPixelGroupBytes;
323
324 for( i = 0; i*nOMult < nBlockXSize; i++ )
325 {
326 double dfTotal;
327 int iSample;
328 int nXSize, nYSize;
329
330 if( i + nTXOff >= nOBlockXSize )
331 break;
332
333 nXSize = MIN(nOMult,nBlockXSize-i);
334 nYSize = MIN(nOMult,nBlockYSize-j);
335
336 TIFF_GetSourceSamples( padfSamples, pabySrc,
337 nPixelBytes, nSampleFormat,
338 nXSize, nYSize,
339 nPixelGroupBytes,
340 nPixelGroupBytes * nBlockXSize );
341
342 dfTotal = 0;
343 for( iSample = 0; iSample < nXSize*nYSize; iSample++ )
344 {
345 dfTotal += padfSamples[iSample];
346 }
347
348 TIFF_SetSample( pabyDst, nPixelBytes, nSampleFormat,
349 dfTotal / (nXSize*nYSize) );
350
351 pabySrc += nOMult * nPixelGroupBytes;
352 pabyDst += nPixelBytes;
353 }
354 }
355 }
356
357 free( padfSamples );
358 }
359
360 static
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 )
368 {
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;
376 int nDestX, nDestY;
377 int nSampleOffsetInSampleBlock;
378 unsigned char * pSourceBase;
379 unsigned char * pDestBase;
380 int nSourceBaseInc;
381 unsigned char * pSourceBaseEnd;
382 unsigned int nCummulator;
383 unsigned int nCummulatorCount;
384
385 nSampleBlockSize = nHorSubsampling * nVerSubsampling + 2;
386 nSourceSampleRowSize = ( ( nBlockXSize + nHorSubsampling - 1 ) / nHorSubsampling ) * nSampleBlockSize;
387 nDestSampleRowSize = ( ( nOBlockXSize + nHorSubsampling - 1 ) / nHorSubsampling ) * nSampleBlockSize;
388
389 if( strncmp(pszResampling,"nearest",4) == 0
390 || strncmp(pszResampling,"NEAR",4) == 0 )
391 {
392 if( nSample == 0 )
393 {
394 #ifdef NOOPTIMIZATION
395 /*
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
398 */
399 for( nSourceY = 0, nDestY = nTYOff; nSourceY < nBlockYSize; nSourceY += nOMult, nDestY ++)
400 {
401 for( nSourceX = 0, nDestX = nTXOff; nSourceX < nBlockXSize; nSourceX += nOMult, nDestX ++)
402 {
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 ) );
411 }
412 }
413 #else
414 for( nSourceY = 0, nDestY = nTYOff; nSourceY < nBlockYSize; nSourceY += nOMult, nDestY ++)
415 {
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 ++)
421 {
422 * ( pDestBase + ( nDestX / nHorSubsampling ) * nSampleBlockSize
423 + ( nDestX % nHorSubsampling ) ) =
424 * ( pSourceBase + ( nSourceX / nHorSubsampling ) * nSampleBlockSize
425 + ( nSourceX % nHorSubsampling ) );
426 }
427 }
428 #endif
429 }
430 else
431 {
432 #ifdef NOOPTIMIZATION
433 /*
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
436 */
437 nSampleOffsetInSampleBlock = nHorSubsampling * nVerSubsampling + nSample - 1;
438 for( nSourceY = 0, nDestY = ( nTYOff / nVerSubsampling ); nSourceY < ( nBlockYSize / nVerSubsampling );
439 nSourceY += nOMult, nDestY ++)
440 {
441 for( nSourceX = 0, nDestX = ( nTXOff / nHorSubsampling ); nSourceX < ( nBlockXSize / nHorSubsampling );
442 nSourceX += nOMult, nDestX ++)
443 {
444 * ( pabyOTile + nDestY * nDestSampleRowSize
445 + nDestX * nSampleBlockSize
446 + nSampleOffsetInSampleBlock ) =
447 * ( pabySrcTile + nSourceY * nSourceSampleRowSize
448 + nSourceX * nSampleBlockSize
449 + nSampleOffsetInSampleBlock );
450 }
451 }
452 #else
453 nSampleOffsetInSampleBlock = nHorSubsampling * nVerSubsampling + nSample - 1;
454 nSourceBaseInc = nOMult * nSampleBlockSize;
455 for( nSourceY = 0, nDestY = ( nTYOff / nVerSubsampling ); nSourceY < ( nBlockYSize / nVerSubsampling);
456 nSourceY += nOMult, nDestY ++)
457 {
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;
466 }
467 #endif
468 }
469 }
470 else if( strncmp(pszResampling,"averag",6) == 0
471 || strncmp(pszResampling,"AVERAG",6) == 0 )
472 {
473 if( nSample == 0 )
474 {
475 for( nSourceY = 0, nDestY = nTYOff; nSourceY < nBlockYSize; nSourceY += nOMult, nDestY ++)
476 {
477 for( nSourceX = 0, nDestX = nTXOff; nSourceX < nBlockXSize; nSourceX += nOMult, nDestX ++)
478 {
479 nSourceXSecEnd = nSourceX + nOMult;
480 if( nSourceXSecEnd > nBlockXSize )
481 nSourceXSecEnd = nBlockXSize;
482 nSourceYSecEnd = nSourceY + nOMult;
483 if( nSourceYSecEnd > nBlockYSize )
484 nSourceYSecEnd = nBlockYSize;
485 nCummulator = 0;
486 for( nSourceYSec = nSourceY; nSourceYSec < nSourceYSecEnd; nSourceYSec ++)
487 {
488 for( nSourceXSec = nSourceX; nSourceXSec < nSourceXSecEnd; nSourceXSec ++)
489 {
490 nCummulator += * ( pabySrcTile + ( nSourceYSec / nVerSubsampling ) * nSourceSampleRowSize
491 + ( nSourceYSec % nVerSubsampling ) * nHorSubsampling
492 + ( nSourceXSec / nHorSubsampling ) * nSampleBlockSize
493 + ( nSourceXSec % nHorSubsampling ) );
494 }
495 }
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 );
502 }
503 }
504 }
505 else
506 {
507 nSampleOffsetInSampleBlock = nHorSubsampling * nVerSubsampling + nSample - 1;
508 for( nSourceY = 0, nDestY = ( nTYOff / nVerSubsampling ); nSourceY < ( nBlockYSize / nVerSubsampling );
509 nSourceY += nOMult, nDestY ++)
510 {
511 for( nSourceX = 0, nDestX = ( nTXOff / nHorSubsampling ); nSourceX < ( nBlockXSize / nHorSubsampling );
512 nSourceX += nOMult, nDestX ++)
513 {
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 );
520 nCummulator = 0;
521 for( nSourceYSec = nSourceY; nSourceYSec < nSourceYSecEnd; nSourceYSec ++)
522 {
523 for( nSourceXSec = nSourceX; nSourceXSec < nSourceXSecEnd; nSourceXSec ++)
524 {
525 nCummulator += * ( pabySrcTile + nSourceYSec * nSourceSampleRowSize
526 + nSourceXSec * nSampleBlockSize
527 + nSampleOffsetInSampleBlock );
528 }
529 }
530 nCummulatorCount = ( nSourceXSecEnd - nSourceX ) * ( nSourceYSecEnd - nSourceY );
531 * ( pabyOTile + nDestY * nDestSampleRowSize
532 + nDestX * nSampleBlockSize
533 + nSampleOffsetInSampleBlock ) =
534 ( ( nCummulator + ( nCummulatorCount >> 1 ) ) / nCummulatorCount );
535 }
536 }
537 }
538 }
539 }
540
541 /************************************************************************/
542 /* TIFF_ProcessFullResBlock() */
543 /* */
544 /* Process one block of full res data, downsampling into each */
545 /* of the overviews. */
546 /************************************************************************/
547
548 void TIFF_ProcessFullResBlock( TIFF *hTIFF, int nPlanarConfig,
549 int bSubsampled, int nHorSubsampling, int nVerSubsampling,
550 int nOverviews, int * panOvList,
551 int nBitsPerPixel,
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 )
557
558 {
559 int iOverview, iSample;
560
561 for( iSample = 0; iSample < nSamples; iSample++ )
562 {
563 /*
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.
567 */
568 if( nPlanarConfig == PLANARCONFIG_SEPARATE || iSample == 0 )
569 {
570 if( TIFFIsTiled(hTIFF) )
571 {
572 TIFFReadEncodedTile( hTIFF,
573 TIFFComputeTile(hTIFF, nSXOff, nSYOff,
574 0, (tsample_t)iSample ),
575 pabySrcTile,
576 TIFFTileSize(hTIFF));
577 }
578 else
579 {
580 TIFFReadEncodedStrip( hTIFF,
581 TIFFComputeStrip(hTIFF, nSYOff,
582 (tsample_t) iSample),
583 pabySrcTile,
584 TIFFStripSize(hTIFF) );
585 }
586 }
587
588 /*
589 * Loop over destination overview layers
590 */
591 for( iOverview = 0; iOverview < nOverviews; iOverview++ )
592 {
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;
599
600 /*
601 * Fetch the destination overview tile
602 */
603 nOMult = panOvList[iOverview];
604 nOXOff = (nSXOff/nOMult) / nOBlockXSize;
605 nOYOff = (nSYOff/nOMult) / nOBlockYSize;
606
607 if( bSubsampled )
608 {
609 pabyOTile = TIFFGetOvrBlock_Subsampled( poRBI, nOXOff, nOYOff );
610
611 /*
612 * Establish the offset into this tile at which we should
613 * start placing data.
614 */
615 nTXOff = (nSXOff - nOXOff*nOMult*nOBlockXSize) / nOMult;
616 nTYOff = (nSYOff - nOYOff*nOMult*nOBlockYSize) / nOMult;
617
618
619 #ifdef DBMALLOC
620 malloc_chain_check( 1 );
621 #endif
622 TIFF_DownSample_Subsampled( pabySrcTile, iSample,
623 nBlockXSize, nBlockYSize,
624 pabyOTile,
625 poRBI->nBlockXSize, poRBI->nBlockYSize,
626 nTXOff, nTYOff,
627 nOMult, pszResampling,
628 nHorSubsampling, nVerSubsampling );
629 #ifdef DBMALLOC
630 malloc_chain_check( 1 );
631 #endif
632
633 }
634 else
635 {
636
637 pabyOTile = TIFFGetOvrBlock( poRBI, nOXOff, nOYOff, iSample );
638
639 /*
640 * Establish the offset into this tile at which we should
641 * start placing data.
642 */
643 nTXOff = (nSXOff - nOXOff*nOMult*nOBlockXSize) / nOMult;
644 nTYOff = (nSYOff - nOYOff*nOMult*nOBlockYSize) / nOMult;
645
646 /*
647 * Figure out the skew (extra space between ``our samples'') and
648 * the byte offset to the first sample.
649 */
650 assert( (nBitsPerPixel % 8) == 0 );
651 if( nPlanarConfig == PLANARCONFIG_SEPARATE )
652 {
653 nSkewBits = 0;
654 nSampleByteOffset = 0;
655 }
656 else
657 {
658 nSkewBits = nBitsPerPixel * (nSamples-1);
659 nSampleByteOffset = (nBitsPerPixel/8) * iSample;
660 }
661
662 /*
663 * Perform the downsampling.
664 */
665 #ifdef DBMALLOC
666 malloc_chain_check( 1 );
667 #endif
668 TIFF_DownSample( pabySrcTile + nSampleByteOffset,
669 nBlockXSize, nBlockYSize,
670 nSkewBits, nBitsPerPixel, pabyOTile,
671 poRBI->nBlockXSize, poRBI->nBlockYSize,
672 nTXOff, nTYOff,
673 nOMult, nSampleFormat, pszResampling );
674 #ifdef DBMALLOC
675 malloc_chain_check( 1 );
676 #endif
677 }
678 }
679 }
680 }
681
682 /************************************************************************/
683 /* TIFF_BuildOverviews() */
684 /* */
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 */
689 /* overviews. */
690 /************************************************************************/
691
692 void TIFFBuildOverviews( TIFF *hTIFF, int nOverviews, int * panOvList,
693 int bUseSubIFDs, const char *pszResampleMethod,
694 int (*pfnProgress)( double, void * ),
695 void * pProgressData )
696
697 {
698 TIFFOvrCache **papoRawBIs;
699 uint32 nXSize, nYSize, nBlockXSize, nBlockYSize;
700 uint16 nBitsPerPixel, nPhotometric, nCompressFlag, nSamples,
701 nPlanarConfig, nSampleFormat;
702 int bSubsampled;
703 uint16 nHorSubsampling, nVerSubsampling;
704 int bTiled, nSXOff, nSYOff, i;
705 unsigned char *pabySrcTile;
706 uint16 *panRedMap, *panGreenMap, *panBlueMap;
707 TIFFErrorHandler pfnWarning;
708
709 /* -------------------------------------------------------------------- */
710 /* Get the base raster size. */
711 /* -------------------------------------------------------------------- */
712 TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &nXSize );
713 TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &nYSize );
714
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 );
719
720 TIFFGetFieldDefaulted( hTIFF, TIFFTAG_PHOTOMETRIC, &nPhotometric );
721 TIFFGetFieldDefaulted( hTIFF, TIFFTAG_COMPRESSION, &nCompressFlag );
722 TIFFGetFieldDefaulted( hTIFF, TIFFTAG_SAMPLEFORMAT, &nSampleFormat );
723
724 if( nPhotometric == PHOTOMETRIC_YCBCR || nPhotometric == PHOTOMETRIC_ITULAB )
725 {
726 if( nBitsPerPixel != 8 || nSamples != 3 || nPlanarConfig != PLANARCONFIG_CONTIG ||
727 nSampleFormat != SAMPLEFORMAT_UINT)
728 {
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
736 */
737 return;
738 }
739 bSubsampled = 1;
740 TIFFGetField( hTIFF, TIFFTAG_YCBCRSUBSAMPLING, &nHorSubsampling, &nVerSubsampling );
741 /* TODO: find out if maybe TIFFGetFieldDefaulted is better choice for YCbCrSubsampling tag */
742 }
743 else
744 {
745 if( nBitsPerPixel < 8 )
746 {
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 );
752 return;
753 }
754 bSubsampled = 0;
755 nHorSubsampling = 1;
756 nVerSubsampling = 1;
757 }
758
759 /* -------------------------------------------------------------------- */
760 /* Turn off warnings to avoid alot of repeated warnings while */
761 /* rereading directories. */
762 /* -------------------------------------------------------------------- */
763 pfnWarning = TIFFSetWarningHandler( NULL );
764
765 /* -------------------------------------------------------------------- */
766 /* Get the base raster block size. */
767 /* -------------------------------------------------------------------- */
768 if( TIFFGetField( hTIFF, TIFFTAG_ROWSPERSTRIP, &(nBlockYSize) ) )
769 {
770 nBlockXSize = nXSize;
771 bTiled = FALSE;
772 }
773 else
774 {
775 TIFFGetField( hTIFF, TIFFTAG_TILEWIDTH, &nBlockXSize );
776 TIFFGetField( hTIFF, TIFFTAG_TILELENGTH, &nBlockYSize );
777 bTiled = TRUE;
778 }
779
780 /* -------------------------------------------------------------------- */
781 /* Capture the pallette if there is one. */
782 /* -------------------------------------------------------------------- */
783 if( TIFFGetField( hTIFF, TIFFTAG_COLORMAP,
784 &panRedMap, &panGreenMap, &panBlueMap ) )
785 {
786 uint16 *panRed2, *panGreen2, *panBlue2;
787 int nColorCount = 1 << nBitsPerPixel;
788
789 panRed2 = (uint16 *) _TIFFmalloc(2*nColorCount);
790 panGreen2 = (uint16 *) _TIFFmalloc(2*nColorCount);
791 panBlue2 = (uint16 *) _TIFFmalloc(2*nColorCount);
792
793 memcpy( panRed2, panRedMap, 2 * nColorCount );
794 memcpy( panGreen2, panGreenMap, 2 * nColorCount );
795 memcpy( panBlue2, panBlueMap, 2 * nColorCount );
796
797 panRedMap = panRed2;
798 panGreenMap = panGreen2;
799 panBlueMap = panBlue2;
800 }
801 else
802 {
803 panRedMap = panGreenMap = panBlueMap = NULL;
804 }
805
806 /* -------------------------------------------------------------------- */
807 /* Initialize overviews. */
808 /* -------------------------------------------------------------------- */
809 papoRawBIs = (TIFFOvrCache **) _TIFFmalloc(nOverviews*sizeof(void*));
810
811 for( i = 0; i < nOverviews; i++ )
812 {
813 int nOXSize, nOYSize, nOBlockXSize, nOBlockYSize;
814 uint32 nDirOffset;
815
816 nOXSize = (nXSize + panOvList[i] - 1) / panOvList[i];
817 nOYSize = (nYSize + panOvList[i] - 1) / panOvList[i];
818
819 nOBlockXSize = MIN((int)nBlockXSize,nOXSize);
820 nOBlockYSize = MIN((int)nBlockYSize,nOYSize);
821
822 if( bTiled )
823 {
824 if( (nOBlockXSize % 16) != 0 )
825 nOBlockXSize = nOBlockXSize + 16 - (nOBlockXSize % 16);
826
827 if( (nOBlockYSize % 16) != 0 )
828 nOBlockYSize = nOBlockYSize + 16 - (nOBlockYSize % 16);
829 }
830
831 nDirOffset = TIFF_WriteOverview( hTIFF, nOXSize, nOYSize,
832 nBitsPerPixel, nPlanarConfig,
833 nSamples, nOBlockXSize, nOBlockYSize,
834 bTiled, nCompressFlag, nPhotometric,
835 nSampleFormat,
836 panRedMap, panGreenMap, panBlueMap,
837 bUseSubIFDs,
838 nHorSubsampling, nVerSubsampling );
839
840 papoRawBIs[i] = TIFFCreateOvrCache( hTIFF, nDirOffset );
841 }
842
843 if( panRedMap != NULL )
844 {
845 _TIFFfree( panRedMap );
846 _TIFFfree( panGreenMap );
847 _TIFFfree( panBlueMap );
848 }
849
850 /* -------------------------------------------------------------------- */
851 /* Allocate a buffer to hold a source block. */
852 /* -------------------------------------------------------------------- */
853 if( bTiled )
854 pabySrcTile = (unsigned char *) _TIFFmalloc(TIFFTileSize(hTIFF));
855 else
856 pabySrcTile = (unsigned char *) _TIFFmalloc(TIFFStripSize(hTIFF));
857
858 /* -------------------------------------------------------------------- */
859 /* Loop over the source raster, applying data to the */
860 /* destination raster. */
861 /* -------------------------------------------------------------------- */
862 for( nSYOff = 0; nSYOff < (int) nYSize; nSYOff += nBlockYSize )
863 {
864 for( nSXOff = 0; nSXOff < (int) nXSize; nSXOff += nBlockXSize )
865 {
866 /*
867 * Read and resample into the various overview images.
868 */
869
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 );
877 }
878 }
879
880 _TIFFfree( pabySrcTile );
881
882 /* -------------------------------------------------------------------- */
883 /* Cleanup the rawblockedimage files. */
884 /* -------------------------------------------------------------------- */
885 for( i = 0; i < nOverviews; i++ )
886 {
887 TIFFDestroyOvrCache( papoRawBIs[i] );
888 }
889
890 if( papoRawBIs != NULL )
891 _TIFFfree( papoRawBIs );
892
893 TIFFSetWarningHandler( pfnWarning );
894 }
895
896