CPLErr VRTWarpedDataset::IBuildOverviews( const char *pszResampling, int nOverviews, int *panOverviewList, int nListBands, int *panBandList, GDALProgressFunc pfnProgress, void * pProgressData ) { /* -------------------------------------------------------------------- */ /* Initial progress result. */ /* -------------------------------------------------------------------- */ if( !pfnProgress( 0.0, NULL, pProgressData ) ) { CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Establish which of the overview levels we already have, and */ /* which are new. */ /* -------------------------------------------------------------------- */ int i, nNewOverviews, *panNewOverviewList = NULL; nNewOverviews = 0; panNewOverviewList = (int *) CPLCalloc(sizeof(int),nOverviews); for( i = 0; i < nOverviews; i++ ) { int j; for( j = 0; j < nOverviewCount; j++ ) { int nOvFactor; VRTWarpedDataset *poOverview = papoOverviews[j]; nOvFactor = (int) (0.5+GetRasterXSize() / (double) poOverview->GetRasterXSize()); if( nOvFactor == panOverviewList[i] || nOvFactor == GDALOvLevelAdjust( panOverviewList[i], GetRasterXSize() ) ) panOverviewList[i] *= -1; } if( panOverviewList[i] > 0 ) panNewOverviewList[nNewOverviews++] = panOverviewList[i]; } /* -------------------------------------------------------------------- */ /* Create each missing overview (we don't need to do anything */ /* to update existing overviews). */ /* -------------------------------------------------------------------- */ for( i = 0; i < nNewOverviews; i++ ) { int nOXSize, nOYSize, iBand; VWOTInfo *psInfo; VRTWarpedDataset *poOverviewDS; /* -------------------------------------------------------------------- */ /* What size should this overview be. */ /* -------------------------------------------------------------------- */ nOXSize = (GetRasterXSize() + panNewOverviewList[i] - 1) / panNewOverviewList[i]; nOYSize = (GetRasterYSize() + panNewOverviewList[i] - 1) / panNewOverviewList[i]; /* -------------------------------------------------------------------- */ /* Create the overview dataset. */ /* -------------------------------------------------------------------- */ poOverviewDS = new VRTWarpedDataset( nOXSize, nOYSize ); for( iBand = 0; iBand < GetRasterCount(); iBand++ ) { GDALRasterBand *poOldBand = GetRasterBand(iBand+1); VRTWarpedRasterBand *poNewBand = new VRTWarpedRasterBand( poOverviewDS, iBand+1, poOldBand->GetRasterDataType() ); poNewBand->CopyCommonInfoFrom( poOldBand ); poOverviewDS->SetBand( iBand+1, poNewBand ); } nOverviewCount++; papoOverviews = (VRTWarpedDataset **) CPLRealloc( papoOverviews, sizeof(void*) * nOverviewCount ); papoOverviews[nOverviewCount-1] = poOverviewDS; /* -------------------------------------------------------------------- */ /* Prepare update transformation information that will apply */ /* the overview decimation. */ /* -------------------------------------------------------------------- */ GDALWarpOptions *psWO = (GDALWarpOptions *) poWarper->GetOptions(); psInfo = (VWOTInfo *) CPLCalloc(sizeof(VWOTInfo),1); strcpy( psInfo->sTI.szSignature, "GTI" ); psInfo->sTI.pszClassName = "VRTWarpedOverviewTransform"; psInfo->sTI.pfnTransform = VRTWarpedOverviewTransform; psInfo->sTI.pfnCleanup = VRTWarpedOverviewCleanup; psInfo->sTI.pfnSerialize = NULL; psInfo->pfnBaseTransformer = psWO->pfnTransformer; psInfo->pBaseTransformerArg = psWO->pTransformerArg; psInfo->dfXOverviewFactor = GetRasterXSize() / (double) nOXSize; psInfo->dfYOverviewFactor = GetRasterYSize() / (double) nOYSize; /* -------------------------------------------------------------------- */ /* Initialize the new dataset with adjusted warp options, and */ /* then restore to original condition. */ /* -------------------------------------------------------------------- */ psWO->pfnTransformer = VRTWarpedOverviewTransform; psWO->pTransformerArg = psInfo; poOverviewDS->Initialize( psWO ); psWO->pfnTransformer = psInfo->pfnBaseTransformer; psWO->pTransformerArg = psInfo->pBaseTransformerArg; } CPLFree( panNewOverviewList ); /* -------------------------------------------------------------------- */ /* Progress finished. */ /* -------------------------------------------------------------------- */ pfnProgress( 1.0, NULL, pProgressData ); SetNeedsFlush(); return CE_None; }
CPLErr GDALDefaultOverviews::BuildOverviews( const char * pszBasename, const char * pszResampling, int nOverviews, int * panOverviewList, int nBands, int * panBandList, GDALProgressFunc pfnProgress, void * pProgressData) { GDALRasterBand **pahBands; CPLErr eErr; int i; if( pfnProgress == NULL ) pfnProgress = GDALDummyProgress; if( nOverviews == 0 ) return CleanOverviews(); /* -------------------------------------------------------------------- */ /* If we don't already have an overview file, we need to decide */ /* what format to use. */ /* -------------------------------------------------------------------- */ if( poODS == NULL ) { bOvrIsAux = CSLTestBoolean(CPLGetConfigOption( "USE_RRD", "NO" )); if( bOvrIsAux ) { VSIStatBufL sStatBuf; osOvrFilename = CPLResetExtension(poDS->GetDescription(),"aux"); if( VSIStatExL( osOvrFilename, &sStatBuf, VSI_STAT_EXISTS_FLAG ) == 0 ) osOvrFilename.Printf( "%s.aux", poDS->GetDescription() ); } } /* -------------------------------------------------------------------- */ /* If we already have the overviews open, but they are */ /* read-only, then try and reopen them read-write. */ /* -------------------------------------------------------------------- */ else if( poODS->GetAccess() == GA_ReadOnly ) { GDALClose( poODS ); poODS = (GDALDataset *) GDALOpen( osOvrFilename, GA_Update ); if( poODS == NULL ) return CE_Failure; } /* -------------------------------------------------------------------- */ /* Our TIFF overview support currently only works safely if all */ /* bands are handled at the same time. */ /* -------------------------------------------------------------------- */ if( !bOvrIsAux && nBands != poDS->GetRasterCount() ) { CPLError( CE_Failure, CPLE_NotSupported, "Generation of overviews in external TIFF currently only" " supported when operating on all bands.\n" "Operation failed.\n" ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* If a basename is provided, use it to override the internal */ /* overview filename. */ /* -------------------------------------------------------------------- */ if( pszBasename == NULL && osOvrFilename.length() == 0 ) pszBasename = poDS->GetDescription(); if( pszBasename != NULL ) { if( bOvrIsAux ) osOvrFilename.Printf( "%s.aux", pszBasename ); else osOvrFilename.Printf( "%s.ovr", pszBasename ); } /* -------------------------------------------------------------------- */ /* Establish which of the overview levels we already have, and */ /* which are new. We assume that band 1 of the file is */ /* representative. */ /* -------------------------------------------------------------------- */ int nNewOverviews, *panNewOverviewList = NULL; GDALRasterBand *poBand = poDS->GetRasterBand( 1 ); nNewOverviews = 0; panNewOverviewList = (int *) CPLCalloc(sizeof(int),nOverviews); for( i = 0; i < nOverviews && poBand != NULL; i++ ) { int j; for( j = 0; j < poBand->GetOverviewCount(); j++ ) { int nOvFactor; GDALRasterBand * poOverview = poBand->GetOverview( j ); if (poOverview == NULL) continue; nOvFactor = (int) (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize()); if( nOvFactor == panOverviewList[i] || nOvFactor == GDALOvLevelAdjust( panOverviewList[i], poBand->GetXSize() ) ) panOverviewList[i] *= -1; } if( panOverviewList[i] > 0 ) panNewOverviewList[nNewOverviews++] = panOverviewList[i]; } /* -------------------------------------------------------------------- */ /* Build band list. */ /* -------------------------------------------------------------------- */ pahBands = (GDALRasterBand **) CPLCalloc(sizeof(GDALRasterBand *),nBands); for( i = 0; i < nBands; i++ ) pahBands[i] = poDS->GetRasterBand( panBandList[i] ); /* -------------------------------------------------------------------- */ /* Build new overviews - Imagine. Keep existing file open if */ /* we have it. But mark all overviews as in need of */ /* regeneration, since HFAAuxBuildOverviews() doesn't actually */ /* produce the imagery. */ /* -------------------------------------------------------------------- */ #ifndef WIN32CE if( bOvrIsAux ) { if( nNewOverviews == 0 ) { /* if we call HFAAuxBuildOverviews() with nNewOverviews == 0 */ /* because that there's no new, this will wipe existing */ /* overviews (#4831) */ eErr = CE_None; } else eErr = HFAAuxBuildOverviews( osOvrFilename, poDS, &poODS, nBands, panBandList, nNewOverviews, panNewOverviewList, pszResampling, pfnProgress, pProgressData ); int j; for( j = 0; j < nOverviews; j++ ) { if( panOverviewList[j] > 0 ) panOverviewList[j] *= -1; } } /* -------------------------------------------------------------------- */ /* Build new overviews - TIFF. Close TIFF files while we */ /* operate on it. */ /* -------------------------------------------------------------------- */ else #endif /* WIN32CE */ { if( poODS != NULL ) { delete poODS; poODS = NULL; } eErr = GTIFFBuildOverviews( osOvrFilename, nBands, pahBands, nNewOverviews, panNewOverviewList, pszResampling, pfnProgress, pProgressData ); // Probe for proxy overview filename. if( eErr == CE_Failure ) { const char *pszProxyOvrFilename = poDS->GetMetadataItem("FILENAME","ProxyOverviewRequest"); if( pszProxyOvrFilename != NULL ) { osOvrFilename = pszProxyOvrFilename; eErr = GTIFFBuildOverviews( osOvrFilename, nBands, pahBands, nNewOverviews, panNewOverviewList, pszResampling, pfnProgress, pProgressData ); } } if( eErr == CE_None ) { poODS = (GDALDataset *) GDALOpen( osOvrFilename, GA_Update ); if( poODS == NULL ) eErr = CE_Failure; } } /* -------------------------------------------------------------------- */ /* Refresh old overviews that were listed. */ /* -------------------------------------------------------------------- */ GDALRasterBand **papoOverviewBands; papoOverviewBands = (GDALRasterBand **) CPLCalloc(sizeof(void*),nOverviews); for( int iBand = 0; iBand < nBands && eErr == CE_None; iBand++ ) { poBand = poDS->GetRasterBand( panBandList[iBand] ); nNewOverviews = 0; for( i = 0; i < nOverviews && poBand != NULL; i++ ) { int j; for( j = 0; j < poBand->GetOverviewCount(); j++ ) { int nOvFactor; GDALRasterBand * poOverview = poBand->GetOverview( j ); if (poOverview == NULL) continue; int bHasNoData; double noDataValue = poBand->GetNoDataValue(&bHasNoData); if (bHasNoData) poOverview->SetNoDataValue(noDataValue); nOvFactor = (int) (0.5 + poBand->GetXSize() / (double) poOverview->GetXSize()); if( nOvFactor == - panOverviewList[i] || (panOverviewList[i] < 0 && nOvFactor == GDALOvLevelAdjust( -panOverviewList[i], poBand->GetXSize() )) ) { papoOverviewBands[nNewOverviews++] = poOverview; break; } } } if( nNewOverviews > 0 ) { eErr = GDALRegenerateOverviews( (GDALRasterBandH) poBand, nNewOverviews, (GDALRasterBandH*)papoOverviewBands, pszResampling, pfnProgress, pProgressData ); } } /* -------------------------------------------------------------------- */ /* Cleanup */ /* -------------------------------------------------------------------- */ CPLFree( papoOverviewBands ); CPLFree( panNewOverviewList ); CPLFree( pahBands ); /* -------------------------------------------------------------------- */ /* If we have a mask file, we need to build it's overviews */ /* too. */ /* -------------------------------------------------------------------- */ if( HaveMaskFile() && poMaskDS ) { /* Some config option are not compatible with mask overviews */ /* so unset them, and define more sensible values */ int bJPEG = EQUAL(CPLGetConfigOption("COMPRESS_OVERVIEW", ""), "JPEG"); int bPHOTOMETRIC_YCBCR = EQUAL(CPLGetConfigOption("PHOTOMETRIC_OVERVIEW", ""), "YCBCR"); if( bJPEG ) CPLSetThreadLocalConfigOption("COMPRESS_OVERVIEW", "DEFLATE"); if( bPHOTOMETRIC_YCBCR ) CPLSetThreadLocalConfigOption("PHOTOMETRIC_OVERVIEW", ""); poMaskDS->BuildOverviews( pszResampling, nOverviews, panOverviewList, 0, NULL, pfnProgress, pProgressData ); /* Restore config option */ if( bJPEG ) CPLSetThreadLocalConfigOption("COMPRESS_OVERVIEW", "JPEG"); if( bPHOTOMETRIC_YCBCR ) CPLSetThreadLocalConfigOption("PHOTOMETRIC_OVERVIEW", "YCBCR"); if( bOwnMaskDS ) { /* Reset the poMask member of main dataset bands, since it */ /* will become invalid after poMaskDS closing */ for( int iBand = 1; iBand <= poDS->GetRasterCount(); iBand ++ ) { GDALRasterBand *poBand = poDS->GetRasterBand(iBand); if( poBand != NULL ) poBand->InvalidateMaskBand(); } GDALClose( poMaskDS ); } // force next request to reread mask file. poMaskDS = NULL; bOwnMaskDS = FALSE; bCheckedForMask = FALSE; } /* -------------------------------------------------------------------- */ /* If we have an overview dataset, then mark all the overviews */ /* with the base dataset Used later for finding overviews */ /* masks. Uggg. */ /* -------------------------------------------------------------------- */ if( poODS ) { int nOverviewCount = GetOverviewCount(1); int iOver; for( iOver = 0; iOver < nOverviewCount; iOver++ ) { GDALRasterBand *poBand = GetOverview( 1, iOver ); GDALDataset *poOverDS = NULL; if( poBand != NULL ) poOverDS = poBand->GetDataset(); if (poOverDS != NULL) { poOverDS->oOvManager.poBaseDS = poDS; poOverDS->oOvManager.poDS = poOverDS; } } } return eErr; }