]> git.saurik.com Git - wxWidgets.git/blame - src/tiff/contrib/addtiffo/tif_overview.c
wxMessageBox off the main thread lost result code.
[wxWidgets.git] / src / tiff / contrib / addtiffo / tif_overview.c
CommitLineData
8414a40c
VZ
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
68void 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
80ed523f 80uint32 TIFF_WriteOverview( TIFF *hTIFF, uint32 nXSize, uint32 nYSize,
8414a40c
VZ
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{
80ed523f
VZ
92 toff_t nBaseDirOffset;
93 toff_t nOffset;
94
95 (void) bUseSubIFDs;
8414a40c
VZ
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
163static void
164TIFF_GetSourceSamples( double * padfSamples, unsigned char *pabySrc,
165 int nPixelBytes, int nSampleFormat,
80ed523f 166 uint32 nXSize, uint32 nYSize,
8414a40c
VZ
167 int nPixelOffset, int nLineOffset )
168{
80ed523f
VZ
169 uint32 iXOff, iYOff;
170 int iSample;
8414a40c
VZ
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
218static void
219TIFF_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
260static
261void TIFF_DownSample( unsigned char *pabySrcTile,
80ed523f 262 uint32 nBlockXSize, uint32 nBlockYSize,
8414a40c
VZ
263 int nPixelSkewBits, int nBitsPerPixel,
264 unsigned char * pabyOTile,
80ed523f
VZ
265 uint32 nOBlockXSize, uint32 nOBlockYSize,
266 uint32 nTXOff, uint32 nTYOff, int nOMult,
8414a40c
VZ
267 int nSampleFormat, const char * pszResampling )
268
269{
80ed523f
VZ
270 uint32 i, j;
271 int k, nPixelBytes = (nBitsPerPixel) / 8;
8414a40c
VZ
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;
80ed523f 331 uint32 nXSize, nYSize, iSample;
8414a40c
VZ
332
333 if( i + nTXOff >= nOBlockXSize )
334 break;
335
80ed523f
VZ
336 nXSize = MIN((uint32)nOMult,nBlockXSize-i);
337 nYSize = MIN((uint32)nOMult,nBlockYSize-j);
8414a40c
VZ
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
80ed523f
VZ
363/************************************************************************/
364/* TIFF_DownSample_Subsampled() */
365/************************************************************************/
8414a40c
VZ
366static
367void TIFF_DownSample_Subsampled( unsigned char *pabySrcTile, int nSample,
80ed523f 368 uint32 nBlockXSize, uint32 nBlockYSize,
8414a40c 369 unsigned char * pabyOTile,
80ed523f
VZ
370 uint32 nOBlockXSize, uint32 nOBlockYSize,
371 uint32 nTXOff, uint32 nTYOff, int nOMult,
372 const char *pszResampling,
8414a40c
VZ
373 int nHorSubsampling, int nVerSubsampling )
374{
375 /* TODO: test with variety of subsampling values, and incovinient tile/strip sizes */
80ed523f 376 int nSampleBlockSize;
8414a40c
VZ
377 int nSourceSampleRowSize;
378 int nDestSampleRowSize;
80ed523f
VZ
379 uint32 nSourceX, nSourceY;
380 uint32 nSourceXSec, nSourceYSec;
381 uint32 nSourceXSecEnd, nSourceYSecEnd;
382 uint32 nDestX, nDestY;
8414a40c 383 int nSampleOffsetInSampleBlock;
8414a40c
VZ
384 unsigned int nCummulator;
385 unsigned int nCummulatorCount;
386
387 nSampleBlockSize = nHorSubsampling * nVerSubsampling + 2;
80ed523f
VZ
388 nSourceSampleRowSize =
389 ( ( nBlockXSize + nHorSubsampling - 1 ) / nHorSubsampling ) * nSampleBlockSize;
390 nDestSampleRowSize =
391 ( ( nOBlockXSize + nHorSubsampling - 1 ) / nHorSubsampling ) * nSampleBlockSize;
8414a40c
VZ
392
393 if( strncmp(pszResampling,"nearest",4) == 0
80ed523f
VZ
394 || strncmp(pszResampling,"NEAR",4) == 0 )
395 {
8414a40c
VZ
396 if( nSample == 0 )
397 {
80ed523f
VZ
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 ++)
8414a40c 408 {
80ed523f
VZ
409 if( nDestX >= nOBlockXSize )
410 break;
411
8414a40c 412 * ( pabyOTile + ( nDestY / nVerSubsampling ) * nDestSampleRowSize
80ed523f
VZ
413 + ( nDestY % nVerSubsampling ) * nHorSubsampling
414 + ( nDestX / nHorSubsampling ) * nSampleBlockSize
415 + ( nDestX % nHorSubsampling ) ) =
8414a40c 416 * ( pabySrcTile + ( nSourceY / nVerSubsampling ) * nSourceSampleRowSize
80ed523f
VZ
417 + ( nSourceY % nVerSubsampling ) * nHorSubsampling
418 + ( nSourceX / nHorSubsampling ) * nSampleBlockSize
419 + ( nSourceX % nHorSubsampling ) );
8414a40c
VZ
420 }
421 }
8414a40c
VZ
422 }
423 else
424 {
8414a40c 425 nSampleOffsetInSampleBlock = nHorSubsampling * nVerSubsampling + nSample - 1;
80ed523f
VZ
426 for( nSourceY = 0, nDestY = ( nTYOff / nVerSubsampling );
427 nSourceY < ( nBlockYSize / nVerSubsampling );
428 nSourceY += nOMult, nDestY ++)
8414a40c 429 {
80ed523f
VZ
430 if( nDestY*nVerSubsampling >= nOBlockYSize )
431 break;
432
433 for( nSourceX = 0, nDestX = ( nTXOff / nHorSubsampling );
434 nSourceX < ( nBlockXSize / nHorSubsampling );
435 nSourceX += nOMult, nDestX ++)
8414a40c 436 {
80ed523f
VZ
437 if( nDestX*nHorSubsampling >= nOBlockXSize )
438 break;
439
8414a40c 440 * ( pabyOTile + nDestY * nDestSampleRowSize
80ed523f
VZ
441 + nDestX * nSampleBlockSize
442 + nSampleOffsetInSampleBlock ) =
8414a40c 443 * ( pabySrcTile + nSourceY * nSourceSampleRowSize
80ed523f
VZ
444 + nSourceX * nSampleBlockSize
445 + nSampleOffsetInSampleBlock );
8414a40c
VZ
446 }
447 }
8414a40c
VZ
448 }
449 }
450 else if( strncmp(pszResampling,"averag",6) == 0
80ed523f 451 || strncmp(pszResampling,"AVERAG",6) == 0 )
8414a40c
VZ
452 {
453 if( nSample == 0 )
454 {
455 for( nSourceY = 0, nDestY = nTYOff; nSourceY < nBlockYSize; nSourceY += nOMult, nDestY ++)
456 {
80ed523f
VZ
457 if( nDestY >= nOBlockYSize )
458 break;
459
8414a40c
VZ
460 for( nSourceX = 0, nDestX = nTXOff; nSourceX < nBlockXSize; nSourceX += nOMult, nDestX ++)
461 {
80ed523f
VZ
462 if( nDestX >= nOBlockXSize )
463 break;
464
8414a40c
VZ
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
80ed523f
VZ
477 + ( nSourceYSec % nVerSubsampling ) * nHorSubsampling
478 + ( nSourceXSec / nHorSubsampling ) * nSampleBlockSize
479 + ( nSourceXSec % nHorSubsampling ) );
8414a40c
VZ
480 }
481 }
482 nCummulatorCount = ( nSourceXSecEnd - nSourceX ) * ( nSourceYSecEnd - nSourceY );
483 * ( pabyOTile + ( nDestY / nVerSubsampling ) * nDestSampleRowSize
80ed523f
VZ
484 + ( nDestY % nVerSubsampling ) * nHorSubsampling
485 + ( nDestX / nHorSubsampling ) * nSampleBlockSize
486 + ( nDestX % nHorSubsampling ) ) =
8414a40c
VZ
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 );
80ed523f 495 nSourceY += nOMult, nDestY ++)
8414a40c 496 {
80ed523f
VZ
497 if( nDestY*nVerSubsampling >= nOBlockYSize )
498 break;
499
8414a40c 500 for( nSourceX = 0, nDestX = ( nTXOff / nHorSubsampling ); nSourceX < ( nBlockXSize / nHorSubsampling );
80ed523f 501 nSourceX += nOMult, nDestX ++)
8414a40c 502 {
80ed523f
VZ
503 if( nDestX*nHorSubsampling >= nOBlockXSize )
504 break;
505
8414a40c
VZ
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
80ed523f
VZ
518 + nSourceXSec * nSampleBlockSize
519 + nSampleOffsetInSampleBlock );
8414a40c
VZ
520 }
521 }
522 nCummulatorCount = ( nSourceXSecEnd - nSourceX ) * ( nSourceYSecEnd - nSourceY );
523 * ( pabyOTile + nDestY * nDestSampleRowSize
80ed523f
VZ
524 + nDestX * nSampleBlockSize
525 + nSampleOffsetInSampleBlock ) =
8414a40c
VZ
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
540void TIFF_ProcessFullResBlock( TIFF *hTIFF, int nPlanarConfig,
80ed523f
VZ
541 int bSubsampled,
542 int nHorSubsampling, int nVerSubsampling,
8414a40c
VZ
543 int nOverviews, int * panOvList,
544 int nBitsPerPixel,
545 int nSamples, TIFFOvrCache ** papoRawBIs,
80ed523f 546 uint32 nSXOff, uint32 nSYOff,
8414a40c 547 unsigned char *pabySrcTile,
80ed523f 548 uint32 nBlockXSize, uint32 nBlockYSize,
8414a40c
VZ
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;
80ed523f
VZ
588 uint32 nTXOff, nTYOff, nOXOff, nOYOff, nOMult;
589 uint32 nOBlockXSize = poRBI->nBlockXSize;
590 uint32 nOBlockYSize = poRBI->nBlockYSize;
591 int nSkewBits, nSampleByteOffset;
8414a40c
VZ
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
685void 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
80ed523f
VZ
702 (void) pfnProgress;
703 (void) pProgressData;
704
8414a40c
VZ
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 {
80ed523f
VZ
809 uint32 nOXSize, nOYSize, nOBlockXSize, nOBlockYSize;
810 toff_t nDirOffset;
8414a40c
VZ
811
812 nOXSize = (nXSize + panOvList[i] - 1) / panOvList[i];
813 nOYSize = (nYSize + panOvList[i] - 1) / panOvList[i];
814
80ed523f
VZ
815 nOBlockXSize = MIN(nBlockXSize,nOXSize);
816 nOBlockYSize = MIN(nBlockYSize,nOYSize);
8414a40c
VZ
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
80ed523f
VZ
893/*
894 * Local Variables:
895 * mode: c
896 * c-basic-offset: 8
897 * fill-column: 78
898 * End:
899 */