LCOV - code coverage report
Current view: top level - frmts/rasterlite - rasterliteoverviews.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 307 382 80.4 %
Date: 2024-05-04 12:52:34 Functions: 5 5 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL Rasterlite driver
       4             :  * Purpose:  Implement GDAL Rasterlite support using OGR SQLite driver
       5             :  * Author:   Even Rouault, <even dot rouault at spatialys.com>
       6             :  *
       7             :  **********************************************************************
       8             :  * Copyright (c) 2009-2012, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * Permission is hereby granted, free of charge, to any person obtaining a
      11             :  * copy of this software and associated documentation files (the "Software"),
      12             :  * to deal in the Software without restriction, including without limitation
      13             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14             :  * and/or sell copies of the Software, and to permit persons to whom the
      15             :  * Software is furnished to do so, subject to the following conditions:
      16             :  *
      17             :  * The above copyright notice and this permission notice shall be included
      18             :  * in all copies or substantial portions of the Software.
      19             :  *
      20             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      23             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26             :  * DEALINGS IN THE SOFTWARE.
      27             :  ****************************************************************************/
      28             : 
      29             : #include "cpl_string.h"
      30             : #include "ogr_api.h"
      31             : #include "ogr_srs_api.h"
      32             : #include "memdataset.h"
      33             : 
      34             : #include "rasterlitedataset.h"
      35             : 
      36             : /************************************************************************/
      37             : /*                         ReloadOverviews()                            */
      38             : /************************************************************************/
      39             : 
      40           4 : CPLErr RasterliteDataset::ReloadOverviews()
      41             : {
      42           4 :     if (nLevel != 0)
      43           0 :         return CE_Failure;
      44             : 
      45             :     /* -------------------------------------------------------------------- */
      46             :     /*      Fetch resolutions                                               */
      47             :     /* -------------------------------------------------------------------- */
      48             : 
      49           8 :     CPLString osSQL;
      50             :     OGRLayerH hRasterPyramidsLyr =
      51           4 :         OGR_DS_GetLayerByName(hDS, "raster_pyramids");
      52           4 :     if (hRasterPyramidsLyr)
      53             :     {
      54             :         osSQL.Printf("SELECT pixel_x_size, pixel_y_size "
      55             :                      "FROM raster_pyramids WHERE table_prefix = '%s' "
      56             :                      "ORDER BY pixel_x_size ASC",
      57           4 :                      osTableName.c_str());
      58             :     }
      59             :     else
      60             :     {
      61             :         osSQL.Printf("SELECT DISTINCT(pixel_x_size), pixel_y_size "
      62             :                      "FROM \"%s_metadata\" WHERE pixel_x_size != 0  "
      63             :                      "ORDER BY pixel_x_size ASC",
      64           0 :                      osTableName.c_str());
      65             :     }
      66             : 
      67           4 :     OGRLayerH hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
      68           4 :     if (hSQLLyr == nullptr)
      69             :     {
      70           0 :         if (hRasterPyramidsLyr == nullptr)
      71           0 :             return CE_Failure;
      72             : 
      73             :         osSQL.Printf("SELECT DISTINCT(pixel_x_size), pixel_y_size "
      74             :                      "FROM \"%s_metadata\" WHERE pixel_x_size != 0  "
      75             :                      "ORDER BY pixel_x_size ASC",
      76           0 :                      osTableName.c_str());
      77             : 
      78           0 :         hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
      79           0 :         if (hSQLLyr == nullptr)
      80           0 :             return CE_Failure;
      81             :     }
      82             : 
      83             :     /* -------------------------------------------------------------------- */
      84             :     /*      Cleanup                                                         */
      85             :     /* -------------------------------------------------------------------- */
      86           6 :     for (int i = 1; i < nResolutions; i++)
      87           2 :         delete papoOverviews[i - 1];
      88           4 :     CPLFree(papoOverviews);
      89           4 :     papoOverviews = nullptr;
      90           4 :     CPLFree(padfXResolutions);
      91           4 :     padfXResolutions = nullptr;
      92           4 :     CPLFree(padfYResolutions);
      93           4 :     padfYResolutions = nullptr;
      94             : 
      95             :     /* -------------------------------------------------------------------- */
      96             :     /*      Rebuild arrays                                                  */
      97             :     /* -------------------------------------------------------------------- */
      98             : 
      99           4 :     nResolutions = static_cast<int>(OGR_L_GetFeatureCount(hSQLLyr, TRUE));
     100             : 
     101           4 :     padfXResolutions =
     102           4 :         reinterpret_cast<double *>(CPLMalloc(sizeof(double) * nResolutions));
     103           4 :     padfYResolutions =
     104           4 :         reinterpret_cast<double *>(CPLMalloc(sizeof(double) * nResolutions));
     105             : 
     106             :     {
     107             :         // Exstra scope for i.
     108           4 :         int i = 0;
     109             :         OGRFeatureH hFeat;
     110          14 :         while ((hFeat = OGR_L_GetNextFeature(hSQLLyr)) != nullptr)
     111             :         {
     112          10 :             padfXResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 0);
     113          10 :             padfYResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 1);
     114             : 
     115          10 :             OGR_F_Destroy(hFeat);
     116             : 
     117          10 :             i++;
     118             :         }
     119             :     }
     120             : 
     121           4 :     OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
     122           4 :     hSQLLyr = nullptr;
     123             : 
     124             :     /* -------------------------------------------------------------------- */
     125             :     /*      Add overview levels as internal datasets                        */
     126             :     /* -------------------------------------------------------------------- */
     127           4 :     if (nResolutions > 1)
     128             :     {
     129           8 :         CPLString osRasterTableName = osTableName;
     130           4 :         osRasterTableName += "_rasters";
     131             : 
     132             :         OGRLayerH hRasterLyr =
     133           4 :             OGR_DS_GetLayerByName(hDS, osRasterTableName.c_str());
     134             : 
     135           4 :         papoOverviews = reinterpret_cast<RasterliteDataset **>(
     136           4 :             CPLCalloc(nResolutions - 1, sizeof(RasterliteDataset *)));
     137          10 :         for (int nLev = 1; nLev < nResolutions; nLev++)
     138             :         {
     139             :             int nOvrBands;
     140             :             GDALDataType eOvrDataType;
     141             :             int nBlockXSize, nBlockYSize;
     142           6 :             if (GetBlockParams(hRasterLyr, nLev, &nOvrBands, &eOvrDataType,
     143           6 :                                &nBlockXSize, &nBlockYSize))
     144             :             {
     145           6 :                 if (eOvrDataType == GDT_Byte && nOvrBands == 1 && nBands == 3)
     146           0 :                     nOvrBands = 3;
     147             : 
     148           6 :                 papoOverviews[nLev - 1] = new RasterliteDataset(this, nLev);
     149             : 
     150          12 :                 for (int iBand = 0; iBand < nBands; iBand++)
     151             :                 {
     152           6 :                     papoOverviews[nLev - 1]->SetBand(
     153             :                         iBand + 1, new RasterliteBand(
     154           6 :                                        papoOverviews[nLev - 1], iBand + 1,
     155           6 :                                        eOvrDataType, nBlockXSize, nBlockYSize));
     156             :                 }
     157             :             }
     158             :             else
     159             :             {
     160           0 :                 CPLError(CE_Failure, CPLE_AppDefined,
     161             :                          "Cannot find block characteristics for overview %d",
     162             :                          nLev);
     163           0 :                 papoOverviews[nLev - 1] = nullptr;
     164             :             }
     165             :         }
     166             :     }
     167             : 
     168           4 :     return CE_None;
     169             : }
     170             : 
     171             : /************************************************************************/
     172             : /*                          CleanOverviews()                            */
     173             : /************************************************************************/
     174             : 
     175           1 : CPLErr RasterliteDataset::CleanOverviews()
     176             : {
     177           1 :     if (nLevel != 0)
     178           0 :         return CE_Failure;
     179             : 
     180           2 :     CPLString osSQL("BEGIN");
     181           1 :     OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
     182             : 
     183             :     const CPLString osResolutionCond =
     184           2 :         "NOT " +
     185           2 :         RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]);
     186             : 
     187             :     osSQL.Printf("DELETE FROM \"%s_rasters\" WHERE id "
     188             :                  "IN(SELECT id FROM \"%s_metadata\" WHERE %s)",
     189             :                  osTableName.c_str(), osTableName.c_str(),
     190           1 :                  osResolutionCond.c_str());
     191           1 :     OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
     192             : 
     193             :     osSQL.Printf("DELETE FROM \"%s_metadata\" WHERE %s", osTableName.c_str(),
     194           1 :                  osResolutionCond.c_str());
     195           1 :     OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
     196             : 
     197             :     OGRLayerH hRasterPyramidsLyr =
     198           1 :         OGR_DS_GetLayerByName(hDS, "raster_pyramids");
     199           1 :     if (hRasterPyramidsLyr)
     200             :     {
     201             :         osSQL.Printf(
     202             :             "DELETE FROM raster_pyramids WHERE table_prefix = '%s' AND %s",
     203           1 :             osTableName.c_str(), osResolutionCond.c_str());
     204           1 :         OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
     205             :     }
     206             : 
     207           1 :     osSQL = "COMMIT";
     208           1 :     OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
     209             : 
     210           3 :     for (int i = 1; i < nResolutions; i++)
     211           2 :         delete papoOverviews[i - 1];
     212           1 :     CPLFree(papoOverviews);
     213           1 :     papoOverviews = nullptr;
     214           1 :     nResolutions = 1;
     215             : 
     216           1 :     return CE_None;
     217             : }
     218             : 
     219             : /************************************************************************/
     220             : /*                       CleanOverviewLevel()                           */
     221             : /************************************************************************/
     222             : 
     223           4 : CPLErr RasterliteDataset::CleanOverviewLevel(int nOvrFactor)
     224             : {
     225           4 :     if (nLevel != 0)
     226           0 :         return CE_Failure;
     227             : 
     228             :     /* -------------------------------------------------------------------- */
     229             :     /*      Find the index of the overview matching the overview factor     */
     230             :     /* -------------------------------------------------------------------- */
     231           4 :     int iLev = 1;
     232           6 :     for (; iLev < nResolutions; iLev++)
     233             :     {
     234           2 :         if (fabs(padfXResolutions[0] * nOvrFactor - padfXResolutions[iLev]) <
     235           0 :                 1e-15 &&
     236           0 :             fabs(padfYResolutions[0] * nOvrFactor - padfYResolutions[iLev]) <
     237             :                 1e-15)
     238           0 :             break;
     239             :     }
     240             : 
     241           4 :     if (iLev == nResolutions)
     242           4 :         return CE_None;
     243             : 
     244             :     /* -------------------------------------------------------------------- */
     245             :     /*      Now clean existing overviews at that resolution                 */
     246             :     /* -------------------------------------------------------------------- */
     247             : 
     248           0 :     CPLString osSQL("BEGIN");
     249           0 :     OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
     250             : 
     251             :     CPLString osResolutionCond = RasterliteGetPixelSizeCond(
     252           0 :         padfXResolutions[iLev], padfYResolutions[iLev]);
     253             : 
     254             :     osSQL.Printf("DELETE FROM \"%s_rasters\" WHERE id "
     255             :                  "IN(SELECT id FROM \"%s_metadata\" WHERE %s)",
     256             :                  osTableName.c_str(), osTableName.c_str(),
     257           0 :                  osResolutionCond.c_str());
     258           0 :     OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
     259             : 
     260             :     osSQL.Printf("DELETE FROM \"%s_metadata\" WHERE %s", osTableName.c_str(),
     261           0 :                  osResolutionCond.c_str());
     262           0 :     OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
     263             : 
     264             :     OGRLayerH hRasterPyramidsLyr =
     265           0 :         OGR_DS_GetLayerByName(hDS, "raster_pyramids");
     266           0 :     if (hRasterPyramidsLyr)
     267             :     {
     268             :         osSQL.Printf(
     269             :             "DELETE FROM raster_pyramids WHERE table_prefix = '%s' AND %s",
     270           0 :             osTableName.c_str(), osResolutionCond.c_str());
     271           0 :         OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
     272             :     }
     273             : 
     274           0 :     osSQL = "COMMIT";
     275           0 :     OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
     276             : 
     277           0 :     return CE_None;
     278             : }
     279             : 
     280             : /************************************************************************/
     281             : /*                       CleanOverviewLevel()                           */
     282             : /************************************************************************/
     283             : 
     284           4 : CPLErr RasterliteDataset::CreateOverviewLevel(const char *pszResampling,
     285             :                                               int nOvrFactor,
     286             :                                               CSLConstList papszOptions,
     287             :                                               GDALProgressFunc pfnProgress,
     288             :                                               void *pProgressData)
     289             : {
     290           4 :     const int nOvrXSize = nRasterXSize / nOvrFactor;
     291           4 :     const int nOvrYSize = nRasterYSize / nOvrFactor;
     292             : 
     293           4 :     if (nOvrXSize == 0 || nOvrYSize == 0)
     294           0 :         return CE_Failure;
     295             : 
     296             :     const bool bTiled =
     297           4 :         CPLTestBool(CSLFetchNameValueDef(papszOptions, "TILED", "YES"));
     298             :     int nBlockXSize, nBlockYSize;
     299           4 :     if (bTiled)
     300             :     {
     301             :         nBlockXSize =
     302           4 :             atoi(CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", "256"));
     303             :         nBlockYSize =
     304           4 :             atoi(CSLFetchNameValueDef(papszOptions, "BLOCKYSIZE", "256"));
     305           4 :         if (nBlockXSize < 64)
     306           0 :             nBlockXSize = 64;
     307           4 :         else if (nBlockXSize > 4096)
     308           0 :             nBlockXSize = 4096;
     309           4 :         if (nBlockYSize < 64)
     310           0 :             nBlockYSize = 64;
     311           4 :         else if (nBlockYSize > 4096)
     312           0 :             nBlockYSize = 4096;
     313             :     }
     314             :     else
     315             :     {
     316           0 :         nBlockXSize = nOvrXSize;
     317           0 :         nBlockYSize = nOvrYSize;
     318             :     }
     319             : 
     320             :     const char *pszDriverName =
     321           4 :         CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff");
     322           4 :     if (EQUAL(pszDriverName, "MEM") || EQUAL(pszDriverName, "VRT"))
     323             :     {
     324           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     325             :                  "GDAL %s driver cannot be used as underlying driver",
     326             :                  pszDriverName);
     327           0 :         return CE_Failure;
     328             :     }
     329           4 :     GDALDriverH hTileDriver = GDALGetDriverByName(pszDriverName);
     330           4 :     if (hTileDriver == nullptr)
     331             :     {
     332           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL %s driver",
     333             :                  pszDriverName);
     334           0 :         return CE_Failure;
     335             :     }
     336             : 
     337           4 :     GDALDriverH hMemDriver = GDALGetDriverByName("MEM");
     338           4 :     if (hMemDriver == nullptr)
     339             :     {
     340           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL MEM driver");
     341           0 :         return CE_Failure;
     342             :     }
     343             : 
     344           4 :     const GDALDataType eDataType = GetRasterBand(1)->GetRasterDataType();
     345           4 :     int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8;
     346           4 :     GByte *pabyMEMDSBuffer = reinterpret_cast<GByte *>(VSIMalloc3(
     347           4 :         nBlockXSize, nBlockYSize, cpl::fits_on<int>(nBands * nDataTypeSize)));
     348           4 :     if (pabyMEMDSBuffer == nullptr)
     349             :     {
     350           0 :         return CE_Failure;
     351             :     }
     352             : 
     353           8 :     CPLString osTempFileName;
     354           4 :     osTempFileName.Printf("/vsimem/%p", hDS);
     355             : 
     356           4 :     int nTileId = 0;
     357           4 :     int nBlocks = 0;
     358             : 
     359           4 :     const int nXBlocks = (nOvrXSize + nBlockXSize - 1) / nBlockXSize;
     360           4 :     const int nYBlocks = (nOvrYSize + nBlockYSize - 1) / nBlockYSize;
     361           4 :     int nTotalBlocks = nXBlocks * nYBlocks;
     362             : 
     363           8 :     CPLString osRasterLayer;
     364           4 :     osRasterLayer.Printf("%s_rasters", osTableName.c_str());
     365             : 
     366           8 :     CPLString osMetatadataLayer;
     367           4 :     osMetatadataLayer.Printf("%s_metadata", osTableName.c_str());
     368             : 
     369           4 :     OGRLayerH hRasterLayer = OGR_DS_GetLayerByName(hDS, osRasterLayer.c_str());
     370             :     OGRLayerH hMetadataLayer =
     371           4 :         OGR_DS_GetLayerByName(hDS, osMetatadataLayer.c_str());
     372             : 
     373           8 :     CPLString osSourceName = "unknown";
     374             : 
     375           4 :     const double dfXResolution = padfXResolutions[0] * nOvrFactor;
     376           4 :     const double dfYResolution = padfXResolutions[0] * nOvrFactor;
     377             : 
     378           8 :     CPLString osSQL;
     379             :     osSQL.Printf(
     380             :         "SELECT source_name FROM \"%s\" WHERE "
     381             :         "%s LIMIT 1",
     382             :         osMetatadataLayer.c_str(),
     383           8 :         RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0])
     384           4 :             .c_str());
     385           4 :     OGRLayerH hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
     386           4 :     if (hSQLLyr)
     387             :     {
     388           4 :         OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr);
     389           4 :         if (hFeat)
     390             :         {
     391           4 :             const char *pszVal = OGR_F_GetFieldAsString(hFeat, 0);
     392           4 :             if (pszVal)
     393           4 :                 osSourceName = pszVal;
     394           4 :             OGR_F_Destroy(hFeat);
     395             :         }
     396           4 :         OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
     397             :     }
     398             : 
     399             :     /* -------------------------------------------------------------------- */
     400             :     /*      Compute up to which existing overview level we can use for      */
     401             :     /*      computing the requested overview                                */
     402             :     /* -------------------------------------------------------------------- */
     403           4 :     nLimitOvrCount = 0;
     404           4 :     int iLev = 1;
     405           6 :     for (; iLev < nResolutions; iLev++)
     406             :     {
     407           2 :         if (!(padfXResolutions[iLev] < dfXResolution - 1e-10 &&
     408           2 :               padfYResolutions[iLev] < dfYResolution - 1e-10))
     409             :         {
     410             :             break;
     411             :         }
     412           2 :         nLimitOvrCount++;
     413             :     }
     414             :     /* -------------------------------------------------------------------- */
     415             :     /*      Allocate buffer for tile of previous overview level             */
     416             :     /* -------------------------------------------------------------------- */
     417             : 
     418           4 :     GDALDataset *poPrevOvrLevel =
     419           2 :         (papoOverviews != nullptr && iLev >= 2 && iLev <= nResolutions &&
     420           2 :          papoOverviews[iLev - 2])
     421           6 :             ? papoOverviews[iLev - 2]
     422             :             : this;
     423             :     const double dfRatioPrevOvr =
     424           4 :         static_cast<double>(poPrevOvrLevel->GetRasterBand(1)->GetXSize()) /
     425           4 :         nOvrXSize;
     426           4 :     const int nPrevOvrBlockXSize =
     427           4 :         static_cast<int>(nBlockXSize * dfRatioPrevOvr + 0.5);
     428           4 :     const int nPrevOvrBlockYSize =
     429           4 :         static_cast<int>(nBlockYSize * dfRatioPrevOvr + 0.5);
     430           4 :     GByte *pabyPrevOvrMEMDSBuffer = nullptr;
     431             : 
     432           4 :     if (!STARTS_WITH_CI(pszResampling, "NEAR"))
     433             :     {
     434             :         pabyPrevOvrMEMDSBuffer = reinterpret_cast<GByte *>(
     435           2 :             VSIMalloc3(nPrevOvrBlockXSize, nPrevOvrBlockYSize,
     436           2 :                        cpl::fits_on<int>(nBands * nDataTypeSize)));
     437           2 :         if (pabyPrevOvrMEMDSBuffer == nullptr)
     438             :         {
     439           0 :             VSIFree(pabyMEMDSBuffer);
     440           0 :             return CE_Failure;
     441             :         }
     442             :     }
     443             : 
     444             :     /* -------------------------------------------------------------------- */
     445             :     /*      Iterate over blocks to add data into raster and metadata tables */
     446             :     /* -------------------------------------------------------------------- */
     447             : 
     448             :     char **papszTileDriverOptions =
     449           4 :         RasterliteGetTileDriverOptions(papszOptions);
     450             : 
     451           4 :     OGR_DS_ExecuteSQL(hDS, "BEGIN", nullptr, nullptr);
     452             : 
     453           4 :     CPLErr eErr = CE_None;
     454           8 :     for (int nBlockYOff = 0; eErr == CE_None && nBlockYOff < nYBlocks;
     455             :          nBlockYOff++)
     456             :     {
     457           8 :         for (int nBlockXOff = 0; eErr == CE_None && nBlockXOff < nXBlocks;
     458             :              nBlockXOff++)
     459             :         {
     460           0 :             std::unique_ptr<MEMDataset> poPrevOvrMemDS;
     461             : 
     462             :             /* --------------------------------------------------------------------
     463             :              */
     464             :             /*      Create in-memory tile */
     465             :             /* --------------------------------------------------------------------
     466             :              */
     467           4 :             int nReqXSize = nBlockXSize;
     468           4 :             int nReqYSize = nBlockYSize;
     469           4 :             if ((nBlockXOff + 1) * nBlockXSize > nOvrXSize)
     470           4 :                 nReqXSize = nOvrXSize - nBlockXOff * nBlockXSize;
     471           4 :             if ((nBlockYOff + 1) * nBlockYSize > nOvrYSize)
     472           4 :                 nReqYSize = nOvrYSize - nBlockYOff * nBlockYSize;
     473             : 
     474           4 :             if (pabyPrevOvrMEMDSBuffer != nullptr)
     475             :             {
     476           2 :                 int nPrevOvrReqXSize =
     477           2 :                     static_cast<int>(nReqXSize * dfRatioPrevOvr + 0.5);
     478           2 :                 int nPrevOvrReqYSize =
     479           2 :                     static_cast<int>(nReqYSize * dfRatioPrevOvr + 0.5);
     480             : 
     481           4 :                 eErr = RasterIO(GF_Read, nBlockXOff * nBlockXSize * nOvrFactor,
     482           2 :                                 nBlockYOff * nBlockYSize * nOvrFactor,
     483             :                                 nReqXSize * nOvrFactor, nReqYSize * nOvrFactor,
     484             :                                 pabyPrevOvrMEMDSBuffer, nPrevOvrReqXSize,
     485             :                                 nPrevOvrReqYSize, eDataType, nBands, nullptr, 0,
     486             :                                 0, 0, nullptr);
     487             : 
     488           2 :                 if (eErr != CE_None)
     489             :                 {
     490           0 :                     break;
     491             :                 }
     492             : 
     493           2 :                 poPrevOvrMemDS.reset(MEMDataset::Create("", nPrevOvrReqXSize,
     494             :                                                         nPrevOvrReqYSize, 0,
     495             :                                                         eDataType, nullptr));
     496             : 
     497           4 :                 for (int iBand = 0; iBand < nBands; iBand++)
     498             :                 {
     499           2 :                     auto hBand = MEMCreateRasterBandEx(
     500           2 :                         poPrevOvrMemDS.get(), iBand + 1,
     501           2 :                         pabyPrevOvrMEMDSBuffer + iBand * nDataTypeSize *
     502           2 :                                                      nPrevOvrReqXSize *
     503             :                                                      nPrevOvrReqYSize,
     504             :                         eDataType, 0, 0, false);
     505           2 :                     poPrevOvrMemDS->AddMEMBand(hBand);
     506             :                 }
     507             :             }
     508             :             else
     509             :             {
     510           4 :                 eErr = RasterIO(GF_Read, nBlockXOff * nBlockXSize * nOvrFactor,
     511           2 :                                 nBlockYOff * nBlockYSize * nOvrFactor,
     512             :                                 nReqXSize * nOvrFactor, nReqYSize * nOvrFactor,
     513             :                                 pabyMEMDSBuffer, nReqXSize, nReqYSize,
     514             :                                 eDataType, nBands, nullptr, 0, 0, 0, nullptr);
     515           2 :                 if (eErr != CE_None)
     516             :                 {
     517           0 :                     break;
     518             :                 }
     519             :             }
     520             : 
     521             :             auto poMemDS = std::unique_ptr<MEMDataset>(MEMDataset::Create(
     522           4 :                 "", nReqXSize, nReqYSize, 0, eDataType, nullptr));
     523           8 :             for (int iBand = 0; iBand < nBands; iBand++)
     524             :             {
     525           4 :                 auto hBand = MEMCreateRasterBandEx(
     526           4 :                     poMemDS.get(), iBand + 1,
     527             :                     pabyMEMDSBuffer +
     528           4 :                         iBand * nDataTypeSize * nReqXSize * nReqYSize,
     529             :                     eDataType, 0, 0, false);
     530           4 :                 poMemDS->AddMEMBand(hBand);
     531             :             }
     532             : 
     533           4 :             auto hMemDS = GDALDataset::ToHandle(poMemDS.get());
     534           4 :             if (poPrevOvrMemDS != nullptr)
     535             :             {
     536           4 :                 for (int iBand = 0; iBand < nBands; iBand++)
     537             :                 {
     538             :                     GDALRasterBandH hDstOvrBand =
     539           2 :                         GDALGetRasterBand(hMemDS, iBand + 1);
     540             : 
     541             :                     auto hPrevOvrMEMDS =
     542           2 :                         GDALDataset::ToHandle(poPrevOvrMemDS.get());
     543           2 :                     eErr = GDALRegenerateOverviews(
     544             :                         GDALGetRasterBand(hPrevOvrMEMDS, iBand + 1), 1,
     545             :                         &hDstOvrBand, pszResampling, nullptr, nullptr);
     546           2 :                     if (eErr != CE_None)
     547           0 :                         break;
     548             :                 }
     549             : 
     550           2 :                 poPrevOvrMemDS.reset();
     551             :             }
     552             : 
     553             :             GDALDatasetH hOutDS =
     554           4 :                 GDALCreateCopy(hTileDriver, osTempFileName.c_str(), hMemDS,
     555             :                                FALSE, papszTileDriverOptions, nullptr, nullptr);
     556             : 
     557           4 :             poMemDS.reset();
     558           4 :             if (!hOutDS)
     559             :             {
     560           0 :                 eErr = CE_Failure;
     561           0 :                 break;
     562             :             }
     563             : 
     564           4 :             GDALClose(hOutDS);
     565             : 
     566             :             /* --------------------------------------------------------------------
     567             :              */
     568             :             /*      Insert new entry into raster table */
     569             :             /* --------------------------------------------------------------------
     570             :              */
     571             : 
     572             :             vsi_l_offset nDataLength;
     573           4 :             GByte *pabyData = VSIGetMemFileBuffer(osTempFileName.c_str(),
     574             :                                                   &nDataLength, FALSE);
     575             : 
     576           4 :             OGRFeatureH hFeat = OGR_F_Create(OGR_L_GetLayerDefn(hRasterLayer));
     577           4 :             OGR_F_SetFieldBinary(hFeat, 0, static_cast<int>(nDataLength),
     578             :                                  pabyData);
     579             : 
     580           4 :             if (OGR_L_CreateFeature(hRasterLayer, hFeat) != OGRERR_NONE)
     581           0 :                 eErr = CE_Failure;
     582             :             /* Query raster ID to set it as the ID of the associated metadata */
     583           4 :             const int nRasterID = static_cast<int>(OGR_F_GetFID(hFeat));
     584             : 
     585           4 :             OGR_F_Destroy(hFeat);
     586             : 
     587           4 :             VSIUnlink(osTempFileName.c_str());
     588           4 :             if (eErr == CE_Failure)
     589           0 :                 break;
     590             : 
     591             :             /* --------------------------------------------------------------------
     592             :              */
     593             :             /*      Insert new entry into metadata table */
     594             :             /* --------------------------------------------------------------------
     595             :              */
     596             : 
     597           4 :             hFeat = OGR_F_Create(OGR_L_GetLayerDefn(hMetadataLayer));
     598           4 :             OGR_F_SetFID(hFeat, nRasterID);
     599           4 :             OGR_F_SetFieldString(hFeat, 0, osSourceName);
     600           4 :             OGR_F_SetFieldInteger(hFeat, 1, nTileId++);
     601           4 :             OGR_F_SetFieldInteger(hFeat, 2, nReqXSize);
     602           4 :             OGR_F_SetFieldInteger(hFeat, 3, nReqYSize);
     603           4 :             OGR_F_SetFieldDouble(hFeat, 4, dfXResolution);
     604           4 :             OGR_F_SetFieldDouble(hFeat, 5, dfYResolution);
     605             : 
     606           4 :             const double minx =
     607           4 :                 adfGeoTransform[0] + (nBlockXSize * nBlockXOff) * dfXResolution;
     608           4 :             const double maxx =
     609           4 :                 adfGeoTransform[0] +
     610           4 :                 (nBlockXSize * nBlockXOff + nReqXSize) * dfXResolution;
     611           4 :             const double maxy = adfGeoTransform[3] +
     612           4 :                                 (nBlockYSize * nBlockYOff) * (-dfYResolution);
     613           4 :             const double miny =
     614           4 :                 adfGeoTransform[3] +
     615           4 :                 (nBlockYSize * nBlockYOff + nReqYSize) * (-dfYResolution);
     616             : 
     617           4 :             OGRGeometryH hRectangle = OGR_G_CreateGeometry(wkbPolygon);
     618           4 :             OGRGeometryH hLinearRing = OGR_G_CreateGeometry(wkbLinearRing);
     619           4 :             OGR_G_AddPoint_2D(hLinearRing, minx, miny);
     620           4 :             OGR_G_AddPoint_2D(hLinearRing, minx, maxy);
     621           4 :             OGR_G_AddPoint_2D(hLinearRing, maxx, maxy);
     622           4 :             OGR_G_AddPoint_2D(hLinearRing, maxx, miny);
     623           4 :             OGR_G_AddPoint_2D(hLinearRing, minx, miny);
     624           4 :             OGR_G_AddGeometryDirectly(hRectangle, hLinearRing);
     625             : 
     626           4 :             OGR_F_SetGeometryDirectly(hFeat, hRectangle);
     627             : 
     628           4 :             if (OGR_L_CreateFeature(hMetadataLayer, hFeat) != OGRERR_NONE)
     629           0 :                 eErr = CE_Failure;
     630           4 :             OGR_F_Destroy(hFeat);
     631             : 
     632           4 :             nBlocks++;
     633           4 :             if (pfnProgress && !pfnProgress(1.0 * nBlocks / nTotalBlocks,
     634             :                                             nullptr, pProgressData))
     635           0 :                 eErr = CE_Failure;
     636             :         }
     637             :     }
     638             : 
     639           4 :     nLimitOvrCount = -1;
     640             : 
     641           4 :     VSIUnlink(osTempFileName);
     642           4 :     VSIUnlink((osTempFileName + ".aux.xml").c_str());
     643             : 
     644           4 :     if (eErr == CE_None)
     645           4 :         OGR_DS_ExecuteSQL(hDS, "COMMIT", nullptr, nullptr);
     646             :     else
     647           0 :         OGR_DS_ExecuteSQL(hDS, "ROLLBACK", nullptr, nullptr);
     648             : 
     649           4 :     VSIFree(pabyMEMDSBuffer);
     650           4 :     VSIFree(pabyPrevOvrMEMDSBuffer);
     651             : 
     652           4 :     CSLDestroy(papszTileDriverOptions);
     653           4 :     papszTileDriverOptions = nullptr;
     654             : 
     655             :     /* -------------------------------------------------------------------- */
     656             :     /*      Update raster_pyramids table                                    */
     657             :     /* -------------------------------------------------------------------- */
     658           4 :     if (eErr != CE_None)
     659           0 :         return eErr;
     660             : 
     661             :     OGRLayerH hRasterPyramidsLyr =
     662           4 :         OGR_DS_GetLayerByName(hDS, "raster_pyramids");
     663           4 :     if (hRasterPyramidsLyr == nullptr)
     664             :     {
     665             :         osSQL.Printf("CREATE TABLE raster_pyramids ("
     666             :                      "table_prefix TEXT NOT NULL,"
     667             :                      "pixel_x_size DOUBLE NOT NULL,"
     668             :                      "pixel_y_size DOUBLE NOT NULL,"
     669           2 :                      "tile_count INTEGER NOT NULL)");
     670           2 :         OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
     671             : 
     672             :         /* Re-open the DB to take into account the new tables*/
     673           2 :         OGRReleaseDataSource(hDS);
     674             : 
     675           2 :         hDS = RasterliteOpenSQLiteDB(osFileName.c_str(), GA_Update);
     676             : 
     677           2 :         hRasterPyramidsLyr = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
     678           2 :         if (hRasterPyramidsLyr == nullptr)
     679           0 :             return CE_Failure;
     680             :     }
     681           4 :     OGRFeatureDefnH hFDefn = OGR_L_GetLayerDefn(hRasterPyramidsLyr);
     682             : 
     683             :     /* Insert base resolution into raster_pyramids if not already done */
     684           4 :     bool bHasBaseResolution = false;
     685             :     osSQL.Printf(
     686             :         "SELECT * FROM raster_pyramids WHERE "
     687             :         "table_prefix = '%s' AND %s",
     688             :         osTableName.c_str(),
     689           8 :         RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0])
     690           4 :             .c_str());
     691           4 :     hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
     692           4 :     if (hSQLLyr)
     693             :     {
     694           4 :         OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr);
     695           4 :         if (hFeat)
     696             :         {
     697           2 :             bHasBaseResolution = true;
     698           2 :             OGR_F_Destroy(hFeat);
     699             :         }
     700           4 :         OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
     701             :     }
     702             : 
     703           4 :     if (!bHasBaseResolution)
     704             :     {
     705             :         osSQL.Printf(
     706             :             "SELECT COUNT(*) FROM \"%s\" WHERE %s", osMetatadataLayer.c_str(),
     707           4 :             RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0])
     708           2 :                 .c_str());
     709             : 
     710           2 :         int nBlocksMainRes = 0;
     711             : 
     712           2 :         hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
     713           2 :         if (hSQLLyr)
     714             :         {
     715           2 :             OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr);
     716           2 :             if (hFeat)
     717             :             {
     718           2 :                 nBlocksMainRes = OGR_F_GetFieldAsInteger(hFeat, 0);
     719           2 :                 OGR_F_Destroy(hFeat);
     720             :             }
     721           2 :             OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
     722             :         }
     723             : 
     724           2 :         OGRFeatureH hFeat = OGR_F_Create(hFDefn);
     725           2 :         OGR_F_SetFieldString(hFeat,
     726             :                              OGR_FD_GetFieldIndex(hFDefn, "table_prefix"),
     727             :                              osTableName.c_str());
     728           2 :         OGR_F_SetFieldDouble(hFeat,
     729             :                              OGR_FD_GetFieldIndex(hFDefn, "pixel_x_size"),
     730           2 :                              padfXResolutions[0]);
     731           2 :         OGR_F_SetFieldDouble(hFeat,
     732             :                              OGR_FD_GetFieldIndex(hFDefn, "pixel_y_size"),
     733           2 :                              padfYResolutions[0]);
     734           2 :         OGR_F_SetFieldInteger(hFeat, OGR_FD_GetFieldIndex(hFDefn, "tile_count"),
     735             :                               nBlocksMainRes);
     736           2 :         if (OGR_L_CreateFeature(hRasterPyramidsLyr, hFeat) != OGRERR_NONE)
     737           0 :             eErr = CE_Failure;
     738           2 :         OGR_F_Destroy(hFeat);
     739             :     }
     740             : 
     741           4 :     OGRFeatureH hFeat = OGR_F_Create(hFDefn);
     742           4 :     OGR_F_SetFieldString(hFeat, OGR_FD_GetFieldIndex(hFDefn, "table_prefix"),
     743             :                          osTableName.c_str());
     744           4 :     OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_x_size"),
     745             :                          dfXResolution);
     746           4 :     OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_y_size"),
     747             :                          dfYResolution);
     748           4 :     OGR_F_SetFieldInteger(hFeat, OGR_FD_GetFieldIndex(hFDefn, "tile_count"),
     749             :                           nTotalBlocks);
     750           4 :     if (OGR_L_CreateFeature(hRasterPyramidsLyr, hFeat) != OGRERR_NONE)
     751           0 :         eErr = CE_Failure;
     752           4 :     OGR_F_Destroy(hFeat);
     753             : 
     754           4 :     return eErr;
     755             : }
     756             : 
     757             : /************************************************************************/
     758             : /*                          IBuildOverviews()                           */
     759             : /************************************************************************/
     760             : 
     761           3 : CPLErr RasterliteDataset::IBuildOverviews(
     762             :     const char *pszResampling, int nOverviews, const int *panOverviewList,
     763             :     int nBandsIn, const int *panBandList, GDALProgressFunc pfnProgress,
     764             :     void *pProgressData, CSLConstList papszOptions)
     765             : {
     766           3 :     if (nLevel != 0)
     767             :     {
     768           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     769             :                  "Overviews can only be computed on the base dataset");
     770           0 :         return CE_Failure;
     771             :     }
     772             : 
     773           3 :     if (osTableName.empty())
     774           0 :         return CE_Failure;
     775             : 
     776             :     /* -------------------------------------------------------------------- */
     777             :     /*      If we don't have read access, then create the overviews         */
     778             :     /*      externally.                                                     */
     779             :     /* -------------------------------------------------------------------- */
     780           3 :     if (GetAccess() != GA_Update)
     781             :     {
     782           0 :         CPLDebug("Rasterlite", "File open for read-only accessing, "
     783             :                                "creating overviews externally.");
     784             : 
     785           0 :         if (nResolutions != 1)
     786             :         {
     787           0 :             CPLError(CE_Failure, CPLE_NotSupported,
     788             :                      "Cannot add external overviews to a "
     789             :                      "dataset with internal overviews");
     790           0 :             return CE_Failure;
     791             :         }
     792             : 
     793           0 :         bCheckForExistingOverview = FALSE;
     794           0 :         CPLErr eErr = GDALDataset::IBuildOverviews(
     795             :             pszResampling, nOverviews, panOverviewList, nBandsIn, panBandList,
     796             :             pfnProgress, pProgressData, papszOptions);
     797           0 :         bCheckForExistingOverview = TRUE;
     798           0 :         return eErr;
     799             :     }
     800             : 
     801             :     /* -------------------------------------------------------------------- */
     802             :     /*      If zero overviews were requested, we need to clear all          */
     803             :     /*      existing overviews.                                             */
     804             :     /* -------------------------------------------------------------------- */
     805           3 :     if (nOverviews == 0)
     806             :     {
     807           1 :         return CleanOverviews();
     808             :     }
     809             : 
     810           2 :     if (nBandsIn != GetRasterCount())
     811             :     {
     812           0 :         CPLError(CE_Failure, CPLE_NotSupported,
     813             :                  "Generation of overviews in RASTERLITE only"
     814             :                  " supported when operating on all bands.\n"
     815             :                  "Operation failed.\n");
     816           0 :         return CE_Failure;
     817             :     }
     818             : 
     819             :     const char *pszOvrOptions =
     820           2 :         CPLGetConfigOption("RASTERLITE_OVR_OPTIONS", nullptr);
     821             :     const CPLStringList aosCreationOptions(
     822           2 :         pszOvrOptions ? CSLTokenizeString2(pszOvrOptions, ",", 0) : nullptr);
     823           2 :     GDALValidateCreationOptions(GetDriver(), aosCreationOptions.List());
     824             : 
     825           2 :     CPLErr eErr = CE_None;
     826           6 :     for (int i = 0; i < nOverviews && eErr == CE_None; i++)
     827             :     {
     828           4 :         if (panOverviewList[i] <= 1)
     829           0 :             continue;
     830             : 
     831           4 :         eErr = CleanOverviewLevel(panOverviewList[i]);
     832           4 :         if (eErr == CE_None)
     833           4 :             eErr = CreateOverviewLevel(pszResampling, panOverviewList[i],
     834             :                                        aosCreationOptions.List(), pfnProgress,
     835             :                                        pProgressData);
     836             : 
     837           4 :         ReloadOverviews();
     838             :     }
     839             : 
     840           2 :     return eErr;
     841             : }

Generated by: LCOV version 1.14