| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| TIFFOvrCache *TIFFCreateOvrCache( TIFF *hTIFF, toff_t nDirOffset ) |
| |
| { |
| TIFFOvrCache *psCache; |
| toff_t nBaseDirOffset; |
| |
| psCache = (TIFFOvrCache *) _TIFFmalloc(sizeof(TIFFOvrCache)); |
| psCache->nDirOffset = nDirOffset; |
| psCache->hTIFF = hTIFF; |
| |
| |
| |
| |
| nBaseDirOffset = TIFFCurrentDirOffset( psCache->hTIFF ); |
| TIFFSetSubDirectory( hTIFF, nDirOffset ); |
| |
| TIFFGetField( hTIFF, TIFFTAG_IMAGEWIDTH, &(psCache->nXSize) ); |
| TIFFGetField( hTIFF, TIFFTAG_IMAGELENGTH, &(psCache->nYSize) ); |
| |
| TIFFGetField( hTIFF, TIFFTAG_BITSPERSAMPLE, &(psCache->nBitsPerPixel) ); |
| TIFFGetField( hTIFF, TIFFTAG_SAMPLESPERPIXEL, &(psCache->nSamples) ); |
| TIFFGetField( hTIFF, TIFFTAG_PLANARCONFIG, &(psCache->nPlanarConfig) ); |
| |
| if( !TIFFIsTiled( hTIFF ) ) |
| { |
| TIFFGetField( hTIFF, TIFFTAG_ROWSPERSTRIP, &(psCache->nBlockYSize) ); |
| psCache->nBlockXSize = psCache->nXSize; |
| psCache->nBytesPerBlock = TIFFStripSize(hTIFF); |
| psCache->bTiled = FALSE; |
| } |
| else |
| { |
| TIFFGetField( hTIFF, TIFFTAG_TILEWIDTH, &(psCache->nBlockXSize) ); |
| TIFFGetField( hTIFF, TIFFTAG_TILELENGTH, &(psCache->nBlockYSize) ); |
| psCache->nBytesPerBlock = TIFFTileSize(hTIFF); |
| psCache->bTiled = TRUE; |
| } |
| |
| |
| |
| |
| |
| psCache->nBlocksPerRow = (psCache->nXSize + psCache->nBlockXSize - 1) |
| / psCache->nBlockXSize; |
| psCache->nBlocksPerColumn = (psCache->nYSize + psCache->nBlockYSize - 1) |
| / psCache->nBlockYSize; |
| |
| if (psCache->nPlanarConfig == PLANARCONFIG_SEPARATE) |
| psCache->nBytesPerRow = psCache->nBytesPerBlock |
| * psCache->nBlocksPerRow * psCache->nSamples; |
| else |
| psCache->nBytesPerRow = |
| psCache->nBytesPerBlock * psCache->nBlocksPerRow; |
| |
| |
| |
| |
| |
| |
| psCache->pabyRow1Blocks = |
| (unsigned char *) _TIFFmalloc(psCache->nBytesPerRow); |
| psCache->pabyRow2Blocks = |
| (unsigned char *) _TIFFmalloc(psCache->nBytesPerRow); |
| |
| if( psCache->pabyRow1Blocks == NULL |
| || psCache->pabyRow2Blocks == NULL ) |
| { |
| TIFFErrorExt( hTIFF->tif_clientdata, hTIFF->tif_name, |
| "Can't allocate memory for overview cache." ); |
| |
| return NULL; |
| } |
| |
| _TIFFmemset( psCache->pabyRow1Blocks, 0, psCache->nBytesPerRow ); |
| _TIFFmemset( psCache->pabyRow2Blocks, 0, psCache->nBytesPerRow ); |
| |
| psCache->nBlockOffset = 0; |
| |
| TIFFSetSubDirectory( psCache->hTIFF, nBaseDirOffset ); |
| |
| return psCache; |
| } |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| static void TIFFWriteOvrRow( TIFFOvrCache * psCache ) |
| |
| { |
| int nRet, iTileX, iTileY = psCache->nBlockOffset; |
| unsigned char *pabyData; |
| toff_t nBaseDirOffset; |
| uint32 RowsInStrip; |
| |
| |
| |
| |
| |
| |
| if( TIFFIsByteSwapped(psCache->hTIFF) ) |
| { |
| if( psCache->nBitsPerPixel == 16 ) |
| TIFFSwabArrayOfShort( (uint16 *) psCache->pabyRow1Blocks, |
| (psCache->nBytesPerBlock * psCache->nSamples) / 2 ); |
| |
| else if( psCache->nBitsPerPixel == 32 ) |
| TIFFSwabArrayOfLong( (uint32 *) psCache->pabyRow1Blocks, |
| (psCache->nBytesPerBlock * psCache->nSamples) / 4 ); |
| |
| else if( psCache->nBitsPerPixel == 64 ) |
| TIFFSwabArrayOfDouble( (double *) psCache->pabyRow1Blocks, |
| (psCache->nBytesPerBlock * psCache->nSamples) / 8 ); |
| } |
| |
| |
| |
| |
| |
| nBaseDirOffset = TIFFCurrentDirOffset( psCache->hTIFF ); |
| nRet = TIFFSetSubDirectory( psCache->hTIFF, psCache->nDirOffset ); |
| assert( nRet == 1 ); |
| |
| |
| |
| |
| for( iTileX = 0; iTileX < psCache->nBlocksPerRow; iTileX++ ) |
| { |
| int nTileID; |
| |
| if (psCache->nPlanarConfig == PLANARCONFIG_SEPARATE) |
| { |
| int iSample; |
| |
| for( iSample = 0; iSample < psCache->nSamples; iSample++ ) |
| { |
| pabyData = TIFFGetOvrBlock( psCache, iTileX, iTileY, iSample ); |
| |
| if( psCache->bTiled ) |
| { |
| nTileID = TIFFComputeTile( psCache->hTIFF, |
| iTileX * psCache->nBlockXSize, |
| iTileY * psCache->nBlockYSize, |
| 0, (tsample_t) iSample ); |
| TIFFWriteEncodedTile( psCache->hTIFF, nTileID, |
| pabyData, |
| TIFFTileSize(psCache->hTIFF) ); |
| } |
| else |
| { |
| nTileID = TIFFComputeStrip( psCache->hTIFF, |
| iTileY * psCache->nBlockYSize, |
| (tsample_t) iSample ); |
| RowsInStrip=psCache->nBlockYSize; |
| if ((iTileY+1)*psCache->nBlockYSize>psCache->nYSize) |
| RowsInStrip=psCache->nYSize-iTileY*psCache->nBlockYSize; |
| TIFFWriteEncodedStrip( psCache->hTIFF, nTileID, |
| pabyData, |
| TIFFVStripSize(psCache->hTIFF,RowsInStrip) ); |
| } |
| } |
| |
| } |
| else |
| { |
| pabyData = TIFFGetOvrBlock( psCache, iTileX, iTileY, 0 ); |
| |
| if( psCache->bTiled ) |
| { |
| nTileID = TIFFComputeTile( psCache->hTIFF, |
| iTileX * psCache->nBlockXSize, |
| iTileY * psCache->nBlockYSize, |
| 0, 0 ); |
| TIFFWriteEncodedTile( psCache->hTIFF, nTileID, |
| pabyData, |
| TIFFTileSize(psCache->hTIFF) ); |
| } |
| else |
| { |
| nTileID = TIFFComputeStrip( psCache->hTIFF, |
| iTileY * psCache->nBlockYSize, |
| 0 ); |
| RowsInStrip=psCache->nBlockYSize; |
| if ((iTileY+1)*psCache->nBlockYSize>psCache->nYSize) |
| RowsInStrip=psCache->nYSize-iTileY*psCache->nBlockYSize; |
| TIFFWriteEncodedStrip( psCache->hTIFF, nTileID, |
| pabyData, |
| TIFFVStripSize(psCache->hTIFF,RowsInStrip) ); |
| } |
| } |
| } |
| |
| |
| |
| |
| |
| pabyData = psCache->pabyRow1Blocks; |
| psCache->pabyRow1Blocks = psCache->pabyRow2Blocks; |
| psCache->pabyRow2Blocks = pabyData; |
| |
| _TIFFmemset( pabyData, 0, psCache->nBytesPerRow ); |
| |
| psCache->nBlockOffset++; |
| |
| |
| |
| |
| TIFFFlush( psCache->hTIFF ); |
| |
| TIFFSetSubDirectory( psCache->hTIFF, nBaseDirOffset ); |
| |
| } |
| |
| |
| |
| |
| |
| |
| |
| unsigned char *TIFFGetOvrBlock( TIFFOvrCache *psCache, int iTileX, int iTileY, |
| int iSample ) |
| |
| { |
| int nRowOffset; |
| |
| if( iTileY > psCache->nBlockOffset + 1 ) |
| TIFFWriteOvrRow( psCache ); |
| |
| assert( iTileX >= 0 && iTileX < psCache->nBlocksPerRow ); |
| assert( iTileY >= 0 && iTileY < psCache->nBlocksPerColumn ); |
| assert( iTileY >= psCache->nBlockOffset |
| && iTileY < psCache->nBlockOffset+2 ); |
| assert( iSample >= 0 && iSample < psCache->nSamples ); |
| |
| if (psCache->nPlanarConfig == PLANARCONFIG_SEPARATE) |
| nRowOffset = ((iTileX * psCache->nSamples) + iSample) |
| * psCache->nBytesPerBlock; |
| else |
| nRowOffset = iTileX * psCache->nBytesPerBlock + |
| (psCache->nBitsPerPixel + 7) / 8 * iSample; |
| |
| if( iTileY == psCache->nBlockOffset ) |
| return psCache->pabyRow1Blocks + nRowOffset; |
| else |
| return psCache->pabyRow2Blocks + nRowOffset; |
| } |
| |
| |
| |
| |
| |
| unsigned char *TIFFGetOvrBlock_Subsampled( TIFFOvrCache *psCache, |
| int iTileX, int iTileY ) |
| |
| { |
| int nRowOffset; |
| |
| if( iTileY > psCache->nBlockOffset + 1 ) |
| TIFFWriteOvrRow( psCache ); |
| |
| assert( iTileX >= 0 && iTileX < psCache->nBlocksPerRow ); |
| assert( iTileY >= 0 && iTileY < psCache->nBlocksPerColumn ); |
| assert( iTileY >= psCache->nBlockOffset |
| && iTileY < psCache->nBlockOffset+2 ); |
| assert( psCache->nPlanarConfig != PLANARCONFIG_SEPARATE ); |
| |
| nRowOffset = iTileX * psCache->nBytesPerBlock; |
| |
| if( iTileY == psCache->nBlockOffset ) |
| return psCache->pabyRow1Blocks + nRowOffset; |
| else |
| return psCache->pabyRow2Blocks + nRowOffset; |
| } |
| |
| |
| |
| |
| |
| void TIFFDestroyOvrCache( TIFFOvrCache * psCache ) |
| |
| { |
| while( psCache->nBlockOffset < psCache->nBlocksPerColumn ) |
| TIFFWriteOvrRow( psCache ); |
| |
| _TIFFfree( psCache->pabyRow1Blocks ); |
| _TIFFfree( psCache->pabyRow2Blocks ); |
| _TIFFfree( psCache ); |
| } |
| |
| |
| |
| |
| |
| |
| |