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

Generated by: LCOV version 1.14