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 80uint32 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 161static void 162TIFF_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 215static void 216TIFF_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 257static 258void 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/************************************************************************/ 361/* TIFF_DownSample_Subsampled() */ 362/************************************************************************/ 363static 364void TIFF_DownSample_Subsampled( unsigned char *pabySrcTile, int nSample, 365 int nBlockXSize, int nBlockYSize, 366 unsigned char * pabyOTile, 367 int nOBlockXSize, int nOBlockYSize, 368 int nTXOff, int nTYOff, int nOMult, 369 const char * pszResampling, 370 int nHorSubsampling, int nVerSubsampling ) 371{ 372 /* TODO: test with variety of subsampling values, and incovinient tile/strip sizes */ 373 int nSampleBlockSize; 374 int nSourceSampleRowSize; 375 int nDestSampleRowSize; 376 int nSourceX, nSourceY; 377 int nSourceXSec, nSourceYSec; 378 int nSourceXSecEnd, nSourceYSecEnd; 379 int nDestX, nDestY; 380 int nSampleOffsetInSampleBlock; 381 unsigned char * pSourceBase; 382 unsigned char * pDestBase; 383 int nSourceBaseInc; 384 unsigned char * pSourceBaseEnd; 385 unsigned int nCummulator; 386 unsigned int nCummulatorCount; 387 388 nSampleBlockSize = nHorSubsampling * nVerSubsampling + 2; 389 nSourceSampleRowSize = 390 ( ( nBlockXSize + nHorSubsampling - 1 ) / nHorSubsampling ) * nSampleBlockSize; 391 nDestSampleRowSize = 392 ( ( nOBlockXSize + nHorSubsampling - 1 ) / nHorSubsampling ) * nSampleBlockSize; 393 394 if( strncmp(pszResampling,"nearest",4) == 0 395 || strncmp(pszResampling,"NEAR",4) == 0 ) 396 { 397 if( nSample == 0 ) 398 { 399 for( nSourceY = 0, nDestY = nTYOff; 400 nSourceY < nBlockYSize; 401 nSourceY += nOMult, nDestY ++) 402 { 403 if( nDestY >= nOBlockYSize ) 404 break; 405 406 for( nSourceX = 0, nDestX = nTXOff; 407 nSourceX < nBlockXSize; 408 nSourceX += nOMult, nDestX ++) 409 { 410 if( nDestX >= nOBlockXSize ) 411 break; 412 413 * ( pabyOTile + ( nDestY / nVerSubsampling ) * nDestSampleRowSize 414 + ( nDestY % nVerSubsampling ) * nHorSubsampling 415 + ( nDestX / nHorSubsampling ) * nSampleBlockSize 416 + ( nDestX % nHorSubsampling ) ) = 417 * ( pabySrcTile + ( nSourceY / nVerSubsampling ) * nSourceSampleRowSize 418 + ( nSourceY % nVerSubsampling ) * nHorSubsampling 419 + ( nSourceX / nHorSubsampling ) * nSampleBlockSize 420 + ( nSourceX % nHorSubsampling ) ); 421 } 422 } 423 } 424 else 425 { 426 nSampleOffsetInSampleBlock = nHorSubsampling * nVerSubsampling + nSample - 1; 427 for( nSourceY = 0, nDestY = ( nTYOff / nVerSubsampling ); 428 nSourceY < ( nBlockYSize / nVerSubsampling ); 429 nSourceY += nOMult, nDestY ++) 430 { 431 if( nDestY*nVerSubsampling >= nOBlockYSize ) 432 break; 433 434 for( nSourceX = 0, nDestX = ( nTXOff / nHorSubsampling ); 435 nSourceX < ( nBlockXSize / nHorSubsampling ); 436 nSourceX += nOMult, nDestX ++) 437 { 438 if( nDestX*nHorSubsampling >= nOBlockXSize ) 439 break; 440 441 * ( pabyOTile + nDestY * nDestSampleRowSize 442 + nDestX * nSampleBlockSize 443 + nSampleOffsetInSampleBlock ) = 444 * ( pabySrcTile + nSourceY * nSourceSampleRowSize 445 + nSourceX * nSampleBlockSize 446 + nSampleOffsetInSampleBlock ); 447 } 448 } 449 } 450 } 451 else if( strncmp(pszResampling,"averag",6) == 0 452 || strncmp(pszResampling,"AVERAG",6) == 0 ) 453 { 454 if( nSample == 0 ) 455 { 456 for( nSourceY = 0, nDestY = nTYOff; nSourceY < nBlockYSize; nSourceY += nOMult, nDestY ++) 457 { 458 if( nDestY >= nOBlockYSize ) 459 break; 460 461 for( nSourceX = 0, nDestX = nTXOff; nSourceX < nBlockXSize; nSourceX += nOMult, nDestX ++) 462 { 463 if( nDestX >= nOBlockXSize ) 464 break; 465 466 nSourceXSecEnd = nSourceX + nOMult; 467 if( nSourceXSecEnd > nBlockXSize ) 468 nSourceXSecEnd = nBlockXSize; 469 nSourceYSecEnd = nSourceY + nOMult; 470 if( nSourceYSecEnd > nBlockYSize ) 471 nSourceYSecEnd = nBlockYSize; 472 nCummulator = 0; 473 for( nSourceYSec = nSourceY; nSourceYSec < nSourceYSecEnd; nSourceYSec ++) 474 { 475 for( nSourceXSec = nSourceX; nSourceXSec < nSourceXSecEnd; nSourceXSec ++) 476 { 477 nCummulator += * ( pabySrcTile + ( nSourceYSec / nVerSubsampling ) * nSourceSampleRowSize 478 + ( nSourceYSec % nVerSubsampling ) * nHorSubsampling 479 + ( nSourceXSec / nHorSubsampling ) * nSampleBlockSize 480 + ( nSourceXSec % nHorSubsampling ) ); 481 } 482 } 483 nCummulatorCount = ( nSourceXSecEnd - nSourceX ) * ( nSourceYSecEnd - nSourceY ); 484 * ( pabyOTile + ( nDestY / nVerSubsampling ) * nDestSampleRowSize 485 + ( nDestY % nVerSubsampling ) * nHorSubsampling 486 + ( nDestX / nHorSubsampling ) * nSampleBlockSize 487 + ( nDestX % nHorSubsampling ) ) = 488 ( ( nCummulator + ( nCummulatorCount >> 1 ) ) / nCummulatorCount ); 489 } 490 } 491 } 492 else 493 { 494 nSampleOffsetInSampleBlock = nHorSubsampling * nVerSubsampling + nSample - 1; 495 for( nSourceY = 0, nDestY = ( nTYOff / nVerSubsampling ); nSourceY < ( nBlockYSize / nVerSubsampling ); 496 nSourceY += nOMult, nDestY ++) 497 { 498 if( nDestY*nVerSubsampling >= nOBlockYSize ) 499 break; 500 501 for( nSourceX = 0, nDestX = ( nTXOff / nHorSubsampling ); nSourceX < ( nBlockXSize / nHorSubsampling ); 502 nSourceX += nOMult, nDestX ++) 503 { 504 if( nDestX*nHorSubsampling >= nOBlockXSize ) 505 break; 506 507 nSourceXSecEnd = nSourceX + nOMult; 508 if( nSourceXSecEnd > ( nBlockXSize / nHorSubsampling ) ) 509 nSourceXSecEnd = ( nBlockXSize / nHorSubsampling ); 510 nSourceYSecEnd = nSourceY + nOMult; 511 if( nSourceYSecEnd > ( nBlockYSize / nVerSubsampling ) ) 512 nSourceYSecEnd = ( nBlockYSize / nVerSubsampling ); 513 nCummulator = 0; 514 for( nSourceYSec = nSourceY; nSourceYSec < nSourceYSecEnd; nSourceYSec ++) 515 { 516 for( nSourceXSec = nSourceX; nSourceXSec < nSourceXSecEnd; nSourceXSec ++) 517 { 518 nCummulator += * ( pabySrcTile + nSourceYSec * nSourceSampleRowSize 519 + nSourceXSec * nSampleBlockSize 520 + nSampleOffsetInSampleBlock ); 521 } 522 } 523 nCummulatorCount = ( nSourceXSecEnd - nSourceX ) * ( nSourceYSecEnd - nSourceY ); 524 * ( pabyOTile + nDestY * nDestSampleRowSize 525 + nDestX * nSampleBlockSize 526 + nSampleOffsetInSampleBlock ) = 527 ( ( nCummulator + ( nCummulatorCount >> 1 ) ) / nCummulatorCount ); 528 } 529 } 530 } 531 } 532} 533 534/************************************************************************/ 535/* TIFF_ProcessFullResBlock() */ 536/* */ 537/* Process one block of full res data, downsampling into each */ 538/* of the overviews. */ 539/************************************************************************/ 540 541void TIFF_ProcessFullResBlock( TIFF *hTIFF, int nPlanarConfig, 542 int bSubsampled, int nHorSubsampling, int nVerSubsampling, 543 int nOverviews, int * panOvList, 544 int nBitsPerPixel, 545 int nSamples, TIFFOvrCache ** papoRawBIs, 546 int nSXOff, int nSYOff, 547 unsigned char *pabySrcTile, 548 int nBlockXSize, int 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 int nTXOff, nTYOff, nOXOff, nOYOff, nOMult; 589 int nOBlockXSize = poRBI->nBlockXSize; 590 int 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 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 702/* -------------------------------------------------------------------- */ 703/* Get the base raster size. */ 704/* -------------------------------------------------------------------- */ 705 TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &nXSize ); 706 TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &nYSize ); 707 708 TIFFGetField( hTIFF, TIFFTAG_BITSPERSAMPLE, &nBitsPerPixel ); 709 /* TODO: nBitsPerPixel seems misnomer and may need renaming to nBitsPerSample */ 710 TIFFGetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, &nSamples ); 711 TIFFGetFieldDefaulted( hTIFF, TIFFTAG_PLANARCONFIG, &nPlanarConfig ); 712 713 TIFFGetFieldDefaulted( hTIFF, TIFFTAG_PHOTOMETRIC, &nPhotometric ); 714 TIFFGetFieldDefaulted( hTIFF, TIFFTAG_COMPRESSION, &nCompressFlag ); 715 TIFFGetFieldDefaulted( hTIFF, TIFFTAG_SAMPLEFORMAT, &nSampleFormat ); 716 717 if( nPhotometric == PHOTOMETRIC_YCBCR || nPhotometric == PHOTOMETRIC_ITULAB ) 718 { 719 if( nBitsPerPixel != 8 || nSamples != 3 || nPlanarConfig != PLANARCONFIG_CONTIG || 720 nSampleFormat != SAMPLEFORMAT_UINT) 721 { 722 /* TODO: use of TIFFError is inconsistent with use of fprintf in addtiffo.c, sort out */ 723 TIFFErrorExt( TIFFClientdata(hTIFF), "TIFFBuildOverviews", 724 "File `%s' has an unsupported subsampling configuration.\n", 725 TIFFFileName(hTIFF) ); 726 /* If you need support for this particular flavor, please contact either 727 * Frank Warmerdam warmerdam@pobox.com 728 * Joris Van Damme info@awaresystems.be 729 */ 730 return; 731 } 732 bSubsampled = 1; 733 TIFFGetField( hTIFF, TIFFTAG_YCBCRSUBSAMPLING, &nHorSubsampling, &nVerSubsampling ); 734 /* TODO: find out if maybe TIFFGetFieldDefaulted is better choice for YCbCrSubsampling tag */ 735 } 736 else 737 { 738 if( nBitsPerPixel < 8 ) 739 { 740 /* TODO: use of TIFFError is inconsistent with use of fprintf in addtiffo.c, sort out */ 741 TIFFErrorExt( TIFFClientdata(hTIFF), "TIFFBuildOverviews", 742 "File `%s' has samples of %d bits per sample. Sample\n" 743 "sizes of less than 8 bits per sample are not supported.\n", 744 TIFFFileName(hTIFF), nBitsPerPixel ); 745 return; 746 } 747 bSubsampled = 0; 748 nHorSubsampling = 1; 749 nVerSubsampling = 1; 750 } 751 752/* -------------------------------------------------------------------- */ 753/* Turn off warnings to avoid alot of repeated warnings while */ 754/* rereading directories. */ 755/* -------------------------------------------------------------------- */ 756 pfnWarning = TIFFSetWarningHandler( NULL ); 757 758/* -------------------------------------------------------------------- */ 759/* Get the base raster block size. */ 760/* -------------------------------------------------------------------- */ 761 if( TIFFGetField( hTIFF, TIFFTAG_ROWSPERSTRIP, &(nBlockYSize) ) ) 762 { 763 nBlockXSize = nXSize; 764 bTiled = FALSE; 765 } 766 else 767 { 768 TIFFGetField( hTIFF, TIFFTAG_TILEWIDTH, &nBlockXSize ); 769 TIFFGetField( hTIFF, TIFFTAG_TILELENGTH, &nBlockYSize ); 770 bTiled = TRUE; 771 } 772 773/* -------------------------------------------------------------------- */ 774/* Capture the pallette if there is one. */ 775/* -------------------------------------------------------------------- */ 776 if( TIFFGetField( hTIFF, TIFFTAG_COLORMAP, 777 &panRedMap, &panGreenMap, &panBlueMap ) ) 778 { 779 uint16 *panRed2, *panGreen2, *panBlue2; 780 int nColorCount = 1 << nBitsPerPixel; 781 782 panRed2 = (uint16 *) _TIFFmalloc(2*nColorCount); 783 panGreen2 = (uint16 *) _TIFFmalloc(2*nColorCount); 784 panBlue2 = (uint16 *) _TIFFmalloc(2*nColorCount); 785 786 memcpy( panRed2, panRedMap, 2 * nColorCount ); 787 memcpy( panGreen2, panGreenMap, 2 * nColorCount ); 788 memcpy( panBlue2, panBlueMap, 2 * nColorCount ); 789 790 panRedMap = panRed2; 791 panGreenMap = panGreen2; 792 panBlueMap = panBlue2; 793 } 794 else 795 { 796 panRedMap = panGreenMap = panBlueMap = NULL; 797 } 798 799/* -------------------------------------------------------------------- */ 800/* Initialize overviews. */ 801/* -------------------------------------------------------------------- */ 802 papoRawBIs = (TIFFOvrCache **) _TIFFmalloc(nOverviews*sizeof(void*)); 803 804 for( i = 0; i < nOverviews; i++ ) 805 { 806 int nOXSize, nOYSize, nOBlockXSize, nOBlockYSize; 807 uint32 nDirOffset; 808 809 nOXSize = (nXSize + panOvList[i] - 1) / panOvList[i]; 810 nOYSize = (nYSize + panOvList[i] - 1) / panOvList[i]; 811 812 nOBlockXSize = MIN((int)nBlockXSize,nOXSize); 813 nOBlockYSize = MIN((int)nBlockYSize,nOYSize); 814 815 if( bTiled ) 816 { 817 if( (nOBlockXSize % 16) != 0 ) 818 nOBlockXSize = nOBlockXSize + 16 - (nOBlockXSize % 16); 819 820 if( (nOBlockYSize % 16) != 0 ) 821 nOBlockYSize = nOBlockYSize + 16 - (nOBlockYSize % 16); 822 } 823 824 nDirOffset = TIFF_WriteOverview( hTIFF, nOXSize, nOYSize, 825 nBitsPerPixel, nPlanarConfig, 826 nSamples, nOBlockXSize, nOBlockYSize, 827 bTiled, nCompressFlag, nPhotometric, 828 nSampleFormat, 829 panRedMap, panGreenMap, panBlueMap, 830 bUseSubIFDs, 831 nHorSubsampling, nVerSubsampling ); 832 833 papoRawBIs[i] = TIFFCreateOvrCache( hTIFF, nDirOffset ); 834 } 835 836 if( panRedMap != NULL ) 837 { 838 _TIFFfree( panRedMap ); 839 _TIFFfree( panGreenMap ); 840 _TIFFfree( panBlueMap ); 841 } 842 843/* -------------------------------------------------------------------- */ 844/* Allocate a buffer to hold a source block. */ 845/* -------------------------------------------------------------------- */ 846 if( bTiled ) 847 pabySrcTile = (unsigned char *) _TIFFmalloc(TIFFTileSize(hTIFF)); 848 else 849 pabySrcTile = (unsigned char *) _TIFFmalloc(TIFFStripSize(hTIFF)); 850 851/* -------------------------------------------------------------------- */ 852/* Loop over the source raster, applying data to the */ 853/* destination raster. */ 854/* -------------------------------------------------------------------- */ 855 for( nSYOff = 0; nSYOff < (int) nYSize; nSYOff += nBlockYSize ) 856 { 857 for( nSXOff = 0; nSXOff < (int) nXSize; nSXOff += nBlockXSize ) 858 { 859 /* 860 * Read and resample into the various overview images. 861 */ 862 863 TIFF_ProcessFullResBlock( hTIFF, nPlanarConfig, 864 bSubsampled,nHorSubsampling,nVerSubsampling, 865 nOverviews, panOvList, 866 nBitsPerPixel, nSamples, papoRawBIs, 867 nSXOff, nSYOff, pabySrcTile, 868 nBlockXSize, nBlockYSize, 869 nSampleFormat, pszResampleMethod ); 870 } 871 } 872 873 _TIFFfree( pabySrcTile ); 874 875/* -------------------------------------------------------------------- */ 876/* Cleanup the rawblockedimage files. */ 877/* -------------------------------------------------------------------- */ 878 for( i = 0; i < nOverviews; i++ ) 879 { 880 TIFFDestroyOvrCache( papoRawBIs[i] ); 881 } 882 883 if( papoRawBIs != NULL ) 884 _TIFFfree( papoRawBIs ); 885 886 TIFFSetWarningHandler( pfnWarning ); 887} 888 889 890/* 891 * Local Variables: 892 * mode: c 893 * c-basic-offset: 8 894 * fill-column: 78 895 * End: 896 */ 897