mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-08-25 06:12:47 -06:00
807 lines
32 KiB
C++
807 lines
32 KiB
C++
/******************************************************************************
|
|
* $Id: rasterliteoverviews.cpp 28053 2014-12-04 09:31:07Z rouault $
|
|
*
|
|
* Project: GDAL Rasterlite driver
|
|
* Purpose: Implement GDAL Rasterlite support using OGR SQLite driver
|
|
* Author: Even Rouault, <even dot rouault at mines dash paris dot org>
|
|
*
|
|
**********************************************************************
|
|
* Copyright (c) 2009-2012, Even Rouault <even dot rouault at mines-paris dot org>
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a
|
|
* copy of this software and associated documentation files (the "Software"),
|
|
* to deal in the Software without restriction, including without limitation
|
|
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
* and/or sell copies of the Software, and to permit persons to whom the
|
|
* Software is furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included
|
|
* in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
|
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
****************************************************************************/
|
|
|
|
#include "cpl_string.h"
|
|
#include "ogr_api.h"
|
|
#include "ogr_srs_api.h"
|
|
|
|
#include "rasterlitedataset.h"
|
|
|
|
CPL_CVSID("$Id: rasterliteoverviews.cpp 28053 2014-12-04 09:31:07Z rouault $");
|
|
|
|
/************************************************************************/
|
|
/* ReloadOverviews() */
|
|
/************************************************************************/
|
|
|
|
CPLErr RasterliteDataset::ReloadOverviews()
|
|
{
|
|
if (nLevel != 0)
|
|
return CE_Failure;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Fetch resolutions */
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
CPLString osSQL;
|
|
OGRLayerH hRasterPyramidsLyr = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
|
|
if (hRasterPyramidsLyr)
|
|
{
|
|
osSQL.Printf("SELECT pixel_x_size, pixel_y_size "
|
|
"FROM raster_pyramids WHERE table_prefix = '%s' "
|
|
"ORDER BY pixel_x_size ASC",
|
|
osTableName.c_str());
|
|
}
|
|
else
|
|
{
|
|
osSQL.Printf("SELECT DISTINCT(pixel_x_size), pixel_y_size "
|
|
"FROM \"%s_metadata\" WHERE pixel_x_size != 0 "
|
|
"ORDER BY pixel_x_size ASC",
|
|
osTableName.c_str());
|
|
}
|
|
|
|
OGRLayerH hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
|
|
if (hSQLLyr == NULL)
|
|
{
|
|
if (hRasterPyramidsLyr == NULL)
|
|
return CE_Failure;
|
|
|
|
osSQL.Printf("SELECT DISTINCT(pixel_x_size), pixel_y_size "
|
|
"FROM \"%s_metadata\" WHERE pixel_x_size != 0 "
|
|
"ORDER BY pixel_x_size ASC",
|
|
osTableName.c_str());
|
|
|
|
hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
|
|
if (hSQLLyr == NULL)
|
|
return CE_Failure;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Cleanup */
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
int i;
|
|
for(i=1;i<nResolutions;i++)
|
|
delete papoOverviews[i-1];
|
|
CPLFree(papoOverviews);
|
|
papoOverviews = NULL;
|
|
CPLFree(padfXResolutions);
|
|
padfXResolutions = NULL;
|
|
CPLFree(padfYResolutions);
|
|
padfYResolutions = NULL;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Rebuild arrays */
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
nResolutions = OGR_L_GetFeatureCount(hSQLLyr, TRUE);
|
|
|
|
padfXResolutions =
|
|
(double*)CPLMalloc(sizeof(double) * nResolutions);
|
|
padfYResolutions =
|
|
(double*)CPLMalloc(sizeof(double) * nResolutions);
|
|
|
|
i = 0;
|
|
OGRFeatureH hFeat;
|
|
while((hFeat = OGR_L_GetNextFeature(hSQLLyr)) != NULL)
|
|
{
|
|
padfXResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 0);
|
|
padfYResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 1);
|
|
|
|
OGR_F_Destroy(hFeat);
|
|
|
|
i ++;
|
|
}
|
|
|
|
OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
|
|
hSQLLyr = NULL;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Add overview levels as internal datasets */
|
|
/* -------------------------------------------------------------------- */
|
|
if (nResolutions > 1)
|
|
{
|
|
CPLString osRasterTableName = osTableName;
|
|
osRasterTableName += "_rasters";
|
|
|
|
OGRLayerH hRasterLyr = OGR_DS_GetLayerByName(hDS, osRasterTableName.c_str());
|
|
|
|
papoOverviews = (RasterliteDataset**)
|
|
CPLCalloc(nResolutions - 1, sizeof(RasterliteDataset*));
|
|
int nLev;
|
|
for(nLev=1;nLev<nResolutions;nLev++)
|
|
{
|
|
int nOvrBands;
|
|
GDALDataType eOvrDataType;
|
|
int nBlockXSize, nBlockYSize;
|
|
if (GetBlockParams(hRasterLyr, nLev, &nOvrBands, &eOvrDataType,
|
|
&nBlockXSize, &nBlockYSize))
|
|
{
|
|
if (eOvrDataType == GDT_Byte && nOvrBands == 1 && nBands == 3)
|
|
nOvrBands = 3;
|
|
|
|
papoOverviews[nLev-1] = new RasterliteDataset(this, nLev);
|
|
|
|
int iBand;
|
|
for(iBand=0;iBand<nBands;iBand++)
|
|
{
|
|
papoOverviews[nLev-1]->SetBand(iBand+1,
|
|
new RasterliteBand(papoOverviews[nLev-1], iBand+1, eOvrDataType,
|
|
nBlockXSize, nBlockYSize));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
"Cannot find block characteristics for overview %d", nLev);
|
|
papoOverviews[nLev-1] = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
return CE_None;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* CleanOverviews() */
|
|
/************************************************************************/
|
|
|
|
CPLErr RasterliteDataset::CleanOverviews()
|
|
{
|
|
CPLString osSQL;
|
|
|
|
if (nLevel != 0)
|
|
return CE_Failure;
|
|
|
|
osSQL.Printf("BEGIN");
|
|
OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
|
|
|
|
CPLString osResolutionCond =
|
|
"NOT " + RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]);
|
|
|
|
osSQL.Printf("DELETE FROM \"%s_rasters\" WHERE id "
|
|
"IN(SELECT id FROM \"%s_metadata\" WHERE %s)",
|
|
osTableName.c_str(), osTableName.c_str(),
|
|
osResolutionCond.c_str());
|
|
OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
|
|
|
|
osSQL.Printf("DELETE FROM \"%s_metadata\" WHERE %s",
|
|
osTableName.c_str(), osResolutionCond.c_str());
|
|
OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
|
|
|
|
OGRLayerH hRasterPyramidsLyr = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
|
|
if (hRasterPyramidsLyr)
|
|
{
|
|
osSQL.Printf("DELETE FROM raster_pyramids WHERE table_prefix = '%s' AND %s",
|
|
osTableName.c_str(), osResolutionCond.c_str());
|
|
OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
|
|
}
|
|
|
|
osSQL.Printf("COMMIT");
|
|
OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
|
|
|
|
int i;
|
|
for(i=1;i<nResolutions;i++)
|
|
delete papoOverviews[i-1];
|
|
CPLFree(papoOverviews);
|
|
papoOverviews = NULL;
|
|
nResolutions = 1;
|
|
|
|
return CE_None;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* CleanOverviewLevel() */
|
|
/************************************************************************/
|
|
|
|
CPLErr RasterliteDataset::CleanOverviewLevel(int nOvrFactor)
|
|
{
|
|
CPLString osSQL;
|
|
|
|
if (nLevel != 0)
|
|
return CE_Failure;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Find the index of the overview matching the overview factor */
|
|
/* -------------------------------------------------------------------- */
|
|
int iLev;
|
|
for(iLev=1;iLev<nResolutions;iLev++)
|
|
{
|
|
if (fabs(padfXResolutions[0] * nOvrFactor - padfXResolutions[iLev]) < 1e-15 &&
|
|
fabs(padfYResolutions[0] * nOvrFactor - padfYResolutions[iLev]) < 1e-15)
|
|
break;
|
|
}
|
|
|
|
if (iLev == nResolutions)
|
|
return CE_None;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Now clean existing overviews at that resolution */
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
osSQL.Printf("BEGIN");
|
|
OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
|
|
|
|
CPLString osResolutionCond =
|
|
RasterliteGetPixelSizeCond(padfXResolutions[iLev], padfYResolutions[iLev]);
|
|
|
|
osSQL.Printf("DELETE FROM \"%s_rasters\" WHERE id "
|
|
"IN(SELECT id FROM \"%s_metadata\" WHERE %s)",
|
|
osTableName.c_str(), osTableName.c_str(),
|
|
osResolutionCond.c_str());
|
|
OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
|
|
|
|
osSQL.Printf("DELETE FROM \"%s_metadata\" WHERE %s",
|
|
osTableName.c_str(), osResolutionCond.c_str());
|
|
OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
|
|
|
|
OGRLayerH hRasterPyramidsLyr = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
|
|
if (hRasterPyramidsLyr)
|
|
{
|
|
osSQL.Printf("DELETE FROM raster_pyramids WHERE table_prefix = '%s' AND %s",
|
|
osTableName.c_str(), osResolutionCond.c_str());
|
|
OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
|
|
}
|
|
|
|
osSQL.Printf("COMMIT");
|
|
OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
|
|
|
|
return CE_None;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* CleanOverviewLevel() */
|
|
/************************************************************************/
|
|
|
|
CPLErr RasterliteDataset::CreateOverviewLevel(const char * pszResampling,
|
|
int nOvrFactor,
|
|
char** papszOptions,
|
|
GDALProgressFunc pfnProgress,
|
|
void * pProgressData)
|
|
{
|
|
|
|
double dfXResolution = padfXResolutions[0] * nOvrFactor;
|
|
double dfYResolution = padfXResolutions[0] * nOvrFactor;
|
|
|
|
CPLString osSQL;
|
|
|
|
int nOvrXSize = nRasterXSize / nOvrFactor;
|
|
int nOvrYSize = nRasterYSize / nOvrFactor;
|
|
|
|
if (nOvrXSize == 0 || nOvrYSize == 0)
|
|
return CE_Failure;
|
|
|
|
int bTiled = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "TILED", "YES"));
|
|
int nBlockXSize, nBlockYSize;
|
|
if (bTiled)
|
|
{
|
|
nBlockXSize = atoi(CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", "256"));
|
|
nBlockYSize = atoi(CSLFetchNameValueDef(papszOptions, "BLOCKYSIZE", "256"));
|
|
if (nBlockXSize < 64) nBlockXSize = 64;
|
|
else if (nBlockXSize > 4096) nBlockXSize = 4096;
|
|
if (nBlockYSize < 64) nBlockYSize = 64;
|
|
else if (nBlockYSize > 4096) nBlockYSize = 4096;
|
|
}
|
|
else
|
|
{
|
|
nBlockXSize = nOvrXSize;
|
|
nBlockYSize = nOvrYSize;
|
|
}
|
|
|
|
int nXBlocks = (nOvrXSize + nBlockXSize - 1) / nBlockXSize;
|
|
int nYBlocks = (nOvrYSize + nBlockYSize - 1) / nBlockYSize;
|
|
|
|
const char* pszDriverName = CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff");
|
|
if (EQUAL(pszDriverName, "MEM") || EQUAL(pszDriverName, "VRT"))
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined, "GDAL %s driver cannot be used as underlying driver",
|
|
pszDriverName);
|
|
return CE_Failure;
|
|
}
|
|
GDALDriverH hTileDriver = GDALGetDriverByName(pszDriverName);
|
|
if (hTileDriver == NULL)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL %s driver", pszDriverName);
|
|
return CE_Failure;
|
|
}
|
|
|
|
GDALDriverH hMemDriver = GDALGetDriverByName("MEM");
|
|
if (hMemDriver == NULL)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL MEM driver");
|
|
return CE_Failure;
|
|
}
|
|
|
|
GDALDataType eDataType = GetRasterBand(1)->GetRasterDataType();
|
|
int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8;
|
|
GByte* pabyMEMDSBuffer =
|
|
(GByte*)VSIMalloc3(nBlockXSize, nBlockYSize, nBands * nDataTypeSize);
|
|
if (pabyMEMDSBuffer == NULL)
|
|
{
|
|
return CE_Failure;
|
|
}
|
|
|
|
CPLString osTempFileName;
|
|
osTempFileName.Printf("/vsimem/%p", hDS);
|
|
|
|
int nTileId = 0;
|
|
int nBlocks = 0;
|
|
int nTotalBlocks = nXBlocks * nYBlocks;
|
|
|
|
CPLString osRasterLayer;
|
|
osRasterLayer.Printf("%s_rasters", osTableName.c_str());
|
|
|
|
CPLString osMetatadataLayer;
|
|
osMetatadataLayer.Printf("%s_metadata", osTableName.c_str());
|
|
|
|
OGRLayerH hRasterLayer = OGR_DS_GetLayerByName(hDS, osRasterLayer.c_str());
|
|
OGRLayerH hMetadataLayer = OGR_DS_GetLayerByName(hDS, osMetatadataLayer.c_str());
|
|
|
|
CPLString osSourceName = "unknown";
|
|
|
|
osSQL.Printf("SELECT source_name FROM \"%s\" WHERE "
|
|
"%s LIMIT 1",
|
|
osMetatadataLayer.c_str(),
|
|
RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]).c_str());
|
|
OGRLayerH hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
|
|
if (hSQLLyr)
|
|
{
|
|
OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr);
|
|
if (hFeat)
|
|
{
|
|
const char* pszVal = OGR_F_GetFieldAsString(hFeat, 0);
|
|
if (pszVal)
|
|
osSourceName = pszVal;
|
|
OGR_F_Destroy(hFeat);
|
|
}
|
|
OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Compute up to which existing overview level we can use for */
|
|
/* computing the requested overview */
|
|
/* -------------------------------------------------------------------- */
|
|
int iLev;
|
|
nLimitOvrCount = 0;
|
|
for(iLev=1;iLev<nResolutions;iLev++)
|
|
{
|
|
if (!(padfXResolutions[iLev] < dfXResolution - 1e-10 &&
|
|
padfYResolutions[iLev] < dfYResolution - 1e-10))
|
|
{
|
|
break;
|
|
}
|
|
nLimitOvrCount++;
|
|
}
|
|
/* -------------------------------------------------------------------- */
|
|
/* Allocate buffer for tile of previous overview level */
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
GDALDataset* poPrevOvrLevel =
|
|
(papoOverviews != NULL && iLev >= 2 && iLev <= nResolutions && papoOverviews[iLev-2]) ?
|
|
papoOverviews[iLev-2] : this;
|
|
double dfRatioPrevOvr = poPrevOvrLevel->GetRasterBand(1)->GetXSize() / nOvrXSize;
|
|
int nPrevOvrBlockXSize = (int)(nBlockXSize * dfRatioPrevOvr + 0.5);
|
|
int nPrevOvrBlockYSize = (int)(nBlockYSize * dfRatioPrevOvr + 0.5);
|
|
GByte* pabyPrevOvrMEMDSBuffer = NULL;
|
|
|
|
if( !EQUALN(pszResampling, "NEAR", 4))
|
|
{
|
|
pabyPrevOvrMEMDSBuffer =
|
|
(GByte*)VSIMalloc3(nPrevOvrBlockXSize, nPrevOvrBlockYSize, nBands * nDataTypeSize);
|
|
if (pabyPrevOvrMEMDSBuffer == NULL)
|
|
{
|
|
VSIFree(pabyMEMDSBuffer);
|
|
return CE_Failure;
|
|
}
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Iterate over blocks to add data into raster and metadata tables */
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
char** papszTileDriverOptions = RasterliteGetTileDriverOptions(papszOptions);
|
|
|
|
OGR_DS_ExecuteSQL(hDS, "BEGIN", NULL, NULL);
|
|
|
|
CPLErr eErr = CE_None;
|
|
int nBlockXOff, nBlockYOff;
|
|
for(nBlockYOff=0;eErr == CE_None && nBlockYOff<nYBlocks;nBlockYOff++)
|
|
{
|
|
for(nBlockXOff=0;eErr == CE_None && nBlockXOff<nXBlocks;nBlockXOff++)
|
|
{
|
|
GDALDatasetH hPrevOvrMemDS = NULL;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Create in-memory tile */
|
|
/* -------------------------------------------------------------------- */
|
|
int nReqXSize = nBlockXSize, nReqYSize = nBlockYSize;
|
|
if ((nBlockXOff+1) * nBlockXSize > nOvrXSize)
|
|
nReqXSize = nOvrXSize - nBlockXOff * nBlockXSize;
|
|
if ((nBlockYOff+1) * nBlockYSize > nOvrYSize)
|
|
nReqYSize = nOvrYSize - nBlockYOff * nBlockYSize;
|
|
|
|
if( pabyPrevOvrMEMDSBuffer != NULL )
|
|
{
|
|
int nPrevOvrReqXSize =
|
|
(int)(nReqXSize * dfRatioPrevOvr + 0.5);
|
|
int nPrevOvrReqYSize =
|
|
(int)(nReqYSize * dfRatioPrevOvr + 0.5);
|
|
|
|
eErr = RasterIO(GF_Read,
|
|
nBlockXOff * nBlockXSize * nOvrFactor,
|
|
nBlockYOff * nBlockYSize * nOvrFactor,
|
|
nReqXSize * nOvrFactor, nReqYSize * nOvrFactor,
|
|
pabyPrevOvrMEMDSBuffer, nPrevOvrReqXSize, nPrevOvrReqYSize,
|
|
eDataType, nBands, NULL,
|
|
0, 0, 0, NULL);
|
|
|
|
if (eErr != CE_None)
|
|
{
|
|
break;
|
|
}
|
|
|
|
hPrevOvrMemDS = GDALCreate(hMemDriver, "MEM:::",
|
|
nPrevOvrReqXSize, nPrevOvrReqYSize, 0,
|
|
eDataType, NULL);
|
|
|
|
if (hPrevOvrMemDS == NULL)
|
|
{
|
|
eErr = CE_Failure;
|
|
break;
|
|
}
|
|
|
|
int iBand;
|
|
for(iBand = 0; iBand < nBands; iBand ++)
|
|
{
|
|
char** papszOptions = NULL;
|
|
char szTmp[64];
|
|
memset(szTmp, 0, sizeof(szTmp));
|
|
CPLPrintPointer(szTmp,
|
|
pabyPrevOvrMEMDSBuffer + iBand * nDataTypeSize *
|
|
nPrevOvrReqXSize * nPrevOvrReqYSize, sizeof(szTmp));
|
|
papszOptions = CSLSetNameValue(papszOptions, "DATAPOINTER", szTmp);
|
|
GDALAddBand(hPrevOvrMemDS, eDataType, papszOptions);
|
|
CSLDestroy(papszOptions);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
eErr = RasterIO(GF_Read,
|
|
nBlockXOff * nBlockXSize * nOvrFactor,
|
|
nBlockYOff * nBlockYSize * nOvrFactor,
|
|
nReqXSize * nOvrFactor, nReqYSize * nOvrFactor,
|
|
pabyMEMDSBuffer, nReqXSize, nReqYSize,
|
|
eDataType, nBands, NULL,
|
|
0, 0, 0, NULL);
|
|
if (eErr != CE_None)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
GDALDatasetH hMemDS = GDALCreate(hMemDriver, "MEM:::",
|
|
nReqXSize, nReqYSize, 0,
|
|
eDataType, NULL);
|
|
if (hMemDS == NULL)
|
|
{
|
|
eErr = CE_Failure;
|
|
break;
|
|
}
|
|
|
|
int iBand;
|
|
for(iBand = 0; iBand < nBands; iBand ++)
|
|
{
|
|
char** papszOptions = NULL;
|
|
char szTmp[64];
|
|
memset(szTmp, 0, sizeof(szTmp));
|
|
CPLPrintPointer(szTmp,
|
|
pabyMEMDSBuffer + iBand * nDataTypeSize *
|
|
nReqXSize * nReqYSize, sizeof(szTmp));
|
|
papszOptions = CSLSetNameValue(papszOptions, "DATAPOINTER", szTmp);
|
|
GDALAddBand(hMemDS, eDataType, papszOptions);
|
|
CSLDestroy(papszOptions);
|
|
}
|
|
|
|
if( hPrevOvrMemDS != NULL )
|
|
{
|
|
for(iBand = 0; iBand < nBands; iBand ++)
|
|
{
|
|
GDALRasterBandH hDstOvrBand = GDALGetRasterBand(hMemDS, iBand+1);
|
|
|
|
eErr = GDALRegenerateOverviews( GDALGetRasterBand(hPrevOvrMemDS, iBand+1),
|
|
1, &hDstOvrBand,
|
|
pszResampling,
|
|
NULL, NULL );
|
|
if( eErr != CE_None )
|
|
break;
|
|
}
|
|
|
|
GDALClose(hPrevOvrMemDS);
|
|
}
|
|
|
|
GDALDatasetH hOutDS = GDALCreateCopy(hTileDriver,
|
|
osTempFileName.c_str(), hMemDS, FALSE,
|
|
papszTileDriverOptions, NULL, NULL);
|
|
|
|
GDALClose(hMemDS);
|
|
if (hOutDS)
|
|
GDALClose(hOutDS);
|
|
else
|
|
{
|
|
eErr = CE_Failure;
|
|
break;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Insert new entry into raster table */
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
vsi_l_offset nDataLength;
|
|
GByte *pabyData = VSIGetMemFileBuffer( osTempFileName.c_str(),
|
|
&nDataLength, FALSE);
|
|
|
|
OGRFeatureH hFeat = OGR_F_Create( OGR_L_GetLayerDefn(hRasterLayer) );
|
|
OGR_F_SetFieldBinary(hFeat, 0, (int)nDataLength, pabyData);
|
|
|
|
OGR_L_CreateFeature(hRasterLayer, hFeat);
|
|
/* Query raster ID to set it as the ID of the associated metadata */
|
|
int nRasterID = (int)OGR_F_GetFID(hFeat);
|
|
|
|
OGR_F_Destroy(hFeat);
|
|
|
|
VSIUnlink(osTempFileName.c_str());
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Insert new entry into metadata table */
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
hFeat = OGR_F_Create( OGR_L_GetLayerDefn(hMetadataLayer) );
|
|
OGR_F_SetFID(hFeat, nRasterID);
|
|
OGR_F_SetFieldString(hFeat, 0, osSourceName);
|
|
OGR_F_SetFieldInteger(hFeat, 1, nTileId ++);
|
|
OGR_F_SetFieldInteger(hFeat, 2, nReqXSize);
|
|
OGR_F_SetFieldInteger(hFeat, 3, nReqYSize);
|
|
OGR_F_SetFieldDouble(hFeat, 4, dfXResolution);
|
|
OGR_F_SetFieldDouble(hFeat, 5, dfYResolution);
|
|
|
|
double minx, maxx, maxy, miny;
|
|
minx = adfGeoTransform[0] +
|
|
(nBlockXSize * nBlockXOff) * dfXResolution;
|
|
maxx = adfGeoTransform[0] +
|
|
(nBlockXSize * nBlockXOff + nReqXSize) * dfXResolution;
|
|
maxy = adfGeoTransform[3] +
|
|
(nBlockYSize * nBlockYOff) * (-dfYResolution);
|
|
miny = adfGeoTransform[3] +
|
|
(nBlockYSize * nBlockYOff + nReqYSize) * (-dfYResolution);
|
|
|
|
OGRGeometryH hRectangle = OGR_G_CreateGeometry(wkbPolygon);
|
|
OGRGeometryH hLinearRing = OGR_G_CreateGeometry(wkbLinearRing);
|
|
OGR_G_AddPoint_2D(hLinearRing, minx, miny);
|
|
OGR_G_AddPoint_2D(hLinearRing, minx, maxy);
|
|
OGR_G_AddPoint_2D(hLinearRing, maxx, maxy);
|
|
OGR_G_AddPoint_2D(hLinearRing, maxx, miny);
|
|
OGR_G_AddPoint_2D(hLinearRing, minx, miny);
|
|
OGR_G_AddGeometryDirectly(hRectangle, hLinearRing);
|
|
|
|
OGR_F_SetGeometryDirectly(hFeat, hRectangle);
|
|
|
|
OGR_L_CreateFeature(hMetadataLayer, hFeat);
|
|
OGR_F_Destroy(hFeat);
|
|
|
|
nBlocks++;
|
|
if (pfnProgress && !pfnProgress(1.0 * nBlocks / nTotalBlocks,
|
|
NULL, pProgressData))
|
|
eErr = CE_Failure;
|
|
}
|
|
}
|
|
|
|
nLimitOvrCount = -1;
|
|
|
|
if (eErr == CE_None)
|
|
OGR_DS_ExecuteSQL(hDS, "COMMIT", NULL, NULL);
|
|
else
|
|
OGR_DS_ExecuteSQL(hDS, "ROLLBACK", NULL, NULL);
|
|
|
|
VSIFree(pabyMEMDSBuffer);
|
|
VSIFree(pabyPrevOvrMEMDSBuffer);
|
|
|
|
CSLDestroy(papszTileDriverOptions);
|
|
papszTileDriverOptions = NULL;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Update raster_pyramids table */
|
|
/* -------------------------------------------------------------------- */
|
|
if (eErr == CE_None)
|
|
{
|
|
OGRLayerH hRasterPyramidsLyr = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
|
|
if (hRasterPyramidsLyr == NULL)
|
|
{
|
|
osSQL.Printf ("CREATE TABLE raster_pyramids ("
|
|
"table_prefix TEXT NOT NULL,"
|
|
"pixel_x_size DOUBLE NOT NULL,"
|
|
"pixel_y_size DOUBLE NOT NULL,"
|
|
"tile_count INTEGER NOT NULL)");
|
|
OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
|
|
|
|
/* Re-open the DB to take into account the new tables*/
|
|
OGRReleaseDataSource(hDS);
|
|
|
|
hDS = RasterliteOpenSQLiteDB(osFileName.c_str(), GA_Update);
|
|
|
|
hRasterPyramidsLyr = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
|
|
if (hRasterPyramidsLyr == NULL)
|
|
return CE_Failure;
|
|
}
|
|
OGRFeatureDefnH hFDefn = OGR_L_GetLayerDefn(hRasterPyramidsLyr);
|
|
|
|
/* Insert base resolution into raster_pyramids if not already done */
|
|
int bHasBaseResolution = FALSE;
|
|
osSQL.Printf("SELECT * FROM raster_pyramids WHERE "
|
|
"table_prefix = '%s' AND %s",
|
|
osTableName.c_str(),
|
|
RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]).c_str());
|
|
hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
|
|
if (hSQLLyr)
|
|
{
|
|
OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr);
|
|
if (hFeat)
|
|
{
|
|
bHasBaseResolution = TRUE;
|
|
OGR_F_Destroy(hFeat);
|
|
}
|
|
OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
|
|
}
|
|
|
|
if (!bHasBaseResolution)
|
|
{
|
|
osSQL.Printf("SELECT COUNT(*) FROM \"%s\" WHERE %s",
|
|
osMetatadataLayer.c_str(),
|
|
RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]).c_str());
|
|
|
|
int nBlocksMainRes = 0;
|
|
|
|
hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
|
|
if (hSQLLyr)
|
|
{
|
|
OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr);
|
|
if (hFeat)
|
|
{
|
|
nBlocksMainRes = OGR_F_GetFieldAsInteger(hFeat, 0);
|
|
OGR_F_Destroy(hFeat);
|
|
}
|
|
OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
|
|
}
|
|
|
|
OGRFeatureH hFeat = OGR_F_Create( hFDefn );
|
|
OGR_F_SetFieldString(hFeat, OGR_FD_GetFieldIndex(hFDefn, "table_prefix"), osTableName.c_str());
|
|
OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_x_size"), padfXResolutions[0]);
|
|
OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_y_size"), padfYResolutions[0]);
|
|
OGR_F_SetFieldInteger(hFeat, OGR_FD_GetFieldIndex(hFDefn, "tile_count"), nBlocksMainRes);
|
|
OGR_L_CreateFeature(hRasterPyramidsLyr, hFeat);
|
|
OGR_F_Destroy(hFeat);
|
|
}
|
|
|
|
OGRFeatureH hFeat = OGR_F_Create( hFDefn );
|
|
OGR_F_SetFieldString(hFeat, OGR_FD_GetFieldIndex(hFDefn, "table_prefix"), osTableName.c_str());
|
|
OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_x_size"), dfXResolution);
|
|
OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_y_size"), dfYResolution);
|
|
OGR_F_SetFieldInteger(hFeat, OGR_FD_GetFieldIndex(hFDefn, "tile_count"), nTotalBlocks);
|
|
OGR_L_CreateFeature(hRasterPyramidsLyr, hFeat);
|
|
OGR_F_Destroy(hFeat);
|
|
}
|
|
|
|
return eErr;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* IBuildOverviews() */
|
|
/************************************************************************/
|
|
|
|
CPLErr RasterliteDataset::IBuildOverviews( const char * pszResampling,
|
|
int nOverviews, int * panOverviewList,
|
|
int nBands, int * panBandList,
|
|
GDALProgressFunc pfnProgress,
|
|
void * pProgressData )
|
|
{
|
|
CPLErr eErr = CE_None;
|
|
|
|
if (nLevel != 0)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
"Overviews can only be computed on the base dataset");
|
|
return CE_Failure;
|
|
}
|
|
|
|
if (osTableName.size() == 0)
|
|
return CE_Failure;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* If we don't have read access, then create the overviews */
|
|
/* externally. */
|
|
/* -------------------------------------------------------------------- */
|
|
if( GetAccess() != GA_Update )
|
|
{
|
|
CPLDebug( "Rasterlite",
|
|
"File open for read-only accessing, "
|
|
"creating overviews externally." );
|
|
|
|
if (nResolutions != 1)
|
|
{
|
|
CPLError(CE_Failure, CPLE_NotSupported,
|
|
"Cannot add external overviews to a "
|
|
"dataset with internal overviews");
|
|
return CE_Failure;
|
|
}
|
|
|
|
bCheckForExistingOverview = FALSE;
|
|
eErr = GDALDataset::IBuildOverviews(
|
|
pszResampling, nOverviews, panOverviewList,
|
|
nBands, panBandList, pfnProgress, pProgressData );
|
|
bCheckForExistingOverview = TRUE;
|
|
return eErr;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* If zero overviews were requested, we need to clear all */
|
|
/* existing overviews. */
|
|
/* -------------------------------------------------------------------- */
|
|
if (nOverviews == 0)
|
|
{
|
|
return CleanOverviews();
|
|
}
|
|
|
|
if( nBands != GetRasterCount() )
|
|
{
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"Generation of overviews in RASTERLITE only"
|
|
" supported when operating on all bands.\n"
|
|
"Operation failed.\n" );
|
|
return CE_Failure;
|
|
}
|
|
|
|
const char* pszOvrOptions = CPLGetConfigOption("RASTERLITE_OVR_OPTIONS", NULL);
|
|
char** papszOptions = (pszOvrOptions) ? CSLTokenizeString2( pszOvrOptions, ",", 0) : NULL;
|
|
GDALValidateCreationOptions( GetDriver(), papszOptions);
|
|
|
|
int i;
|
|
for(i=0;i<nOverviews && eErr == CE_None;i++)
|
|
{
|
|
if (panOverviewList[i] <= 1)
|
|
continue;
|
|
|
|
eErr = CleanOverviewLevel(panOverviewList[i]);
|
|
if (eErr == CE_None)
|
|
eErr = CreateOverviewLevel(pszResampling, panOverviewList[i], papszOptions, pfnProgress, pProgressData);
|
|
|
|
ReloadOverviews();
|
|
}
|
|
|
|
CSLDestroy(papszOptions);
|
|
|
|
return eErr;
|
|
}
|