LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/sqlite - rasterlite2.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 5 18 27.8 %
Date: 2025-07-09 17:50:03 Functions: 2 5 40.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  Implements RasterLite2 support class.
       5             :  * Author:   Even Rouault <even.rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  *
       9             :  * CREDITS: The RasterLite2 module has been completely funded by:
      10             :  * Regione Toscana - Settore Sistema Informativo Territoriale ed
      11             :  * Ambientale (GDAL/RasterLite2 driver)
      12             :  * CIG: 644544015A
      13             :  *
      14             :  ******************************************************************************
      15             :  * Copyright (c) 2016, Even Rouault <even.rouault at spatialys.com>
      16             :  *
      17             :  * SPDX-License-Identifier: MIT
      18             :  ****************************************************************************/
      19             : 
      20             : #include "cpl_port.h"
      21             : #include "ogr_sqlite.h"
      22             : #include "ogrsqliteutility.h"
      23             : #include "rasterlite2_header.h"
      24             : 
      25             : #include <cstring>
      26             : #include <algorithm>
      27             : 
      28             : #include "cpl_error.h"
      29             : #include "cpl_string.h"
      30             : 
      31             : #ifdef HAVE_RASTERLITE2
      32             : 
      33             : static CPLString EscapeNameAndQuoteIfNeeded(const char *pszName)
      34             : {
      35             :     if (strchr(pszName, '"') == nullptr && strchr(pszName, ':') == nullptr)
      36             :         return pszName;
      37             :     return '"' + SQLEscapeName(pszName) + '"';
      38             : }
      39             : 
      40             : #endif
      41             : 
      42             : /************************************************************************/
      43             : /*                            OpenRaster()                              */
      44             : /************************************************************************/
      45             : 
      46           3 : bool OGRSQLiteDataSource::OpenRaster()
      47             : {
      48             : #ifdef HAVE_RASTERLITE2
      49             :     /* -------------------------------------------------------------------- */
      50             :     /*      Detect RasterLite2 coverages.                                   */
      51             :     /* -------------------------------------------------------------------- */
      52             :     char **papszResults = nullptr;
      53             :     int nRowCount = 0, nColCount = 0;
      54             :     int rc = sqlite3_get_table(hDB,
      55             :                                "SELECT name FROM sqlite_master WHERE "
      56             :                                "type = 'table' AND name = 'raster_coverages'",
      57             :                                &papszResults, &nRowCount, &nColCount, nullptr);
      58             :     sqlite3_free_table(papszResults);
      59             :     if (!(rc == SQLITE_OK && nRowCount == 1))
      60             :     {
      61             :         return false;
      62             :     }
      63             : 
      64             :     papszResults = nullptr;
      65             :     nRowCount = 0;
      66             :     nColCount = 0;
      67             :     rc = sqlite3_get_table(hDB,
      68             :                            "SELECT coverage_name, title, abstract "
      69             :                            "FROM raster_coverages "
      70             :                            "LIMIT 10000",
      71             :                            &papszResults, &nRowCount, &nColCount, nullptr);
      72             :     if (!(rc == SQLITE_OK && nRowCount > 0))
      73             :     {
      74             :         sqlite3_free_table(papszResults);
      75             :         return false;
      76             :     }
      77             :     for (int i = 0; i < nRowCount; ++i)
      78             :     {
      79             :         const char *const *papszRow = papszResults + i * 3 + 3;
      80             :         const char *pszCoverageName = papszRow[0];
      81             :         const char *pszTitle = papszRow[1];
      82             :         const char *pszAbstract = papszRow[2];
      83             :         if (pszCoverageName != nullptr)
      84             :         {
      85             :             rl2CoveragePtr cvg =
      86             :                 rl2_create_coverage_from_dbms(hDB, nullptr, pszCoverageName);
      87             :             if (cvg != nullptr)
      88             :             {
      89             :                 const int nIdx = m_aosSubDatasets.size() / 2 + 1;
      90             :                 m_aosSubDatasets.AddNameValue(
      91             :                     CPLSPrintf("SUBDATASET_%d_NAME", nIdx),
      92             :                     CPLSPrintf(
      93             :                         "RASTERLITE2:%s:%s",
      94             :                         EscapeNameAndQuoteIfNeeded(m_pszFilename).c_str(),
      95             :                         EscapeNameAndQuoteIfNeeded(pszCoverageName).c_str()));
      96             :                 CPLString osDesc("Coverage ");
      97             :                 osDesc += pszCoverageName;
      98             :                 if (pszTitle != nullptr && pszTitle[0] != '\0' &&
      99             :                     !EQUAL(pszTitle, "*** missing Title ***"))
     100             :                 {
     101             :                     osDesc += ", title = ";
     102             :                     osDesc += pszTitle;
     103             :                 }
     104             :                 if (pszAbstract != nullptr && pszAbstract[0] != '\0' &&
     105             :                     !EQUAL(pszAbstract, "*** missing Abstract ***"))
     106             :                 {
     107             :                     osDesc += ", abstract = ";
     108             :                     osDesc += pszAbstract;
     109             :                 }
     110             :                 m_aosSubDatasets.AddNameValue(
     111             :                     CPLSPrintf("SUBDATASET_%d_DESC", nIdx), osDesc.c_str());
     112             : 
     113             :                 rl2_destroy_coverage(cvg);
     114             :             }
     115             :         }
     116             :     }
     117             :     sqlite3_free_table(papszResults);
     118             : 
     119             :     if (m_aosSubDatasets.size() == 2)
     120             :     {
     121             :         const char *pszSubDSName =
     122             :             m_aosSubDatasets.FetchNameValue("SUBDATASET_1_NAME");
     123             :         if (pszSubDSName)
     124             :         {
     125             :             return OpenRasterSubDataset(pszSubDSName);
     126             :         }
     127             :     }
     128             : 
     129             :     return !m_aosSubDatasets.empty();
     130             : #else
     131           3 :     return false;
     132             : #endif
     133             : }
     134             : 
     135             : /************************************************************************/
     136             : /*                        OpenRasterSubDataset()                        */
     137             : /************************************************************************/
     138             : 
     139           0 : bool OGRSQLiteDataSource::OpenRasterSubDataset(
     140             :     CPL_UNUSED const char *pszConnectionId)
     141             : {
     142             : #ifdef HAVE_RASTERLITE2
     143             :     if (!STARTS_WITH_CI(pszConnectionId, "RASTERLITE2:"))
     144             :         return false;
     145             : 
     146             :     char **papszTokens =
     147             :         CSLTokenizeString2(pszConnectionId, ":", CSLT_HONOURSTRINGS);
     148             :     if (CSLCount(papszTokens) < 3)
     149             :     {
     150             :         CSLDestroy(papszTokens);
     151             :         return false;
     152             :     }
     153             : 
     154             :     m_aosSubDatasets.Clear();
     155             : 
     156             :     m_osCoverageName = SQLUnescape(papszTokens[2]);
     157             :     m_nSectionId =
     158             :         (CSLCount(papszTokens) >= 4) ? CPLAtoGIntBig(papszTokens[3]) : -1;
     159             : 
     160             :     CSLDestroy(papszTokens);
     161             : 
     162             :     m_pRL2Coverage =
     163             :         rl2_create_coverage_from_dbms(hDB, nullptr, m_osCoverageName);
     164             :     if (m_pRL2Coverage == nullptr)
     165             :     {
     166             :         CPLError(CE_Failure, CPLE_AppDefined, "Invalid coverage: %s",
     167             :                  m_osCoverageName.c_str());
     168             :         return false;
     169             :     }
     170             : 
     171             :     bool bSingleSection = false;
     172             :     if (m_nSectionId < 0)
     173             :     {
     174             :         CPLString osSectionTableName(
     175             :             CPLSPrintf("%s_sections", m_osCoverageName.c_str()));
     176             :         int nRowCount2 = 0;
     177             :         int nColCount2 = 0;
     178             :         char **papszResults2 = nullptr;
     179             :         char *pszSQL =
     180             :             sqlite3_mprintf("SELECT section_id, section_name FROM \"%w\" "
     181             :                             "ORDER BY section_id "
     182             :                             "LIMIT 1000000",
     183             :                             osSectionTableName.c_str());
     184             :         int rc = sqlite3_get_table(hDB, pszSQL, &papszResults2, &nRowCount2,
     185             :                                    &nColCount2, nullptr);
     186             :         sqlite3_free(pszSQL);
     187             :         if (rc == SQLITE_OK)
     188             :         {
     189             :             for (int j = 0; j < nRowCount2; ++j)
     190             :             {
     191             :                 const char *const *papszRow2 = papszResults2 + j * 2 + 2;
     192             :                 const char *pszSectionId = papszRow2[0];
     193             :                 const char *pszSectionName = papszRow2[1];
     194             :                 if (pszSectionName != nullptr && pszSectionId != nullptr)
     195             :                 {
     196             :                     if (nRowCount2 > 1)
     197             :                     {
     198             :                         const int nIdx = m_aosSubDatasets.size() / 2 + 1;
     199             :                         m_aosSubDatasets.AddNameValue(
     200             :                             CPLSPrintf("SUBDATASET_%d_NAME", nIdx),
     201             :                             CPLSPrintf(
     202             :                                 "RASTERLITE2:%s:%s:%s:%s",
     203             :                                 EscapeNameAndQuoteIfNeeded(m_pszFilename)
     204             :                                     .c_str(),
     205             :                                 EscapeNameAndQuoteIfNeeded(m_osCoverageName)
     206             :                                     .c_str(),
     207             :                                 pszSectionId,
     208             :                                 EscapeNameAndQuoteIfNeeded(pszSectionName)
     209             :                                     .c_str()));
     210             :                         m_aosSubDatasets.AddNameValue(
     211             :                             CPLSPrintf("SUBDATASET_%d_DESC", nIdx),
     212             :                             CPLSPrintf("Coverage %s, section %s / %s",
     213             :                                        m_osCoverageName.c_str(), pszSectionName,
     214             :                                        pszSectionId));
     215             :                     }
     216             :                     else
     217             :                     {
     218             :                         m_nSectionId = CPLAtoGIntBig(pszSectionId);
     219             :                         bSingleSection = true;
     220             :                     }
     221             :                 }
     222             :             }
     223             :         }
     224             :         sqlite3_free_table(papszResults2);
     225             :     }
     226             : 
     227             :     double dfXRes = 0.0;
     228             :     double dfYRes = 0.0;
     229             : 
     230             :     double dfMinX = 0.0;
     231             :     double dfMinY = 0.0;
     232             :     double dfMaxX = 0.0;
     233             :     double dfMaxY = 0.0;
     234             :     unsigned int nWidth = 0;
     235             :     unsigned int nHeight = 0;
     236             : 
     237             :     // Get extent and resolution
     238             :     if (m_nSectionId >= 0)
     239             :     {
     240             :         int ret = rl2_resolve_base_resolution_from_dbms(
     241             :             hDB, nullptr, m_osCoverageName,
     242             :             TRUE,  // by_section
     243             :             m_nSectionId, &dfXRes, &dfYRes);
     244             :         if (ret != RL2_OK)
     245             :         {
     246             :             CPLError(CE_Failure, CPLE_AppDefined,
     247             :                      "rl2_resolve_base_resolution_from_dbms() failed / "
     248             :                      "Invalid section: " CPL_FRMT_GIB,
     249             :                      m_nSectionId);
     250             :             return false;
     251             :         }
     252             : 
     253             :         ret = rl2_resolve_full_section_from_dbms(
     254             :             hDB, nullptr, m_osCoverageName, m_nSectionId, dfXRes, dfYRes,
     255             :             &dfMinX, &dfMinY, &dfMaxX, &dfMaxY, &nWidth, &nHeight);
     256             :         if (ret != RL2_OK || nWidth == 0 || nWidth > INT_MAX || nHeight == 0 ||
     257             :             nHeight > INT_MAX)
     258             :         {
     259             :             CPLError(CE_Failure, CPLE_AppDefined,
     260             :                      "rl2_resolve_full_section_from_dbms() failed / "
     261             :                      "Invalid section: " CPL_FRMT_GIB,
     262             :                      m_nSectionId);
     263             :             return false;
     264             :         }
     265             :     }
     266             :     else
     267             :     {
     268             :         rl2_get_coverage_resolution(m_pRL2Coverage, &dfXRes, &dfYRes);
     269             : 
     270             :         char *pszSQL = sqlite3_mprintf(
     271             :             "SELECT extent_minx, extent_miny, extent_maxx, extent_maxy "
     272             :             "FROM raster_coverages WHERE "
     273             :             "Lower(coverage_name) = Lower('%q') "
     274             :             "LIMIT 1",
     275             :             m_osCoverageName.c_str());
     276             :         char **papszResults = nullptr;
     277             :         int nRowCount = 0;
     278             :         int nColCount = 0;
     279             :         int rc = sqlite3_get_table(hDB, pszSQL, &papszResults, &nRowCount,
     280             :                                    &nColCount, nullptr);
     281             :         sqlite3_free(pszSQL);
     282             :         if (rc == SQLITE_OK)
     283             :         {
     284             :             if (nRowCount == 1)
     285             :             {
     286             :                 const char *pszMinX = papszResults[4 + 0];
     287             :                 const char *pszMinY = papszResults[4 + 1];
     288             :                 const char *pszMaxX = papszResults[4 + 2];
     289             :                 const char *pszMaxY = papszResults[4 + 3];
     290             :                 if (pszMinX != nullptr && pszMinY != nullptr &&
     291             :                     pszMaxX != nullptr && pszMaxY != nullptr)
     292             :                 {
     293             :                     dfMinX = CPLAtof(pszMinX);
     294             :                     dfMinY = CPLAtof(pszMinY);
     295             :                     dfMaxX = CPLAtof(pszMaxX);
     296             :                     dfMaxY = CPLAtof(pszMaxY);
     297             :                 }
     298             :             }
     299             :             sqlite3_free_table(papszResults);
     300             :         }
     301             :         double dfWidth = 0.5 + (dfMaxX - dfMinX) / dfXRes;
     302             :         double dfHeight = 0.5 + (dfMaxY - dfMinY) / dfYRes;
     303             :         if (dfWidth <= 0.5 || dfHeight <= 0.5 || dfWidth > INT_MAX ||
     304             :             dfHeight > INT_MAX)
     305             :         {
     306             :             CPLError(CE_Failure, CPLE_AppDefined, "Invalid dimensions");
     307             :             return false;
     308             :         }
     309             :         nWidth = static_cast<int>(dfWidth);
     310             :         nHeight = static_cast<int>(dfHeight);
     311             :     }
     312             : 
     313             :     // Compute dimension and geotransform
     314             :     nRasterXSize = static_cast<int>(nWidth);
     315             :     nRasterYSize = static_cast<int>(nHeight);
     316             :     m_bGeoTransformValid = true;
     317             :     m_gt[0] = dfMinX;
     318             :     m_gt[1] = (dfMaxX - dfMinX) / nRasterXSize;
     319             :     m_gt[2] = 0.0;
     320             :     m_gt[3] = dfMaxY;
     321             :     m_gt[4] = 0.0;
     322             :     m_gt[5] = -(dfMaxY - dfMinY) / nRasterYSize;
     323             : 
     324             :     // Get SRS
     325             :     int nSRID = 0;
     326             :     if (rl2_get_coverage_srid(m_pRL2Coverage, &nSRID) == RL2_OK)
     327             :     {
     328             :         OGRSpatialReference *poSRS = FetchSRS(nSRID);
     329             :         if (poSRS != nullptr)
     330             :         {
     331             :             m_oSRS = *poSRS;
     332             :             m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
     333             :         }
     334             :     }
     335             : 
     336             :     // Get pixel information and number of bands
     337             :     unsigned char nSampleType = 0;
     338             :     unsigned char nPixelType = 0;
     339             :     unsigned char l_nBands = 0;
     340             :     rl2_get_coverage_type(m_pRL2Coverage, &nSampleType, &nPixelType, &l_nBands);
     341             :     if (!GDALCheckBandCount(l_nBands, FALSE))
     342             :         return false;
     343             :     int nBits = 0;
     344             :     GDALDataType eDT = GDT_Unknown;
     345             :     switch (nSampleType)
     346             :     {
     347             :         default:
     348             :         case RL2_SAMPLE_UNKNOWN:
     349             :         {
     350             :             CPLError(CE_Failure, CPLE_AppDefined, "Unknown sample type");
     351             :             return false;
     352             :         }
     353             :         case RL2_SAMPLE_1_BIT:
     354             :         {
     355             :             if (nPixelType == RL2_PIXEL_MONOCHROME)
     356             :             {
     357             :                 m_bPromote1BitAs8Bit =
     358             :                     CPLFetchBool(papszOpenOptions, "1BIT_AS_8BIT", true);
     359             :             }
     360             :             nBits = 1;
     361             :             eDT = GDT_Byte;
     362             :             break;
     363             :         }
     364             :         case RL2_SAMPLE_2_BIT:
     365             :         {
     366             :             nBits = 2;
     367             :             eDT = GDT_Byte;
     368             :             break;
     369             :         }
     370             :         case RL2_SAMPLE_4_BIT:
     371             :         {
     372             :             nBits = 4;
     373             :             eDT = GDT_Byte;
     374             :             break;
     375             :         }
     376             :         case RL2_SAMPLE_INT8:
     377             :         {
     378             :             nBits = 8;
     379             :             eDT = GDT_Int8;
     380             :             break;
     381             :         }
     382             :         case RL2_SAMPLE_UINT8:
     383             :         {
     384             :             nBits = 8;
     385             :             eDT = GDT_Byte;
     386             :             break;
     387             :         }
     388             :         case RL2_SAMPLE_INT16:
     389             :         {
     390             :             nBits = 16;
     391             :             eDT = GDT_Int16;
     392             :             break;
     393             :         }
     394             :         case RL2_SAMPLE_UINT16:
     395             :         {
     396             :             nBits = 16;
     397             :             eDT = GDT_UInt16;
     398             :             break;
     399             :         }
     400             :         case RL2_SAMPLE_INT32:
     401             :         {
     402             :             nBits = 32;
     403             :             eDT = GDT_Int32;
     404             :             break;
     405             :         }
     406             :         case RL2_SAMPLE_UINT32:
     407             :         {
     408             :             nBits = 32;
     409             :             eDT = GDT_UInt32;
     410             :             break;
     411             :         }
     412             :         case RL2_SAMPLE_FLOAT:
     413             :         {
     414             :             nBits = 32;
     415             :             eDT = GDT_Float32;
     416             :             break;
     417             :         }
     418             :         case RL2_SAMPLE_DOUBLE:
     419             :         {
     420             :             nBits = 64;
     421             :             eDT = GDT_Float64;
     422             :             break;
     423             :         }
     424             :     }
     425             : 
     426             :     // Get information about compression (informative)
     427             :     unsigned char nCompression = 0;
     428             :     int nQuality = 0;
     429             :     rl2_get_coverage_compression(m_pRL2Coverage, &nCompression, &nQuality);
     430             :     const char *pszCompression = nullptr;
     431             :     switch (nCompression)
     432             :     {
     433             :         case RL2_COMPRESSION_DEFLATE:
     434             :         case RL2_COMPRESSION_DEFLATE_NO:
     435             :             pszCompression = "DEFLATE";
     436             :             break;
     437             :         case RL2_COMPRESSION_LZMA:
     438             :         case RL2_COMPRESSION_LZMA_NO:
     439             :             pszCompression = "LZMA";
     440             :             break;
     441             :         case RL2_COMPRESSION_GIF:
     442             :             pszCompression = "GIF";
     443             :             break;
     444             :         case RL2_COMPRESSION_JPEG:
     445             :             pszCompression = "JPEG";
     446             :             break;
     447             :         case RL2_COMPRESSION_PNG:
     448             :             pszCompression = "PNG";
     449             :             break;
     450             :         case RL2_COMPRESSION_LOSSY_WEBP:
     451             :             pszCompression = "WEBP";
     452             :             break;
     453             :         case RL2_COMPRESSION_LOSSLESS_WEBP:
     454             :             pszCompression = "WEBP_LOSSLESS";
     455             :             break;
     456             :         case RL2_COMPRESSION_CCITTFAX3:
     457             :             pszCompression = "CCITTFAX3";
     458             :             break;
     459             :         case RL2_COMPRESSION_CCITTFAX4:
     460             :             pszCompression = "CCITTFAX4";
     461             :             break;
     462             :         case RL2_COMPRESSION_LZW:
     463             :             pszCompression = "LZW";
     464             :             break;
     465             :         case RL2_COMPRESSION_LOSSY_JP2:
     466             :             pszCompression = "JPEG2000";
     467             :             break;
     468             :         case RL2_COMPRESSION_LOSSLESS_JP2:
     469             :             pszCompression = "JPEG2000_LOSSLESS";
     470             :             break;
     471             :         default:
     472             :             break;
     473             :     }
     474             : 
     475             :     if (pszCompression != nullptr)
     476             :     {
     477             :         GDALDataset::SetMetadataItem("COMPRESSION", pszCompression,
     478             :                                      "IMAGE_STRUCTURE");
     479             :     }
     480             : 
     481             :     if (nQuality != 0 && (nCompression == RL2_COMPRESSION_JPEG ||
     482             :                           nCompression == RL2_COMPRESSION_LOSSY_WEBP ||
     483             :                           nCompression == RL2_COMPRESSION_LOSSY_JP2))
     484             :     {
     485             :         GDALDataset::SetMetadataItem("QUALITY", CPLSPrintf("%d", nQuality),
     486             :                                      "IMAGE_STRUCTURE");
     487             :     }
     488             : 
     489             :     // Get tile dimensions
     490             :     unsigned int nTileWidth = 0;
     491             :     unsigned int nTileHeight = 0;
     492             :     rl2_get_coverage_tile_size(m_pRL2Coverage, &nTileWidth, &nTileHeight);
     493             :     if (nTileWidth == 0 || nTileHeight == 0 || nTileWidth > INT_MAX ||
     494             :         nTileHeight > INT_MAX)
     495             :     {
     496             :         CPLError(CE_Failure, CPLE_AppDefined, "Invalid block size");
     497             :         return false;
     498             :     }
     499             :     const int nBlockXSize = static_cast<int>(nTileWidth);
     500             :     const int nBlockYSize = static_cast<int>(nTileHeight);
     501             : 
     502             :     // Fetch nodata values
     503             :     std::vector<double> adfNoDataValues;
     504             :     rl2PixelPtr noDataPtr = rl2_get_coverage_no_data(m_pRL2Coverage);
     505             :     if (noDataPtr != nullptr)
     506             :     {
     507             :         unsigned char noDataSampleType = 0;
     508             :         unsigned char noDataPixelType = 0;
     509             :         unsigned char noDataBands = 0;
     510             :         if (rl2_get_pixel_type(noDataPtr, &noDataSampleType, &noDataPixelType,
     511             :                                &noDataBands) == RL2_OK &&
     512             :             noDataSampleType == nSampleType && noDataPixelType == nPixelType &&
     513             :             noDataBands == l_nBands)
     514             :         {
     515             :             for (int i = 0; i < l_nBands; ++i)
     516             :             {
     517             :                 double dfNoDataValue = 0.0;
     518             :                 switch (nSampleType)
     519             :                 {
     520             :                     default:
     521             :                     {
     522             :                         break;
     523             :                     }
     524             :                     case RL2_SAMPLE_1_BIT:
     525             :                     {
     526             :                         unsigned char nVal = 0;
     527             :                         rl2_get_pixel_sample_1bit(noDataPtr, &nVal);
     528             :                         dfNoDataValue = nVal;
     529             :                         break;
     530             :                     }
     531             :                     case RL2_SAMPLE_2_BIT:
     532             :                     {
     533             :                         unsigned char nVal = 0;
     534             :                         rl2_get_pixel_sample_2bit(noDataPtr, &nVal);
     535             :                         dfNoDataValue = nVal;
     536             :                         break;
     537             :                     }
     538             :                     case RL2_SAMPLE_4_BIT:
     539             :                     {
     540             :                         unsigned char nVal = 0;
     541             :                         rl2_get_pixel_sample_4bit(noDataPtr, &nVal);
     542             :                         dfNoDataValue = nVal;
     543             :                         break;
     544             :                     }
     545             :                     case RL2_SAMPLE_INT8:
     546             :                     {
     547             :                         char nVal = 0;
     548             :                         rl2_get_pixel_sample_int8(noDataPtr, &nVal);
     549             :                         dfNoDataValue = nVal;
     550             :                         break;
     551             :                     }
     552             :                     case RL2_SAMPLE_UINT8:
     553             :                     {
     554             :                         unsigned char nVal = 0;
     555             :                         rl2_get_pixel_sample_uint8(noDataPtr, i, &nVal);
     556             :                         dfNoDataValue = nVal;
     557             :                         break;
     558             :                     }
     559             :                     case RL2_SAMPLE_INT16:
     560             :                     {
     561             :                         short nVal = 0;
     562             :                         rl2_get_pixel_sample_int16(noDataPtr, &nVal);
     563             :                         dfNoDataValue = nVal;
     564             :                         break;
     565             :                     }
     566             :                     case RL2_SAMPLE_UINT16:
     567             :                     {
     568             :                         unsigned short nVal = 0;
     569             :                         rl2_get_pixel_sample_uint16(noDataPtr, i, &nVal);
     570             :                         dfNoDataValue = nVal;
     571             :                         break;
     572             :                     }
     573             :                     case RL2_SAMPLE_INT32:
     574             :                     {
     575             :                         int nVal = 0;
     576             :                         rl2_get_pixel_sample_int32(noDataPtr, &nVal);
     577             :                         dfNoDataValue = nVal;
     578             :                         break;
     579             :                     }
     580             :                     case RL2_SAMPLE_UINT32:
     581             :                     {
     582             :                         unsigned int nVal = 0;
     583             :                         rl2_get_pixel_sample_uint32(noDataPtr, &nVal);
     584             :                         dfNoDataValue = nVal;
     585             :                         break;
     586             :                     }
     587             :                     case RL2_SAMPLE_FLOAT:
     588             :                     {
     589             :                         float fVal = 0.0f;
     590             :                         rl2_get_pixel_sample_float(noDataPtr, &fVal);
     591             :                         dfNoDataValue = fVal;
     592             :                         break;
     593             :                     }
     594             :                     case RL2_SAMPLE_DOUBLE:
     595             :                     {
     596             :                         double dfVal = 0.0;
     597             :                         rl2_get_pixel_sample_double(noDataPtr, &dfVal);
     598             :                         dfNoDataValue = dfVal;
     599             :                         break;
     600             :                     }
     601             :                 }
     602             : 
     603             :                 adfNoDataValues.push_back(dfNoDataValue);
     604             :             }
     605             :         }
     606             : 
     607             :         // Do not destroy noDataPtr. It belongs to m_pRL2Coverage
     608             :     }
     609             : 
     610             :     // The nodata concept in RasterLite2 is equivalent to the NODATA_VALUES
     611             :     // one of GDAL: the nodata value must be matched simultaneously on all
     612             :     // bands.
     613             :     if (adfNoDataValues.size() == l_nBands && l_nBands > 1)
     614             :     {
     615             :         CPLString osNoDataValues;
     616             :         for (int i = 0; i < l_nBands; i++)
     617             :         {
     618             :             if (!osNoDataValues.empty())
     619             :                 osNoDataValues += " ";
     620             :             osNoDataValues += CPLSPrintf("%g", adfNoDataValues[i]);
     621             :         }
     622             :         GDALDataset::SetMetadataItem("NODATA_VALUES", osNoDataValues.c_str());
     623             :     }
     624             : 
     625             :     for (int iBand = 1; iBand <= l_nBands; ++iBand)
     626             :     {
     627             :         const bool bHasNoData = adfNoDataValues.size() == 1 && l_nBands == 1;
     628             :         const double dfNoDataValue = bHasNoData ? adfNoDataValues[0] : 0.0;
     629             :         SetBand(iBand,
     630             :                 new RL2RasterBand(iBand, nPixelType, eDT, nBits,
     631             :                                   m_bPromote1BitAs8Bit, nBlockXSize,
     632             :                                   nBlockYSize, bHasNoData, dfNoDataValue));
     633             :     }
     634             : 
     635             :     // Fetch statistics
     636             :     if (m_nSectionId < 0 || bSingleSection)
     637             :     {
     638             :         rl2RasterStatisticsPtr pStatistics =
     639             :             rl2_create_raster_statistics_from_dbms(hDB, nullptr,
     640             :                                                    m_osCoverageName);
     641             :         if (pStatistics != nullptr)
     642             :         {
     643             :             for (int iBand = 1; iBand <= l_nBands; ++iBand)
     644             :             {
     645             :                 GDALRasterBand *poBand = GetRasterBand(iBand);
     646             :                 double dfMin = 0.0;
     647             :                 double dfMax = 0.0;
     648             :                 double dfMean = 0.0;
     649             :                 double dfVariance = 0.0;
     650             :                 double dfStdDev = 0.0;
     651             :                 if (!(nBits == 1 && m_bPromote1BitAs8Bit) &&
     652             :                     rl2_get_band_statistics(
     653             :                         pStatistics, static_cast<unsigned char>(iBand - 1),
     654             :                         &dfMin, &dfMax, &dfMean, &dfVariance,
     655             :                         &dfStdDev) == RL2_OK)
     656             :                 {
     657             :                     poBand->GDALRasterBand::SetMetadataItem(
     658             :                         "STATISTICS_MINIMUM", CPLSPrintf("%.16g", dfMin));
     659             :                     poBand->GDALRasterBand::SetMetadataItem(
     660             :                         "STATISTICS_MAXIMUM", CPLSPrintf("%.16g", dfMax));
     661             :                     poBand->GDALRasterBand::SetMetadataItem(
     662             :                         "STATISTICS_MEAN", CPLSPrintf("%.16g", dfMean));
     663             :                     poBand->GDALRasterBand::SetMetadataItem(
     664             :                         "STATISTICS_STDDEV", CPLSPrintf("%.16g", dfStdDev));
     665             :                 }
     666             :             }
     667             :             rl2_destroy_raster_statistics(pStatistics);
     668             :         }
     669             :     }
     670             : 
     671             :     // Fetch other metadata
     672             :     char *pszSQL =
     673             :         sqlite3_mprintf("SELECT title, abstract FROM raster_coverages WHERE "
     674             :                         "Lower(coverage_name) = Lower('%q') LIMIT 1",
     675             :                         m_osCoverageName.c_str());
     676             :     char **papszResults = nullptr;
     677             :     int nRowCount = 0;
     678             :     int nColCount = 0;
     679             :     int rc = sqlite3_get_table(hDB, pszSQL, &papszResults, &nRowCount,
     680             :                                &nColCount, nullptr);
     681             :     sqlite3_free(pszSQL);
     682             :     if (rc == SQLITE_OK)
     683             :     {
     684             :         if (nRowCount == 1)
     685             :         {
     686             :             const char *pszTitle = papszResults[2 + 0];
     687             :             const char *pszAbstract = papszResults[2 + 1];
     688             :             if (pszTitle != nullptr && pszTitle[0] != '\0' &&
     689             :                 !EQUAL(pszTitle, "*** missing Title ***"))
     690             :             {
     691             :                 GDALDataset::SetMetadataItem("COVERAGE_TITLE", pszTitle);
     692             :             }
     693             :             if (pszAbstract != nullptr && pszAbstract[0] != '\0' &&
     694             :                 !EQUAL(pszAbstract, "*** missing Abstract ***"))
     695             :             {
     696             :                 GDALDataset::SetMetadataItem("COVERAGE_ABSTRACT", pszAbstract);
     697             :             }
     698             :         }
     699             :         sqlite3_free_table(papszResults);
     700             :     }
     701             : 
     702             :     if (m_nSectionId >= 0)
     703             :     {
     704             :         papszResults = nullptr;
     705             :         nRowCount = 0;
     706             :         nColCount = 0;
     707             :         pszSQL =
     708             :             sqlite3_mprintf("SELECT summary FROM \"%w\" WHERE "
     709             :                             "section_id = %d LIMIT 1",
     710             :                             CPLSPrintf("%s_sections", m_osCoverageName.c_str()),
     711             :                             static_cast<int>(m_nSectionId));
     712             :         rc = sqlite3_get_table(hDB, pszSQL, &papszResults, &nRowCount,
     713             :                                &nColCount, nullptr);
     714             :         sqlite3_free(pszSQL);
     715             :         if (rc == SQLITE_OK)
     716             :         {
     717             :             if (nRowCount == 1)
     718             :             {
     719             :                 const char *pszSummary = papszResults[1 + 0];
     720             :                 if (pszSummary != nullptr && pszSummary[0] != '\0')
     721             :                 {
     722             :                     GDALDataset::SetMetadataItem("SECTION_SUMMARY", pszSummary);
     723             :                 }
     724             :             }
     725             :             sqlite3_free_table(papszResults);
     726             :         }
     727             :     }
     728             : 
     729             :     // Instantiate overviews
     730             :     int nStrictResolution = 0;
     731             :     int nMixedResolutions = 0;
     732             :     int nSectionPaths = 0;
     733             :     int nSectionMD5 = 0;
     734             :     int nSectionSummary = 0;
     735             :     rl2_get_coverage_policies(m_pRL2Coverage, &nStrictResolution,
     736             :                               &nMixedResolutions, &nSectionPaths, &nSectionMD5,
     737             :                               &nSectionSummary);
     738             :     m_bRL2MixedResolutions = CPL_TO_BOOL(nMixedResolutions);
     739             : 
     740             :     ListOverviews();
     741             : 
     742             :     return true;
     743             : #else   // !defined(HAVE_RASTERLITE2)
     744           0 :     return false;
     745             : #endif  // HAVE_RASTERLITE2
     746             : }
     747             : 
     748             : #ifdef HAVE_RASTERLITE2
     749             : 
     750             : /************************************************************************/
     751             : /*                          ListOverviews()                             */
     752             : /************************************************************************/
     753             : 
     754             : void OGRSQLiteDataSource::ListOverviews()
     755             : {
     756             :     if (!m_bRL2MixedResolutions || m_nSectionId >= 0)
     757             :     {
     758             :         char *pszSQL;
     759             :         if (!m_bRL2MixedResolutions)
     760             :         {
     761             :             pszSQL = sqlite3_mprintf(
     762             :                 "SELECT x_resolution_1_1, y_resolution_1_1, "
     763             :                 "x_resolution_1_2, y_resolution_1_2, "
     764             :                 "x_resolution_1_4, y_resolution_1_4,"
     765             :                 "x_resolution_1_8, y_resolution_1_8 "
     766             :                 "FROM \"%w\" ORDER BY pyramid_level "
     767             :                 "LIMIT 1000",
     768             :                 CPLSPrintf("%s_levels", m_osCoverageName.c_str()));
     769             :         }
     770             :         else
     771             :         {
     772             :             pszSQL = sqlite3_mprintf(
     773             :                 "SELECT x_resolution_1_1, y_resolution_1_1, "
     774             :                 "x_resolution_1_2, y_resolution_1_2, "
     775             :                 "x_resolution_1_4, y_resolution_1_4,"
     776             :                 "x_resolution_1_8, y_resolution_1_8 "
     777             :                 "FROM \"%w\" WHERE section_id = %d "
     778             :                 "ORDER BY pyramid_level "
     779             :                 "LIMIT 1000",
     780             :                 CPLSPrintf("%s_section_levels", m_osCoverageName.c_str()),
     781             :                 static_cast<int>(m_nSectionId));
     782             :         }
     783             :         char **papszResults = nullptr;
     784             :         int nRowCount = 0;
     785             :         int nColCount = 0;
     786             :         char *pszErrMsg = nullptr;
     787             :         int rc = sqlite3_get_table(hDB, pszSQL, &papszResults, &nRowCount,
     788             :                                    &nColCount, &pszErrMsg);
     789             :         sqlite3_free(pszSQL);
     790             :         if (pszErrMsg)
     791             :             CPLDebug("SQLite", "%s", pszErrMsg);
     792             :         sqlite3_free(pszErrMsg);
     793             :         if (rc == SQLITE_OK)
     794             :         {
     795             :             for (int i = 0; i < nRowCount; ++i)
     796             :             {
     797             :                 const char *const *papszRow = papszResults + i * 8 + 8;
     798             :                 const char *pszXRes1 = papszRow[0];
     799             :                 const char *pszYRes1 = papszRow[1];
     800             :                 const char *pszXRes2 = papszRow[2];
     801             :                 const char *pszYRes2 = papszRow[3];
     802             :                 const char *pszXRes4 = papszRow[4];
     803             :                 const char *pszYRes4 = papszRow[5];
     804             :                 const char *pszXRes8 = papszRow[6];
     805             :                 const char *pszYRes8 = papszRow[7];
     806             :                 if (pszXRes1 != nullptr && pszYRes1 != nullptr)
     807             :                 {
     808             :                     CreateRL2OverviewDatasetIfNeeded(CPLAtof(pszXRes1),
     809             :                                                      CPLAtof(pszYRes1));
     810             :                 }
     811             :                 if (pszXRes2 != nullptr && pszYRes2 != nullptr)
     812             :                 {
     813             :                     CreateRL2OverviewDatasetIfNeeded(CPLAtof(pszXRes2),
     814             :                                                      CPLAtof(pszYRes2));
     815             :                 }
     816             :                 if (pszXRes4 != nullptr && pszYRes4 != nullptr)
     817             :                 {
     818             :                     CreateRL2OverviewDatasetIfNeeded(CPLAtof(pszXRes4),
     819             :                                                      CPLAtof(pszYRes4));
     820             :                 }
     821             :                 if (pszXRes8 != nullptr && pszYRes8 != nullptr)
     822             :                 {
     823             :                     CreateRL2OverviewDatasetIfNeeded(CPLAtof(pszXRes8),
     824             :                                                      CPLAtof(pszYRes8));
     825             :                 }
     826             :             }
     827             :             sqlite3_free_table(papszResults);
     828             :         }
     829             :     }
     830             : }
     831             : 
     832             : /************************************************************************/
     833             : /*                    CreateRL2OverviewDatasetIfNeeded()                   */
     834             : /************************************************************************/
     835             : 
     836             : void OGRSQLiteDataSource::CreateRL2OverviewDatasetIfNeeded(double dfXRes,
     837             :                                                            double dfYRes)
     838             : {
     839             :     if (fabs(dfXRes - m_gt[1]) < 1e-5 * m_gt[1])
     840             :         return;
     841             : 
     842             :     for (size_t i = 0; i < m_apoOverviewDS.size(); ++i)
     843             :     {
     844             :         if (fabs(dfXRes - m_apoOverviewDS[i]->m_gt[1]) <
     845             :             1e-5 * m_apoOverviewDS[i]->m_gt[1])
     846             :         {
     847             :             return;
     848             :         }
     849             :     }
     850             : 
     851             :     OGRSQLiteDataSource *poOvrDS = new OGRSQLiteDataSource();
     852             :     poOvrDS->bIsInternal = true;
     853             :     poOvrDS->m_poParentDS = this;
     854             :     poOvrDS->m_osCoverageName = m_osCoverageName;
     855             :     poOvrDS->m_nSectionId = m_nSectionId;
     856             :     poOvrDS->m_bPromote1BitAs8Bit = m_bPromote1BitAs8Bit;
     857             :     poOvrDS->m_bRL2MixedResolutions = m_bRL2MixedResolutions;
     858             :     poOvrDS->m_gt[0] = m_gt[0];
     859             :     poOvrDS->m_gt[1] = dfXRes;
     860             :     poOvrDS->m_gt[3] = m_gt[3];
     861             :     poOvrDS->m_gt[5] = -dfYRes;
     862             :     const double dfMinX = m_gt[0];
     863             :     const double dfMaxX = dfMinX + m_gt[1] * nRasterXSize;
     864             :     const double dfMaxY = m_gt[3];
     865             :     const double dfMinY = dfMaxY + m_gt[5] * nRasterYSize;
     866             :     poOvrDS->nRasterXSize = static_cast<int>(0.5 + (dfMaxX - dfMinX) / dfXRes);
     867             :     poOvrDS->nRasterYSize = static_cast<int>(0.5 + (dfMaxY - dfMinY) / dfYRes);
     868             :     if (poOvrDS->nRasterXSize <= 1 || poOvrDS->nRasterYSize <= 1 ||
     869             :         (poOvrDS->nRasterXSize < 64 && poOvrDS->nRasterYSize < 64 &&
     870             :          !CPLTestBool(CPLGetConfigOption("RL2_SHOW_ALL_PYRAMID_LEVELS", "NO"))))
     871             :     {
     872             :         delete poOvrDS;
     873             :         return;
     874             :     }
     875             :     for (int iBand = 1; iBand <= nBands; ++iBand)
     876             :     {
     877             :         poOvrDS->SetBand(iBand,
     878             :                          new RL2RasterBand(reinterpret_cast<RL2RasterBand *>(
     879             :                              GetRasterBand(iBand))));
     880             :     }
     881             :     m_apoOverviewDS.push_back(poOvrDS);
     882             : }
     883             : 
     884             : /************************************************************************/
     885             : /*                            RL2RasterBand()                           */
     886             : /************************************************************************/
     887             : 
     888             : RL2RasterBand::RL2RasterBand(int nBandIn, int nPixelType, GDALDataType eDT,
     889             :                              int nBits, bool bPromote1BitAs8Bit,
     890             :                              int nBlockXSizeIn, int nBlockYSizeIn,
     891             :                              bool bHasNoDataIn, double dfNoDataValueIn)
     892             :     : m_bHasNoData(bHasNoDataIn), m_dfNoDataValue(dfNoDataValueIn),
     893             :       m_eColorInterp(GCI_Undefined), m_poCT(nullptr)
     894             : {
     895             :     eDataType = eDT;
     896             :     nBlockXSize = nBlockXSizeIn;
     897             :     nBlockYSize = nBlockYSizeIn;
     898             :     if ((nBits % 8) != 0)
     899             :     {
     900             :         GDALRasterBand::SetMetadataItem(
     901             :             (nBits == 1 && bPromote1BitAs8Bit) ? "SOURCE_NBITS" : "NBITS",
     902             :             CPLSPrintf("%d", nBits), "IMAGE_STRUCTURE");
     903             :     }
     904             : 
     905             :     if (nPixelType == RL2_PIXEL_MONOCHROME || nPixelType == RL2_PIXEL_GRAYSCALE)
     906             :     {
     907             :         m_eColorInterp = GCI_GrayIndex;
     908             :     }
     909             :     else if (nPixelType == RL2_PIXEL_PALETTE)
     910             :     {
     911             :         m_eColorInterp = GCI_PaletteIndex;
     912             :     }
     913             :     else if (nPixelType == RL2_PIXEL_RGB)
     914             :     {
     915             :         m_eColorInterp =
     916             :             static_cast<GDALColorInterp>(GCI_RedBand + nBandIn - 1);
     917             :     }
     918             : }
     919             : 
     920             : /************************************************************************/
     921             : /*                            RL2RasterBand()                           */
     922             : /************************************************************************/
     923             : 
     924             : RL2RasterBand::RL2RasterBand(const RL2RasterBand *poOther)
     925             : {
     926             :     eDataType = poOther->eDataType;
     927             :     nBlockXSize = poOther->nBlockXSize;
     928             :     nBlockYSize = poOther->nBlockYSize;
     929             :     GDALRasterBand::SetMetadataItem(
     930             :         "NBITS",
     931             :         const_cast<RL2RasterBand *>(poOther)->GetMetadataItem(
     932             :             "NBITS", "IMAGE_STRUCTURE"),
     933             :         "IMAGE_STRUCTURE");
     934             :     m_eColorInterp = poOther->m_eColorInterp;
     935             :     m_bHasNoData = poOther->m_bHasNoData;
     936             :     m_dfNoDataValue = poOther->m_dfNoDataValue;
     937             :     m_poCT = nullptr;
     938             : }
     939             : 
     940             : /************************************************************************/
     941             : /*                           ~RL2RasterBand()                           */
     942             : /************************************************************************/
     943             : 
     944             : RL2RasterBand::~RL2RasterBand()
     945             : {
     946             :     delete m_poCT;
     947             : }
     948             : 
     949             : /************************************************************************/
     950             : /*                          GetColorTable()                             */
     951             : /************************************************************************/
     952             : 
     953             : GDALColorTable *RL2RasterBand::GetColorTable()
     954             : {
     955             :     OGRSQLiteDataSource *poGDS = reinterpret_cast<OGRSQLiteDataSource *>(poDS);
     956             :     if (m_poCT == nullptr && m_eColorInterp == GCI_PaletteIndex)
     957             :     {
     958             :         rl2PalettePtr palettePtr = rl2_get_dbms_palette(
     959             :             poGDS->GetDB(), nullptr,
     960             :             rl2_get_coverage_name(poGDS->GetRL2CoveragePtr()));
     961             :         if (palettePtr)
     962             :         {
     963             :             m_poCT = new GDALColorTable();
     964             :             unsigned short nEntries = 0;
     965             :             unsigned char *pabyR = nullptr;
     966             :             unsigned char *pabyG = nullptr;
     967             :             unsigned char *pabyB = nullptr;
     968             :             if (rl2_get_palette_colors(palettePtr, &nEntries, &pabyR, &pabyG,
     969             :                                        &pabyB) == RL2_OK)
     970             :             {
     971             :                 for (int i = 0; i < nEntries; ++i)
     972             :                 {
     973             :                     GDALColorEntry sEntry;
     974             :                     sEntry.c1 = pabyR[i];
     975             :                     sEntry.c2 = pabyG[i];
     976             :                     sEntry.c3 = pabyB[i];
     977             :                     sEntry.c4 =
     978             :                         (m_bHasNoData && i == m_dfNoDataValue) ? 0 : 255;
     979             :                     m_poCT->SetColorEntry(i, &sEntry);
     980             :                 }
     981             :                 rl2_free(pabyR);
     982             :                 rl2_free(pabyG);
     983             :                 rl2_free(pabyB);
     984             :             }
     985             :             rl2_destroy_palette(palettePtr);
     986             :         }
     987             :     }
     988             :     return m_poCT;
     989             : }
     990             : 
     991             : /************************************************************************/
     992             : /*                          GetOverviewCount()                          */
     993             : /************************************************************************/
     994             : 
     995             : int RL2RasterBand::GetOverviewCount()
     996             : {
     997             :     OGRSQLiteDataSource *poGDS = reinterpret_cast<OGRSQLiteDataSource *>(poDS);
     998             :     int nRet = static_cast<int>(poGDS->GetOverviews().size());
     999             :     if (nRet > 0)
    1000             :         return nRet;
    1001             :     return GDALPamRasterBand::GetOverviewCount();
    1002             : }
    1003             : 
    1004             : /************************************************************************/
    1005             : /*                           GetOverview()                              */
    1006             : /************************************************************************/
    1007             : 
    1008             : GDALRasterBand *RL2RasterBand::GetOverview(int nIdx)
    1009             : {
    1010             :     OGRSQLiteDataSource *poGDS = reinterpret_cast<OGRSQLiteDataSource *>(poDS);
    1011             :     int nOvr = static_cast<int>(poGDS->GetOverviews().size());
    1012             :     if (nOvr > 0)
    1013             :     {
    1014             :         if (nIdx < 0 || nIdx >= nOvr)
    1015             :             return nullptr;
    1016             :         return poGDS->GetOverviews()[nIdx]->GetRasterBand(nBand);
    1017             :     }
    1018             :     return GDALPamRasterBand::GetOverview(nIdx);
    1019             : }
    1020             : 
    1021             : /************************************************************************/
    1022             : /*                          GetNoDataValue()                            */
    1023             : /************************************************************************/
    1024             : 
    1025             : double RL2RasterBand::GetNoDataValue(int *pbSuccess)
    1026             : {
    1027             :     if (m_bHasNoData)
    1028             :     {
    1029             :         if (pbSuccess)
    1030             :             *pbSuccess = TRUE;
    1031             :         return m_dfNoDataValue;
    1032             :     }
    1033             :     return GDALPamRasterBand::GetNoDataValue(pbSuccess);
    1034             : }
    1035             : 
    1036             : /************************************************************************/
    1037             : /*                             IReadBlock()                             */
    1038             : /************************************************************************/
    1039             : 
    1040             : CPLErr RL2RasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pData)
    1041             : {
    1042             :     OGRSQLiteDataSource *poGDS = reinterpret_cast<OGRSQLiteDataSource *>(poDS);
    1043             : #ifdef DEBUG_VERBOSE
    1044             :     CPLDebug("SQLite", "IReadBlock(ds=%p, band=%d, x=%d, y=%d)", poGDS, nBand,
    1045             :              nBlockXOff, nBlockYOff);
    1046             : #endif
    1047             : 
    1048             :     const int nMaxThreads = 1;
    1049             :     const auto &gt = poGDS->GetGeoTransform();
    1050             :     const double dfMinX = gt[0] + nBlockXOff * nBlockXSize * gt[1];
    1051             :     const double dfMaxX = dfMinX + nBlockXSize * gt[1];
    1052             :     const double dfMaxY = gt[3] + nBlockYOff * nBlockYSize * gt[5];
    1053             :     const double dfMinY = dfMaxY + nBlockYSize * gt[5];
    1054             :     unsigned char *pBuffer = nullptr;
    1055             :     int nBufSize = 0;
    1056             : 
    1057             :     sqlite3 *hDB =
    1058             :         poGDS->GetParentDS() ? poGDS->GetParentDS()->GetDB() : poGDS->GetDB();
    1059             :     rl2CoveragePtr cov = poGDS->GetParentDS()
    1060             :                              ? poGDS->GetParentDS()->GetRL2CoveragePtr()
    1061             :                              : poGDS->GetRL2CoveragePtr();
    1062             :     unsigned char nSampleType = 0;
    1063             :     unsigned char nPixelType = 0;
    1064             :     unsigned char l_nBands = 0;
    1065             :     rl2_get_coverage_type(cov, &nSampleType, &nPixelType, &l_nBands);
    1066             : 
    1067             :     unsigned char nOutPixel = nPixelType;
    1068             :     if (nPixelType == RL2_PIXEL_MONOCHROME && nSampleType == RL2_SAMPLE_1_BIT)
    1069             :     {
    1070             :         nOutPixel = RL2_PIXEL_GRAYSCALE;
    1071             :     }
    1072             : 
    1073             :     const GIntBig nSectionId = poGDS->GetSectionId();
    1074             :     if (nSectionId >= 0 &&
    1075             :         (poGDS->IsRL2MixedResolutions() || poGDS->GetParentDS() == nullptr))
    1076             :     {
    1077             :         int ret = rl2_get_section_raw_raster_data(
    1078             :             hDB, nMaxThreads, cov, nSectionId, nBlockXSize, nBlockYSize, dfMinX,
    1079             :             dfMinY, dfMaxX, dfMaxY, gt[1], fabs(gt[5]), &pBuffer, &nBufSize,
    1080             :             nullptr,  // palette
    1081             :             nOutPixel);
    1082             :         if (ret != RL2_OK)
    1083             :             return CE_Failure;
    1084             :     }
    1085             :     else
    1086             :     {
    1087             :         int ret = rl2_get_raw_raster_data(
    1088             :             hDB, nMaxThreads, cov, nBlockXSize, nBlockYSize, dfMinX, dfMinY,
    1089             :             dfMaxX, dfMaxY, gt[1], fabs(gt[5]), &pBuffer, &nBufSize,
    1090             :             nullptr,  // palette
    1091             :             nOutPixel);
    1092             :         if (ret != RL2_OK)
    1093             :             return CE_Failure;
    1094             :     }
    1095             : 
    1096             :     const int nDTSize = GDALGetDataTypeSizeBytes(eDataType);
    1097             :     const int nExpectedBytesOnBand = nBlockXSize * nBlockYSize * nDTSize;
    1098             :     const int nBands = poGDS->GetRasterCount();
    1099             :     const int nExpectedBytesAllBands = nExpectedBytesOnBand * nBands;
    1100             :     if (nBufSize != nExpectedBytesAllBands)
    1101             :     {
    1102             :         CPLDebug("SQLite", "Got %d bytes instead of %d", nBufSize,
    1103             :                  nExpectedBytesAllBands);
    1104             :         rl2_free(pBuffer);
    1105             :         return CE_Failure;
    1106             :     }
    1107             : 
    1108             :     if (nPixelType == RL2_PIXEL_MONOCHROME && nSampleType == RL2_SAMPLE_1_BIT &&
    1109             :         !poGDS->HasPromote1BitAS8Bit() && poGDS->GetParentDS() != nullptr)
    1110             :     {
    1111             :         GByte *pabyDstData = static_cast<GByte *>(pData);
    1112             :         for (int i = 0; i < nExpectedBytesAllBands; i++)
    1113             :         {
    1114             :             pabyDstData[i] = (pBuffer[i] > 127) ? 1 : 0;
    1115             :         }
    1116             :     }
    1117             :     else
    1118             :     {
    1119             :         GDALCopyWords(pBuffer + (nBand - 1) * nDTSize, eDataType,
    1120             :                       nDTSize * nBands, pData, eDataType, nDTSize,
    1121             :                       nBlockXSize * nBlockYSize);
    1122             :     }
    1123             : 
    1124             :     if (nBands > 1)
    1125             :     {
    1126             :         for (int iBand = 1; iBand <= nBands; ++iBand)
    1127             :         {
    1128             :             if (iBand == nBand)
    1129             :                 continue;
    1130             : 
    1131             :             GDALRasterBlock *poBlock =
    1132             :                 reinterpret_cast<RL2RasterBand *>(poGDS->GetRasterBand(iBand))
    1133             :                     ->TryGetLockedBlockRef(nBlockXOff, nBlockYOff);
    1134             :             if (poBlock != nullptr)
    1135             :             {
    1136             :                 poBlock->DropLock();
    1137             :                 continue;
    1138             :             }
    1139             :             poBlock =
    1140             :                 reinterpret_cast<RL2RasterBand *>(poGDS->GetRasterBand(iBand))
    1141             :                     ->GetLockedBlockRef(nBlockXOff, nBlockYOff, TRUE);
    1142             :             if (poBlock == nullptr)
    1143             :                 continue;
    1144             :             void *pDest = poBlock->GetDataRef();
    1145             :             GDALCopyWords(pBuffer + (iBand - 1) * nDTSize, eDataType,
    1146             :                           nDTSize * nBands, pDest, eDataType, nDTSize,
    1147             :                           nBlockXSize * nBlockYSize);
    1148             : 
    1149             :             poBlock->DropLock();
    1150             :         }
    1151             :     }
    1152             : 
    1153             :     rl2_free(pBuffer);
    1154             : 
    1155             :     return CE_None;
    1156             : }
    1157             : 
    1158             : /************************************************************************/
    1159             : /*                          GetNoDataValue()                            */
    1160             : /************************************************************************/
    1161             : 
    1162             : template <class T>
    1163             : static T GetNoDataValue(GDALDataset *poSrcDS, int nBand, T nDefault)
    1164             : {
    1165             :     int bHasNoData = FALSE;
    1166             :     double dfNoData =
    1167             :         poSrcDS->GetRasterBand(nBand)->GetNoDataValue(&bHasNoData);
    1168             :     if (bHasNoData)
    1169             :         return static_cast<T>(dfNoData);
    1170             :     return static_cast<T>(nDefault);
    1171             : }
    1172             : 
    1173             : /************************************************************************/
    1174             : /*                          CreateNoData()                              */
    1175             : /************************************************************************/
    1176             : 
    1177             : static rl2PixelPtr CreateNoData(unsigned char nSampleType,
    1178             :                                 unsigned char nPixelType,
    1179             :                                 unsigned char nBandCount, GDALDataset *poSrcDS)
    1180             : {
    1181             :     // creating a default NO-DATA value
    1182             :     rl2PixelPtr pxl = rl2_create_pixel(nSampleType, nPixelType, nBandCount);
    1183             :     if (pxl == nullptr)
    1184             :         return nullptr;
    1185             :     switch (nPixelType)
    1186             :     {
    1187             :         case RL2_PIXEL_MONOCHROME:
    1188             :             rl2_set_pixel_sample_1bit(pxl,
    1189             :                                       GetNoDataValue<GByte>(poSrcDS, 1, 0));
    1190             :             break;
    1191             :         case RL2_PIXEL_PALETTE:
    1192             :             switch (nSampleType)
    1193             :             {
    1194             :                 case RL2_SAMPLE_1_BIT:
    1195             :                     rl2_set_pixel_sample_1bit(
    1196             :                         pxl, GetNoDataValue<GByte>(poSrcDS, 1, 0));
    1197             :                     break;
    1198             :                 case RL2_SAMPLE_2_BIT:
    1199             :                     rl2_set_pixel_sample_2bit(
    1200             :                         pxl, GetNoDataValue<GByte>(poSrcDS, 1, 0));
    1201             :                     break;
    1202             :                 case RL2_SAMPLE_4_BIT:
    1203             :                     rl2_set_pixel_sample_4bit(
    1204             :                         pxl, GetNoDataValue<GByte>(poSrcDS, 1, 0));
    1205             :                     break;
    1206             :                 case RL2_SAMPLE_UINT8:
    1207             :                     rl2_set_pixel_sample_uint8(
    1208             :                         pxl, 0, GetNoDataValue<GByte>(poSrcDS, 1, 0));
    1209             :                     break;
    1210             :                 default:
    1211             :                     CPLAssert(false);
    1212             :                     break;
    1213             :             }
    1214             :             break;
    1215             :         case RL2_PIXEL_GRAYSCALE:
    1216             :             switch (nSampleType)
    1217             :             {
    1218             :                 case RL2_SAMPLE_1_BIT:
    1219             :                     rl2_set_pixel_sample_1bit(
    1220             :                         pxl, GetNoDataValue<GByte>(poSrcDS, 1, 1));
    1221             :                     break;
    1222             :                 case RL2_SAMPLE_2_BIT:
    1223             :                     rl2_set_pixel_sample_2bit(
    1224             :                         pxl, GetNoDataValue<GByte>(poSrcDS, 1, 3));
    1225             :                     break;
    1226             :                 case RL2_SAMPLE_4_BIT:
    1227             :                     rl2_set_pixel_sample_4bit(
    1228             :                         pxl, GetNoDataValue<GByte>(poSrcDS, 1, 15));
    1229             :                     break;
    1230             :                 case RL2_SAMPLE_UINT8:
    1231             :                     rl2_set_pixel_sample_uint8(
    1232             :                         pxl, 0, GetNoDataValue<GByte>(poSrcDS, 1, 255));
    1233             :                     break;
    1234             :                 case RL2_SAMPLE_UINT16:
    1235             :                     rl2_set_pixel_sample_uint16(
    1236             :                         pxl, 0, GetNoDataValue<GUInt16>(poSrcDS, 1, 0));
    1237             :                     break;
    1238             :                 default:
    1239             :                     CPLAssert(false);
    1240             :                     break;
    1241             :             }
    1242             :             break;
    1243             :         case RL2_PIXEL_RGB:
    1244             :             switch (nSampleType)
    1245             :             {
    1246             :                 case RL2_SAMPLE_UINT8:
    1247             :                     rl2_set_pixel_sample_uint8(
    1248             :                         pxl, 0, GetNoDataValue<GByte>(poSrcDS, 1, 255));
    1249             :                     rl2_set_pixel_sample_uint8(
    1250             :                         pxl, 1, GetNoDataValue<GByte>(poSrcDS, 2, 255));
    1251             :                     rl2_set_pixel_sample_uint8(
    1252             :                         pxl, 2, GetNoDataValue<GByte>(poSrcDS, 3, 255));
    1253             :                     break;
    1254             :                 case RL2_SAMPLE_UINT16:
    1255             :                     rl2_set_pixel_sample_uint16(
    1256             :                         pxl, 0, GetNoDataValue<GUInt16>(poSrcDS, 1, 0));
    1257             :                     rl2_set_pixel_sample_uint16(
    1258             :                         pxl, 1, GetNoDataValue<GUInt16>(poSrcDS, 2, 0));
    1259             :                     rl2_set_pixel_sample_uint16(
    1260             :                         pxl, 2, GetNoDataValue<GUInt16>(poSrcDS, 3, 0));
    1261             :                     break;
    1262             :                 default:
    1263             :                     CPLAssert(false);
    1264             :                     break;
    1265             :             }
    1266             :             break;
    1267             :         case RL2_PIXEL_DATAGRID:
    1268             :             switch (nSampleType)
    1269             :             {
    1270             :                 case RL2_SAMPLE_INT8:
    1271             :                     rl2_set_pixel_sample_int8(
    1272             :                         pxl, GetNoDataValue<char>(poSrcDS, 1, 0));
    1273             :                     break;
    1274             :                 case RL2_SAMPLE_UINT8:
    1275             :                     rl2_set_pixel_sample_uint8(
    1276             :                         pxl, 0, GetNoDataValue<GByte>(poSrcDS, 1, 0));
    1277             :                     break;
    1278             :                 case RL2_SAMPLE_INT16:
    1279             :                     rl2_set_pixel_sample_int16(
    1280             :                         pxl, GetNoDataValue<GInt16>(poSrcDS, 1, 0));
    1281             :                     break;
    1282             :                 case RL2_SAMPLE_UINT16:
    1283             :                     rl2_set_pixel_sample_uint16(
    1284             :                         pxl, 0, GetNoDataValue<GUInt16>(poSrcDS, 1, 0));
    1285             :                     break;
    1286             :                 case RL2_SAMPLE_INT32:
    1287             :                     rl2_set_pixel_sample_int32(
    1288             :                         pxl, GetNoDataValue<GInt32>(poSrcDS, 1, 0));
    1289             :                     break;
    1290             :                 case RL2_SAMPLE_UINT32:
    1291             :                     rl2_set_pixel_sample_uint32(
    1292             :                         pxl, GetNoDataValue<GUInt32>(poSrcDS, 1, 0));
    1293             :                     break;
    1294             :                 case RL2_SAMPLE_FLOAT:
    1295             :                     rl2_set_pixel_sample_float(
    1296             :                         pxl, GetNoDataValue<float>(poSrcDS, 1, 0));
    1297             :                     break;
    1298             :                 case RL2_SAMPLE_DOUBLE:
    1299             :                     rl2_set_pixel_sample_double(
    1300             :                         pxl, GetNoDataValue<double>(poSrcDS, 1, 0));
    1301             :                     break;
    1302             :                 default:
    1303             :                     CPLAssert(false);
    1304             :                     break;
    1305             :             }
    1306             :             break;
    1307             :         case RL2_PIXEL_MULTIBAND:
    1308             :             switch (nSampleType)
    1309             :             {
    1310             :                 case RL2_SAMPLE_UINT8:
    1311             :                     for (unsigned int nb = 0; nb < nBandCount; nb++)
    1312             :                         rl2_set_pixel_sample_uint8(
    1313             :                             pxl, nb,
    1314             :                             GetNoDataValue<GByte>(poSrcDS, nb + 1, 255));
    1315             :                     break;
    1316             :                 case RL2_SAMPLE_UINT16:
    1317             :                     for (unsigned int nb = 0; nb < nBandCount; nb++)
    1318             :                         rl2_set_pixel_sample_uint16(
    1319             :                             pxl, nb,
    1320             :                             GetNoDataValue<GUInt16>(poSrcDS, nb + 1, 0));
    1321             :                     break;
    1322             :                 default:
    1323             :                     CPLAssert(false);
    1324             :                     break;
    1325             :             }
    1326             :             break;
    1327             :         default:
    1328             :             CPLAssert(false);
    1329             :             break;
    1330             :     }
    1331             :     return pxl;
    1332             : }
    1333             : 
    1334             : /************************************************************************/
    1335             : /*                       RasterLite2Callback()                          */
    1336             : /************************************************************************/
    1337             : 
    1338             : struct RasterLite2CallbackData
    1339             : {
    1340             :     GDALDataset *poSrcDS{};
    1341             :     unsigned char nPixelType{};
    1342             :     unsigned char nSampleType{};
    1343             :     rl2PalettePtr pPalette{};
    1344             :     GDALProgressFunc pfnProgress{};
    1345             :     void *pProgressData{};
    1346             :     GDALGeoTransform gt{};
    1347             : };
    1348             : 
    1349             : static int RasterLite2Callback(void *data, double dfTileMinX, double dfTileMinY,
    1350             :                                double dfTileMaxX, double dfTileMaxY,
    1351             :                                unsigned char *pabyBuffer,
    1352             :                                rl2PalettePtr *pOutPalette)
    1353             : {
    1354             : #ifdef DEBUG_VERBOSE
    1355             :     CPLDebug("SQLite", "RasterLite2Callback(%f %f %f %f)", dfTileMinX,
    1356             :              dfTileMinY, dfTileMaxX, dfTileMaxY);
    1357             : #endif
    1358             :     RasterLite2CallbackData *pCbkData =
    1359             :         static_cast<RasterLite2CallbackData *>(data);
    1360             :     if (pOutPalette)
    1361             :     {
    1362             :         if (pCbkData->pPalette)
    1363             :             *pOutPalette = rl2_clone_palette(pCbkData->pPalette);
    1364             :         else
    1365             :             *pOutPalette = nullptr;
    1366             :     }
    1367             :     int nXOff = static_cast<int>(0.5 + (dfTileMinX - pCbkData->gt[0]) /
    1368             :                                            pCbkData->gt[1]);
    1369             :     int nXOff2 = static_cast<int>(0.5 + (dfTileMaxX - pCbkData->gt[0]) /
    1370             :                                             pCbkData->gt[1]);
    1371             :     int nYOff = static_cast<int>(0.5 + (dfTileMaxY - pCbkData->gt[3]) /
    1372             :                                            pCbkData->gt[5]);
    1373             :     int nYOff2 = static_cast<int>(0.5 + (dfTileMinY - pCbkData->gt[3]) /
    1374             :                                             pCbkData->gt[5]);
    1375             :     int nReqXSize = nXOff2 - nXOff;
    1376             :     bool bZeroInitialize = false;
    1377             :     if (nXOff2 > pCbkData->poSrcDS->GetRasterXSize())
    1378             :     {
    1379             :         bZeroInitialize = true;
    1380             :         nReqXSize = pCbkData->poSrcDS->GetRasterXSize() - nXOff;
    1381             :     }
    1382             :     int nReqYSize = nYOff2 - nYOff;
    1383             :     if (nYOff2 > pCbkData->poSrcDS->GetRasterYSize())
    1384             :     {
    1385             :         bZeroInitialize = true;
    1386             :         nReqYSize = pCbkData->poSrcDS->GetRasterYSize() - nYOff;
    1387             :     }
    1388             : 
    1389             :     GDALDataType eDT = pCbkData->poSrcDS->GetRasterBand(1)->GetRasterDataType();
    1390             :     int nDTSize = GDALGetDataTypeSizeBytes(eDT);
    1391             :     int nBands = pCbkData->poSrcDS->GetRasterCount();
    1392             :     if (bZeroInitialize)
    1393             :     {
    1394             :         memset(pabyBuffer, 0,
    1395             :                static_cast<size_t>(nXOff2 - nXOff) * (nYOff2 - nYOff) * nBands *
    1396             :                    nDTSize);
    1397             :     }
    1398             : 
    1399             :     const GSpacing nPixelSpacing = static_cast<GSpacing>(nDTSize) * nBands;
    1400             :     const GSpacing nLineSpacing = nPixelSpacing * (nXOff2 - nXOff);
    1401             :     CPLErr eErr = pCbkData->poSrcDS->RasterIO(
    1402             :         GF_Read, nXOff, nYOff, nReqXSize, nReqYSize, pabyBuffer, nReqXSize,
    1403             :         nReqYSize, eDT, nBands, nullptr, nPixelSpacing, nLineSpacing, nDTSize,
    1404             :         nullptr);
    1405             :     if (eErr != CE_None)
    1406             :         return FALSE;
    1407             : 
    1408             :     if (pCbkData->pfnProgress &&
    1409             :         !pCbkData->pfnProgress(static_cast<double>(nYOff + nReqYSize) /
    1410             :                                    pCbkData->poSrcDS->GetRasterYSize(),
    1411             :                                "", pCbkData->pProgressData))
    1412             :     {
    1413             :         return FALSE;
    1414             :     }
    1415             : 
    1416             :     int nMaxVal = 0;
    1417             :     if (pCbkData->nSampleType == RL2_SAMPLE_1_BIT)
    1418             :     {
    1419             :         nMaxVal = 1;
    1420             :     }
    1421             :     else if (pCbkData->nSampleType == RL2_SAMPLE_2_BIT)
    1422             :     {
    1423             :         nMaxVal = 3;
    1424             :     }
    1425             :     else if (pCbkData->nSampleType == RL2_SAMPLE_4_BIT)
    1426             :     {
    1427             :         nMaxVal = 7;
    1428             :     }
    1429             :     if (nMaxVal != 0)
    1430             :     {
    1431             :         bool bClamped = false;
    1432             :         for (int iY = 0; iY < nReqYSize; ++iY)
    1433             :         {
    1434             :             for (int iX = 0; iX < nReqXSize; ++iX)
    1435             :             {
    1436             :                 GByte *pbyVal = pabyBuffer +
    1437             :                                 static_cast<size_t>(iY) * (nXOff2 - nXOff) + iX;
    1438             :                 if (*pbyVal > nMaxVal)
    1439             :                 {
    1440             :                     if (!bClamped)
    1441             :                     {
    1442             :                         bClamped = true;
    1443             :                         CPLError(CE_Warning, CPLE_AppDefined,
    1444             :                                  "One or several values above %d have "
    1445             :                                  "been clamped",
    1446             :                                  nMaxVal);
    1447             :                     }
    1448             :                     *pbyVal = nMaxVal;
    1449             :                 }
    1450             :             }
    1451             :         }
    1452             :     }
    1453             : 
    1454             :     return TRUE;
    1455             : }
    1456             : 
    1457             : /************************************************************************/
    1458             : /*                    OGRSQLiteDriverCreateCopy()                       */
    1459             : /************************************************************************/
    1460             : 
    1461             : GDALDataset *OGRSQLiteDriverCreateCopy(const char *pszName,
    1462             :                                        GDALDataset *poSrcDS, int /* bStrict */,
    1463             :                                        char **papszOptions,
    1464             :                                        GDALProgressFunc pfnProgress,
    1465             :                                        void *pProgressData)
    1466             : {
    1467             :     if (poSrcDS->GetRasterCount() == 0 || poSrcDS->GetRasterCount() > 255)
    1468             :     {
    1469             :         CPLError(CE_Failure, CPLE_NotSupported, "Unsupported band count");
    1470             :         return nullptr;
    1471             :     }
    1472             : 
    1473             :     GDALGeoTransform gt;
    1474             :     if (poSrcDS->GetGeoTransform(gt) == CE_None &&
    1475             :         (gt[2] != 0.0 || gt[4] != 0.0))
    1476             :     {
    1477             :         CPLError(CE_Failure, CPLE_NotSupported,
    1478             :                  "Raster with rotation/shearing geotransform terms "
    1479             :                  "are not supported");
    1480             :         return nullptr;
    1481             :     }
    1482             : 
    1483             :     if (CSLFetchNameValue(papszOptions, "APPEND_SUBDATASET") &&
    1484             :         !CSLFetchNameValue(papszOptions, "COVERAGE"))
    1485             :     {
    1486             :         CPLError(CE_Failure, CPLE_AppDefined,
    1487             :                  "COVERAGE must be specified with APPEND_SUBDATASET=YES");
    1488             :         return nullptr;
    1489             :     }
    1490             : 
    1491             :     GDALDataType eDT = poSrcDS->GetRasterBand(1)->GetRasterDataType();
    1492             : 
    1493             :     unsigned char nSampleType = RL2_SAMPLE_UINT8;
    1494             :     unsigned char nPixelType = RL2_PIXEL_GRAYSCALE;
    1495             :     unsigned char nBandCount =
    1496             :         static_cast<unsigned char>(poSrcDS->GetRasterCount());
    1497             : 
    1498             :     const char *pszPixelType = CSLFetchNameValue(papszOptions, "PIXEL_TYPE");
    1499             :     if (pszPixelType)
    1500             :     {
    1501             :         if (EQUAL(pszPixelType, "MONOCHROME"))
    1502             :             nPixelType = RL2_PIXEL_MONOCHROME;
    1503             :         else if (EQUAL(pszPixelType, "PALETTE"))
    1504             :             nPixelType = RL2_PIXEL_PALETTE;
    1505             :         else if (EQUAL(pszPixelType, "GRAYSCALE"))
    1506             :             nPixelType = RL2_PIXEL_GRAYSCALE;
    1507             :         else if (EQUAL(pszPixelType, "RGB"))
    1508             :             nPixelType = RL2_PIXEL_RGB;
    1509             :         else if (EQUAL(pszPixelType, "MULTIBAND"))
    1510             :             nPixelType = RL2_PIXEL_MULTIBAND;
    1511             :         else if (EQUAL(pszPixelType, "DATAGRID"))
    1512             :             nPixelType = RL2_PIXEL_DATAGRID;
    1513             :     }
    1514             :     else
    1515             :     {
    1516             :         // Guess a reasonable pixel type from band characteristics
    1517             :         if (nBandCount == 1 &&
    1518             :             poSrcDS->GetRasterBand(1)->GetColorTable() != nullptr)
    1519             :         {
    1520             :             nPixelType = RL2_PIXEL_PALETTE;
    1521             :         }
    1522             :         else if (nBandCount == 3 && (eDT == GDT_Byte || eDT == GDT_UInt16) &&
    1523             :                  poSrcDS->GetRasterBand(1)->GetColorInterpretation() ==
    1524             :                      GCI_RedBand &&
    1525             :                  poSrcDS->GetRasterBand(2)->GetColorInterpretation() ==
    1526             :                      GCI_GreenBand &&
    1527             :                  poSrcDS->GetRasterBand(3)->GetColorInterpretation() ==
    1528             :                      GCI_BlueBand)
    1529             :         {
    1530             :             nPixelType = RL2_PIXEL_RGB;
    1531             :         }
    1532             :         else if (nBandCount > 1 && (eDT == GDT_Byte || eDT == GDT_UInt16))
    1533             :         {
    1534             :             nPixelType = RL2_PIXEL_MULTIBAND;
    1535             :         }
    1536             :         else if (nBandCount == 1 && eDT != GDT_Byte)
    1537             :         {
    1538             :             nPixelType = RL2_PIXEL_DATAGRID;
    1539             :         }
    1540             :     }
    1541             : 
    1542             :     // Deal with NBITS
    1543             :     const char *pszNBITS = CSLFetchNameValue(papszOptions, "NBITS");
    1544             :     int nBITS = 0;
    1545             :     if (pszNBITS != nullptr)
    1546             :     {
    1547             :         nBITS = atoi(pszNBITS);
    1548             :         if (nBITS != 1 && nBITS != 2 && nBITS != 4 && nBITS != 8)
    1549             :         {
    1550             :             CPLError(CE_Failure, CPLE_NotSupported, "Unsupported NBITS value");
    1551             :             return nullptr;
    1552             :         }
    1553             :     }
    1554             :     else
    1555             :     {
    1556             :         pszNBITS = poSrcDS->GetRasterBand(1)->GetMetadataItem(
    1557             :             "NBITS", "IMAGE_STRUCTURE");
    1558             :         if (pszNBITS != nullptr)
    1559             :         {
    1560             :             nBITS = atoi(pszNBITS);
    1561             :         }
    1562             :     }
    1563             : 
    1564             :     if (nBITS > 0 && nBITS <= 8 && eDT != GDT_Byte)
    1565             :     {
    1566             :         CPLError(CE_Failure, CPLE_NotSupported,
    1567             :                  "NBITS <= 8 only compatible with Byte data type");
    1568             :         return nullptr;
    1569             :     }
    1570             : 
    1571             :     if (nBITS == 1)
    1572             :     {
    1573             :         nSampleType = RL2_SAMPLE_1_BIT;
    1574             :         if (nPixelType != RL2_PIXEL_PALETTE && pszPixelType == nullptr)
    1575             :             nPixelType = RL2_PIXEL_MONOCHROME;
    1576             :     }
    1577             :     else if (nBITS == 2)
    1578             :     {
    1579             :         nSampleType = RL2_SAMPLE_2_BIT;
    1580             :         if (nPixelType != RL2_PIXEL_PALETTE && pszPixelType == nullptr)
    1581             :             nPixelType = RL2_PIXEL_GRAYSCALE;
    1582             :     }
    1583             :     else if (nBITS == 4)
    1584             :     {
    1585             :         nSampleType = RL2_SAMPLE_4_BIT;
    1586             :         if (nPixelType != RL2_PIXEL_PALETTE && pszPixelType == nullptr)
    1587             :             nPixelType = RL2_PIXEL_GRAYSCALE;
    1588             :     }
    1589             : 
    1590             :     if (nPixelType == RL2_PIXEL_MONOCHROME)
    1591             :     {
    1592             :         if (eDT != GDT_Byte)
    1593             :         {
    1594             :             CPLError(CE_Failure, CPLE_NotSupported,
    1595             :                      "Incompatible data type for MONOCHROME");
    1596             :             return nullptr;
    1597             :         }
    1598             :         // Force 1 bit
    1599             :         nSampleType = RL2_SAMPLE_1_BIT;
    1600             :     }
    1601             : 
    1602             :     // Guess sample type in other cases
    1603             :     if (eDT == GDT_Int8)
    1604             :         nSampleType = RL2_SAMPLE_INT8;
    1605             :     else if (eDT == GDT_UInt16)
    1606             :         nSampleType = RL2_SAMPLE_UINT16;
    1607             :     else if (eDT == GDT_Int16)
    1608             :         nSampleType = RL2_SAMPLE_INT16;
    1609             :     else if (eDT == GDT_UInt32)
    1610             :         nSampleType = RL2_SAMPLE_UINT32;
    1611             :     else if (eDT == GDT_Int32)
    1612             :         nSampleType = RL2_SAMPLE_INT32;
    1613             :     else if (eDT == GDT_Float32)
    1614             :         nSampleType = RL2_SAMPLE_FLOAT;
    1615             :     else if (eDT == GDT_Float64)
    1616             :         nSampleType = RL2_SAMPLE_DOUBLE;
    1617             :     else if (eDT != GDT_Byte)
    1618             :     {
    1619             :         CPLError(CE_Failure, CPLE_NotSupported, "Unsupported data type");
    1620             :         return nullptr;
    1621             :     }
    1622             : 
    1623             :     unsigned char nCompression = RL2_COMPRESSION_NONE;
    1624             :     int nQuality = 100;
    1625             :     const char *pszCompression = CSLFetchNameValue(papszOptions, "COMPRESS");
    1626             :     if (pszCompression)
    1627             :     {
    1628             :         if (EQUAL(pszCompression, "NONE"))
    1629             :             nCompression = RL2_COMPRESSION_NONE;
    1630             :         else if (EQUAL(pszCompression, "DEFLATE"))
    1631             :             nCompression = RL2_COMPRESSION_DEFLATE;
    1632             :         else if (EQUAL(pszCompression, "LZMA"))
    1633             :             nCompression = RL2_COMPRESSION_LZMA;
    1634             :         else if (EQUAL(pszCompression, "PNG"))
    1635             :             nCompression = RL2_COMPRESSION_PNG;
    1636             :         else if (EQUAL(pszCompression, "CCITTFAX4"))
    1637             :             nCompression = RL2_COMPRESSION_CCITTFAX4;
    1638             :         else if (EQUAL(pszCompression, "JPEG"))
    1639             :         {
    1640             :             nCompression = RL2_COMPRESSION_JPEG;
    1641             :             nQuality = 75;
    1642             :         }
    1643             :         else if (EQUAL(pszCompression, "WEBP"))
    1644             :         {
    1645             :             nCompression = RL2_COMPRESSION_LOSSY_WEBP;
    1646             :             nQuality = 75;
    1647             :         }
    1648             :         else if (EQUAL(pszCompression, "JPEG2000"))
    1649             :         {
    1650             :             nCompression = RL2_COMPRESSION_LOSSY_JP2;
    1651             :             nQuality = 20;
    1652             :         }
    1653             :         else
    1654             :         {
    1655             :             CPLError(CE_Failure, CPLE_NotSupported, "Unsupported compression");
    1656             :             return nullptr;
    1657             :         }
    1658             :         if (!rl2_is_supported_codec(nCompression))
    1659             :         {
    1660             :             CPLError(CE_Failure, CPLE_NotSupported,
    1661             :                      "librasterlite2 is not built with support for "
    1662             :                      "this compression method.");
    1663             :             return nullptr;
    1664             :         }
    1665             :     }
    1666             : 
    1667             :     // Compatibility checks:
    1668             :     // see
    1669             :     // https://www.gaia-gis.it/fossil/librasterlite2/wiki?name=reference_table
    1670             :     if (nPixelType == RL2_PIXEL_MONOCHROME)
    1671             :     {
    1672             :         if (nBandCount != 1)
    1673             :         {
    1674             :             CPLError(CE_Failure, CPLE_NotSupported,
    1675             :                      "Unsupported band count with MONOCHROME");
    1676             :             return nullptr;
    1677             :         }
    1678             :         CPLAssert(nSampleType == RL2_SAMPLE_1_BIT);
    1679             :     }
    1680             :     else if (nPixelType == RL2_PIXEL_PALETTE)
    1681             :     {
    1682             :         if (nBandCount != 1)
    1683             :         {
    1684             :             CPLError(CE_Failure, CPLE_NotSupported,
    1685             :                      "Unsupported band count with PALETTE");
    1686             :             return nullptr;
    1687             :         }
    1688             :         if (nSampleType != RL2_SAMPLE_1_BIT &&
    1689             :             nSampleType != RL2_SAMPLE_2_BIT &&
    1690             :             nSampleType != RL2_SAMPLE_4_BIT && nSampleType != RL2_SAMPLE_UINT8)
    1691             :         {
    1692             :             CPLError(CE_Failure, CPLE_NotSupported,
    1693             :                      "Unsupported sample type with PALETTE");
    1694             :             return nullptr;
    1695             :         }
    1696             :     }
    1697             :     else if (nPixelType == RL2_PIXEL_GRAYSCALE)
    1698             :     {
    1699             :         if (nBandCount != 1)
    1700             :         {
    1701             :             CPLError(CE_Failure, CPLE_NotSupported,
    1702             :                      "Unsupported band count with GRAYSCALE");
    1703             :             return nullptr;
    1704             :         }
    1705             :         if (nSampleType != RL2_SAMPLE_2_BIT &&
    1706             :             nSampleType != RL2_SAMPLE_4_BIT && nSampleType != RL2_SAMPLE_UINT8)
    1707             :         {
    1708             :             CPLError(CE_Failure, CPLE_NotSupported,
    1709             :                      "Unsupported sample type with GRAYSCALE");
    1710             :             return nullptr;
    1711             :         }
    1712             :     }
    1713             :     else if (nPixelType == RL2_PIXEL_RGB)
    1714             :     {
    1715             :         if (nBandCount != 3)
    1716             :         {
    1717             :             CPLError(CE_Failure, CPLE_NotSupported,
    1718             :                      "Unsupported band count with RGB");
    1719             :             return nullptr;
    1720             :         }
    1721             :         if (nSampleType != RL2_SAMPLE_UINT8 && nSampleType != RL2_SAMPLE_UINT16)
    1722             :         {
    1723             :             CPLError(CE_Failure, CPLE_NotSupported,
    1724             :                      "Unsupported sample type with RGB");
    1725             :             return nullptr;
    1726             :         }
    1727             :     }
    1728             :     else if (nPixelType == RL2_PIXEL_MULTIBAND)
    1729             :     {
    1730             :         if (nBandCount == 1)
    1731             :         {
    1732             :             CPLError(CE_Failure, CPLE_NotSupported,
    1733             :                      "Unsupported band count with MULTIBAND");
    1734             :             return nullptr;
    1735             :         }
    1736             :         if (nSampleType != RL2_SAMPLE_UINT8 && nSampleType != RL2_SAMPLE_UINT16)
    1737             :         {
    1738             :             CPLError(CE_Failure, CPLE_NotSupported,
    1739             :                      "Unsupported sample type with MULTIBAND");
    1740             :             return nullptr;
    1741             :         }
    1742             :     }
    1743             :     else if (nPixelType == RL2_PIXEL_DATAGRID)
    1744             :     {
    1745             :         if (nBandCount != 1)
    1746             :         {
    1747             :             CPLError(CE_Failure, CPLE_NotSupported,
    1748             :                      "Unsupported band count with DATAGRID");
    1749             :             return nullptr;
    1750             :         }
    1751             :         if (nSampleType != RL2_SAMPLE_INT8 && nSampleType != RL2_SAMPLE_UINT8 &&
    1752             :             nSampleType != RL2_SAMPLE_INT16 &&
    1753             :             nSampleType != RL2_SAMPLE_UINT16 &&
    1754             :             nSampleType != RL2_SAMPLE_INT32 &&
    1755             :             nSampleType != RL2_SAMPLE_UINT32 &&
    1756             :             nSampleType != RL2_SAMPLE_FLOAT && nSampleType != RL2_SAMPLE_DOUBLE)
    1757             :         {
    1758             :             CPLError(CE_Failure, CPLE_NotSupported,
    1759             :                      "Unsupported sample type with DATAGRID");
    1760             :             return nullptr;
    1761             :         }
    1762             :     }
    1763             : 
    1764             :     // Other compatibility checks based on compression
    1765             :     if (nPixelType == RL2_PIXEL_MONOCHROME)
    1766             :     {
    1767             :         if (nCompression != RL2_COMPRESSION_NONE &&
    1768             :             nCompression != RL2_COMPRESSION_DEFLATE &&
    1769             :             nCompression != RL2_COMPRESSION_DEFLATE_NO &&
    1770             :             nCompression != RL2_COMPRESSION_LZMA &&
    1771             :             nCompression != RL2_COMPRESSION_LZMA_NO &&
    1772             :             nCompression != RL2_COMPRESSION_CCITTFAX4 &&
    1773             :             nCompression != RL2_COMPRESSION_PNG)
    1774             :         {
    1775             :             CPLError(CE_Failure, CPLE_NotSupported,
    1776             :                      "Unsupported compression with MONOCHROME");
    1777             :             return nullptr;
    1778             :         }
    1779             :     }
    1780             :     else if (nPixelType == RL2_PIXEL_PALETTE)
    1781             :     {
    1782             :         if (nCompression != RL2_COMPRESSION_NONE &&
    1783             :             nCompression != RL2_COMPRESSION_DEFLATE &&
    1784             :             nCompression != RL2_COMPRESSION_DEFLATE_NO &&
    1785             :             nCompression != RL2_COMPRESSION_LZMA &&
    1786             :             nCompression != RL2_COMPRESSION_LZMA_NO &&
    1787             :             nCompression != RL2_COMPRESSION_PNG)
    1788             :         {
    1789             :             CPLError(CE_Failure, CPLE_NotSupported,
    1790             :                      "Unsupported compression with PALETTE");
    1791             :             return nullptr;
    1792             :         }
    1793             :     }
    1794             :     else if (nPixelType == RL2_PIXEL_GRAYSCALE)
    1795             :     {
    1796             :         if (nCompression == RL2_COMPRESSION_CCITTFAX4)
    1797             :         {
    1798             :             CPLError(CE_Failure, CPLE_NotSupported,
    1799             :                      "Unsupported compression with GRAYSCALE");
    1800             :             return nullptr;
    1801             :         }
    1802             :     }
    1803             :     else if (nPixelType == RL2_PIXEL_RGB && nSampleType == RL2_SAMPLE_UINT8)
    1804             :     {
    1805             :         if (nCompression == RL2_COMPRESSION_CCITTFAX4)
    1806             :         {
    1807             :             CPLError(CE_Failure, CPLE_NotSupported,
    1808             :                      "Unsupported compression with RGB UINT8");
    1809             :             return nullptr;
    1810             :         }
    1811             :     }
    1812             :     else if (nPixelType == RL2_PIXEL_RGB && nSampleType == RL2_SAMPLE_UINT16)
    1813             :     {
    1814             :         if (nCompression == RL2_COMPRESSION_CCITTFAX4 ||
    1815             :             nCompression == RL2_COMPRESSION_JPEG ||
    1816             :             nCompression == RL2_COMPRESSION_LOSSY_WEBP ||
    1817             :             nCompression == RL2_COMPRESSION_LOSSLESS_WEBP)
    1818             :         {
    1819             :             CPLError(CE_Failure, CPLE_NotSupported,
    1820             :                      "Unsupported compression with RGB UINT16");
    1821             :             return nullptr;
    1822             :         }
    1823             :     }
    1824             :     else if (nPixelType == RL2_PIXEL_MULTIBAND &&
    1825             :              nSampleType == RL2_SAMPLE_UINT8 &&
    1826             :              (nBandCount == 3 || nBandCount == 4))
    1827             :     {
    1828             :         if (nCompression == RL2_COMPRESSION_CCITTFAX4 ||
    1829             :             nCompression == RL2_COMPRESSION_JPEG)
    1830             :         {
    1831             :             CPLError(CE_Failure, CPLE_NotSupported,
    1832             :                      "Unsupported compression with MULTIBAND UINT8 %d bands",
    1833             :                      nBandCount);
    1834             :             return nullptr;
    1835             :         }
    1836             :     }
    1837             :     else if (nPixelType == RL2_PIXEL_MULTIBAND &&
    1838             :              nSampleType == RL2_SAMPLE_UINT16 &&
    1839             :              (nBandCount == 3 || nBandCount == 4))
    1840             :     {
    1841             :         if (nCompression == RL2_COMPRESSION_CCITTFAX4 ||
    1842             :             nCompression == RL2_COMPRESSION_JPEG ||
    1843             :             nCompression == RL2_COMPRESSION_LOSSY_WEBP ||
    1844             :             nCompression == RL2_COMPRESSION_LOSSLESS_WEBP)
    1845             :         {
    1846             :             CPLError(CE_Failure, CPLE_NotSupported,
    1847             :                      "Unsupported compression with MULTIBAND UINT16 %d bands",
    1848             :                      nBandCount);
    1849             :             return nullptr;
    1850             :         }
    1851             :     }
    1852             :     else if (nPixelType == RL2_PIXEL_MULTIBAND)
    1853             :     {
    1854             :         if (nCompression != RL2_COMPRESSION_NONE &&
    1855             :             nCompression != RL2_COMPRESSION_DEFLATE &&
    1856             :             nCompression != RL2_COMPRESSION_DEFLATE_NO &&
    1857             :             nCompression != RL2_COMPRESSION_LZMA &&
    1858             :             nCompression != RL2_COMPRESSION_LZMA_NO)
    1859             :         {
    1860             :             CPLError(CE_Failure, CPLE_NotSupported,
    1861             :                      "Unsupported compression with MULTIBAND %s %d bands",
    1862             :                      (nSampleType == RL2_SAMPLE_UINT8) ? "UINT8" : "UINT16",
    1863             :                      nBandCount);
    1864             :             return nullptr;
    1865             :         }
    1866             :     }
    1867             :     else if (nPixelType == RL2_PIXEL_DATAGRID &&
    1868             :              (nSampleType == RL2_SAMPLE_UINT8 ||
    1869             :               nSampleType == RL2_SAMPLE_UINT16))
    1870             :     {
    1871             :         if (nCompression == RL2_COMPRESSION_CCITTFAX4 ||
    1872             :             nCompression == RL2_COMPRESSION_JPEG ||
    1873             :             nCompression == RL2_COMPRESSION_LOSSY_WEBP ||
    1874             :             nCompression == RL2_COMPRESSION_LOSSLESS_WEBP)
    1875             :         {
    1876             :             CPLError(CE_Failure, CPLE_NotSupported,
    1877             :                      "Unsupported compression with DATAGRID %s",
    1878             :                      (nSampleType == RL2_SAMPLE_UINT8) ? "UINT8" : "UINT16");
    1879             :             return nullptr;
    1880             :         }
    1881             :     }
    1882             :     else if (nPixelType == RL2_PIXEL_DATAGRID &&
    1883             :              nSampleType != RL2_SAMPLE_UINT8 &&
    1884             :              nSampleType != RL2_SAMPLE_UINT16)
    1885             :     {
    1886             :         if (nCompression != RL2_COMPRESSION_NONE &&
    1887             :             nCompression != RL2_COMPRESSION_DEFLATE &&
    1888             :             nCompression != RL2_COMPRESSION_DEFLATE_NO &&
    1889             :             nCompression != RL2_COMPRESSION_LZMA &&
    1890             :             nCompression != RL2_COMPRESSION_LZMA_NO)
    1891             :         {
    1892             :             CPLError(CE_Failure, CPLE_NotSupported,
    1893             :                      "Unsupported compression with DATAGRID %s",
    1894             :                      GDALGetDataTypeName(eDT));
    1895             :             return nullptr;
    1896             :         }
    1897             :     }
    1898             : 
    1899             :     const char *pszQuality = CSLFetchNameValue(papszOptions, "QUALITY");
    1900             :     if (pszQuality)
    1901             :     {
    1902             :         nQuality = atoi(pszQuality);
    1903             :         if (nQuality == 100 && nCompression == RL2_COMPRESSION_LOSSY_JP2)
    1904             :             nCompression = RL2_COMPRESSION_LOSSLESS_JP2;
    1905             :         else if (nQuality == 100 && nCompression == RL2_COMPRESSION_LOSSY_WEBP)
    1906             :             nCompression = RL2_COMPRESSION_LOSSLESS_WEBP;
    1907             :     }
    1908             : 
    1909             :     unsigned int nTileWidth =
    1910             :         atoi(CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", "512"));
    1911             :     unsigned int nTileHeight =
    1912             :         atoi(CSLFetchNameValueDef(papszOptions, "BLOCKYSIZE", "512"));
    1913             : 
    1914             :     /* -------------------------------------------------------------------- */
    1915             :     /*      Try to create datasource.                                       */
    1916             :     /* -------------------------------------------------------------------- */
    1917             :     OGRSQLiteDataSource *poDS = new OGRSQLiteDataSource();
    1918             : 
    1919             :     if (CSLFetchNameValue(papszOptions, "APPEND_SUBDATASET"))
    1920             :     {
    1921             :         GDALOpenInfo oOpenInfo(pszName, GDAL_OF_RASTER | GDAL_OF_VECTOR |
    1922             :                                             GDAL_OF_UPDATE);
    1923             :         if (!poDS->Open(&oOpenInfo))
    1924             :         {
    1925             :             delete poDS;
    1926             :             return nullptr;
    1927             :         }
    1928             :     }
    1929             :     else
    1930             :     {
    1931             :         char **papszNewOptions = CSLDuplicate(papszOptions);
    1932             :         papszNewOptions = CSLSetNameValue(papszNewOptions, "SPATIALITE", "YES");
    1933             :         if (!poDS->Create(pszName, papszNewOptions))
    1934             :         {
    1935             :             CSLDestroy(papszNewOptions);
    1936             :             delete poDS;
    1937             :             return nullptr;
    1938             :         }
    1939             :         CSLDestroy(papszNewOptions);
    1940             :     }
    1941             : 
    1942             :     /* -------------------------------------------------------------------- */
    1943             :     /*      Try to get the SRS Id of this spatial reference system,         */
    1944             :     /*      adding to the srs table if needed.                              */
    1945             :     /* -------------------------------------------------------------------- */
    1946             :     int nSRSId = 0;
    1947             :     const char *pszSRID = CSLFetchNameValue(papszOptions, "SRID");
    1948             : 
    1949             :     if (pszSRID != nullptr)
    1950             :     {
    1951             :         nSRSId = atoi(pszSRID);
    1952             :         if (nSRSId > 0)
    1953             :         {
    1954             :             OGRSpatialReference *poSRSFetched = poDS->FetchSRS(nSRSId);
    1955             :             if (poSRSFetched == nullptr)
    1956             :             {
    1957             :                 CPLError(CE_Warning, CPLE_AppDefined,
    1958             :                          "SRID %d will be used, but no matching SRS is "
    1959             :                          "defined in spatial_ref_sys",
    1960             :                          nSRSId);
    1961             :             }
    1962             :         }
    1963             :     }
    1964             :     else
    1965             :     {
    1966             :         const OGRSpatialReference *poSRS = poSrcDS->GetSpatialRef();
    1967             :         if (poSRS)
    1968             :         {
    1969             :             nSRSId = poDS->FetchSRSId(poSRS);
    1970             :         }
    1971             :     }
    1972             : 
    1973             :     poDS->StartTransaction();
    1974             : 
    1975             :     char **papszResults = nullptr;
    1976             :     int nRowCount = 0;
    1977             :     int nColCount = 0;
    1978             :     sqlite3_get_table(poDS->GetDB(),
    1979             :                       "SELECT * FROM sqlite_master WHERE "
    1980             :                       "name = 'raster_coverages' AND type = 'table'",
    1981             :                       &papszResults, &nRowCount, &nColCount, nullptr);
    1982             :     sqlite3_free_table(papszResults);
    1983             :     if (nRowCount == 0)
    1984             :     {
    1985             :         char *pszErrMsg = nullptr;
    1986             :         int ret =
    1987             :             sqlite3_exec(poDS->GetDB(), "SELECT CreateRasterCoveragesTable()",
    1988             :                          nullptr, nullptr, &pszErrMsg);
    1989             :         if (ret != SQLITE_OK)
    1990             :         {
    1991             :             CPLError(CE_Failure, CPLE_AppDefined,
    1992             :                      "CreateRasterCoveragesTable() failed: %s", pszErrMsg);
    1993             :             sqlite3_free(pszErrMsg);
    1994             :             delete poDS;
    1995             :             return nullptr;
    1996             :         }
    1997             :     }
    1998             : 
    1999             :     const std::string osCoverageName(CSLFetchNameValueDef(
    2000             :         papszOptions, "COVERAGE", CPLGetBasenameSafe(pszName).c_str()));
    2001             :     // Check if the coverage already exists
    2002             :     rl2CoveragePtr cvg = nullptr;
    2003             :     char *pszSQL = sqlite3_mprintf(
    2004             :         "SELECT coverage_name "
    2005             :         "FROM raster_coverages WHERE coverage_name = '%q' LIMIT 1",
    2006             :         osCoverageName.c_str());
    2007             :     sqlite3_get_table(poDS->GetDB(), pszSQL, &papszResults, &nRowCount,
    2008             :                       &nColCount, nullptr);
    2009             :     sqlite3_free(pszSQL);
    2010             :     sqlite3_free_table(papszResults);
    2011             :     if (nRowCount == 1)
    2012             :     {
    2013             :         cvg = rl2_create_coverage_from_dbms(poDS->GetDB(), nullptr,
    2014             :                                             osCoverageName.c_str());
    2015             :         if (cvg == nullptr)
    2016             :         {
    2017             :             delete poDS;
    2018             :             return nullptr;
    2019             :         }
    2020             :     }
    2021             : 
    2022             :     rl2PalettePtr pPalette = nullptr;
    2023             :     if (nPixelType == RL2_PIXEL_PALETTE)
    2024             :     {
    2025             :         GDALColorTable *poCT = poSrcDS->GetRasterBand(1)->GetColorTable();
    2026             :         if (poCT == nullptr)
    2027             :         {
    2028             :             CPLError(CE_Failure, CPLE_AppDefined, "Missing color table");
    2029             :             delete poDS;
    2030             :             return nullptr;
    2031             :         }
    2032             : 
    2033             :         const int nColors = poCT->GetColorEntryCount();
    2034             :         pPalette = rl2_create_palette(nColors);
    2035             :         for (int i = 0; i < nColors; ++i)
    2036             :         {
    2037             :             const GDALColorEntry *poCE = poCT->GetColorEntry(i);
    2038             :             rl2_set_palette_color(pPalette, i, static_cast<GByte>(poCE->c1),
    2039             :                                   static_cast<GByte>(poCE->c2),
    2040             :                                   static_cast<GByte>(poCE->c3));
    2041             :         }
    2042             :     }
    2043             : 
    2044             :     if (cvg == nullptr)
    2045             :     {
    2046             :         const double dfXRes = gt[1];
    2047             :         const double dfYRes = fabs(gt[5]);
    2048             :         const bool bStrictResolution = true;
    2049             :         const bool bMixedResolutions = false;
    2050             :         const bool bSectionPaths = false;
    2051             :         const bool bSectionMD5 = false;
    2052             :         const bool bSectionSummary = false;
    2053             :         const bool bIsQueryable = false;
    2054             : 
    2055             :         rl2PixelPtr pNoData =
    2056             :             CreateNoData(nSampleType, nPixelType, nBandCount, poSrcDS);
    2057             :         if (pNoData == nullptr)
    2058             :         {
    2059             :             delete poDS;
    2060             :             if (pPalette)
    2061             :                 rl2_destroy_palette(pPalette);
    2062             :             return nullptr;
    2063             :         }
    2064             : 
    2065             :         if (rl2_create_dbms_coverage(
    2066             :                 poDS->GetDB(), osCoverageName.c_str(), nSampleType, nPixelType,
    2067             :                 nBandCount, nCompression, nQuality, nTileWidth, nTileHeight,
    2068             :                 nSRSId, dfXRes, dfYRes, pNoData, pPalette, bStrictResolution,
    2069             :                 bMixedResolutions, bSectionPaths, bSectionMD5, bSectionSummary,
    2070             :                 bIsQueryable) != RL2_OK)
    2071             :         {
    2072             :             CPLError(CE_Failure, CPLE_AppDefined,
    2073             :                      "rl2_create_dbms_coverage() failed");
    2074             :             rl2_destroy_pixel(pNoData);
    2075             :             if (pPalette)
    2076             :                 rl2_destroy_palette(pPalette);
    2077             :             delete poDS;
    2078             :             return nullptr;
    2079             :         }
    2080             : 
    2081             :         rl2_destroy_pixel(pNoData);
    2082             :     }
    2083             : 
    2084             :     if (cvg == nullptr)
    2085             :     {
    2086             :         cvg = rl2_create_coverage_from_dbms(poDS->GetDB(), nullptr,
    2087             :                                             osCoverageName.c_str());
    2088             :         if (cvg == nullptr)
    2089             :         {
    2090             :             if (pPalette)
    2091             :                 rl2_destroy_palette(pPalette);
    2092             :             delete poDS;
    2093             :             return nullptr;
    2094             :         }
    2095             :     }
    2096             : 
    2097             :     if (gt[5] > 0)
    2098             :         gt[5] = -gt[5];
    2099             :     double dfXMin = gt[0];
    2100             :     double dfXMax = dfXMin + gt[1] * poSrcDS->GetRasterXSize();
    2101             :     double dfYMax = gt[3];
    2102             :     double dfYMin = dfYMax + gt[5] * poSrcDS->GetRasterYSize();
    2103             : 
    2104             :     CPLString osSectionName(CSLFetchNameValueDef(
    2105             :         papszOptions, "SECTION", CPLGetBasenameSafe(pszName).c_str()));
    2106             :     const bool bPyramidize = CPLFetchBool(papszOptions, "PYRAMIDIZE", false);
    2107             :     RasterLite2CallbackData cbk_data;
    2108             :     cbk_data.poSrcDS = poSrcDS;
    2109             :     cbk_data.nPixelType = nPixelType;
    2110             :     cbk_data.nSampleType = nSampleType;
    2111             :     cbk_data.pPalette = pPalette;
    2112             :     cbk_data.pfnProgress = pfnProgress;
    2113             :     cbk_data.pProgressData = pProgressData;
    2114             :     cbk_data.gt = gt;
    2115             : 
    2116             :     if (rl2_load_raw_tiles_into_dbms(
    2117             :             poDS->GetDB(), poDS->GetRL2Context(), cvg, osSectionName,
    2118             :             poSrcDS->GetRasterXSize(), poSrcDS->GetRasterYSize(), nSRSId,
    2119             :             dfXMin, dfYMin, dfXMax, dfYMax, RasterLite2Callback, &cbk_data,
    2120             :             bPyramidize) != RL2_OK)
    2121             :     {
    2122             :         CPLError(CE_Failure, CPLE_AppDefined,
    2123             :                  "rl2_load_raw_tiles_into_dbms() failed");
    2124             :         delete poDS;
    2125             :         rl2_destroy_coverage(cvg);
    2126             :         if (pPalette)
    2127             :             rl2_destroy_palette(pPalette);
    2128             :         return nullptr;
    2129             :     }
    2130             : 
    2131             :     rl2_destroy_coverage(cvg);
    2132             :     if (pPalette)
    2133             :         rl2_destroy_palette(pPalette);
    2134             : 
    2135             :     poDS->CommitTransaction();
    2136             : 
    2137             :     delete poDS;
    2138             : 
    2139             :     poDS = new OGRSQLiteDataSource();
    2140             :     GDALOpenInfo oOpenInfo(
    2141             :         CPLSPrintf("RASTERLITE2:%s:%s",
    2142             :                    EscapeNameAndQuoteIfNeeded(pszName).c_str(),
    2143             :                    EscapeNameAndQuoteIfNeeded(osCoverageName.c_str()).c_str()),
    2144             :         GDAL_OF_RASTER | GDAL_OF_UPDATE);
    2145             :     poDS->Open(&oOpenInfo);
    2146             :     return poDS;
    2147             : }
    2148             : 
    2149             : /************************************************************************/
    2150             : /*                          IBuildOverviews()                           */
    2151             : /************************************************************************/
    2152             : 
    2153             : CPLErr OGRSQLiteDataSource::IBuildOverviews(
    2154             :     const char *pszResampling, int nOverviews, const int *panOverviewList,
    2155             :     int nBandsIn, const int * /*panBandList */,
    2156             :     GDALProgressFunc /*pfnProgress*/, void * /*pProgressData*/,
    2157             :     CSLConstList /* papszOptions */)
    2158             : 
    2159             : {
    2160             :     if (nBandsIn != nBands)
    2161             :     {
    2162             :         CPLError(CE_Failure, CPLE_AppDefined,
    2163             :                  "Only build of all bands is supported");
    2164             :     }
    2165             : 
    2166             :     if (nOverviews == 0)
    2167             :     {
    2168             :         int ret;
    2169             :         if (m_bRL2MixedResolutions && m_nSectionId >= 0)
    2170             :         {
    2171             :             ret =
    2172             :                 rl2_delete_section_pyramid(hDB, m_osCoverageName, m_nSectionId);
    2173             :         }
    2174             :         else
    2175             :         {
    2176             :             ret = rl2_delete_all_pyramids(hDB, m_osCoverageName);
    2177             :         }
    2178             :         if (ret != RL2_OK)
    2179             :         {
    2180             :             CPLError(CE_Failure, CPLE_AppDefined,
    2181             :                      "Deletion of pyramids failed");
    2182             :             return CE_Failure;
    2183             :         }
    2184             :     }
    2185             :     else
    2186             :     {
    2187             :         if (!STARTS_WITH_CI(pszResampling, "NEAR"))
    2188             :         {
    2189             :             CPLError(CE_Warning, CPLE_AppDefined,
    2190             :                      "Resampling method is ignored. Using librasterlite2 own "
    2191             :                      "method");
    2192             :         }
    2193             :         for (int i = 0; i < nOverviews; ++i)
    2194             :         {
    2195             :             if (!CPLIsPowerOfTwo(panOverviewList[i]))
    2196             :             {
    2197             :                 CPLError(CE_Failure, CPLE_NotSupported,
    2198             :                          "Only power-of-two overview factors are supported");
    2199             :                 return CE_Failure;
    2200             :             }
    2201             :         }
    2202             : 
    2203             :         const int bForcedRebuild = 1;
    2204             :         const int bVerbose = 0;
    2205             :         const int bVirtualLevels = 1;
    2206             :         int ret;
    2207             :         if (m_bRL2MixedResolutions)
    2208             :         {
    2209             :             if (m_nSectionId >= 0)
    2210             :             {
    2211             :                 ret = rl2_build_section_pyramid(hDB, GetRL2Context(),
    2212             :                                                 m_osCoverageName, m_nSectionId,
    2213             :                                                 bForcedRebuild, bVerbose);
    2214             :             }
    2215             :             else
    2216             :             {
    2217             :                 ret = rl2_build_monolithic_pyramid(hDB, GetRL2Context(),
    2218             :                                                    m_osCoverageName,
    2219             :                                                    bVirtualLevels, bVerbose);
    2220             :             }
    2221             :         }
    2222             :         else
    2223             :         {
    2224             :             ret = rl2_build_monolithic_pyramid(hDB, GetRL2Context(),
    2225             :                                                m_osCoverageName, bVirtualLevels,
    2226             :                                                bVerbose);
    2227             :         }
    2228             :         if (ret != RL2_OK)
    2229             :         {
    2230             :             CPLError(CE_Failure, CPLE_AppDefined, "Build of pyramids failed");
    2231             :             return CE_Failure;
    2232             :         }
    2233             :     }
    2234             : 
    2235             :     for (size_t i = 0; i < m_apoOverviewDS.size(); ++i)
    2236             :         delete m_apoOverviewDS[i];
    2237             :     m_apoOverviewDS.clear();
    2238             :     ListOverviews();
    2239             : 
    2240             :     return CE_None;
    2241             : }
    2242             : 
    2243             : #endif  // HAVE_RASTERLITE2
    2244             : 
    2245             : /************************************************************************/
    2246             : /*                             GetMetadata()                            */
    2247             : /************************************************************************/
    2248             : 
    2249           5 : char **OGRSQLiteDataSource::GetMetadata(const char *pszDomain)
    2250             : {
    2251           5 :     if (pszDomain != nullptr && EQUAL(pszDomain, "SUBDATASETS") &&
    2252           0 :         m_aosSubDatasets.size() > 2)
    2253             :     {
    2254           0 :         return m_aosSubDatasets.List();
    2255             :     }
    2256           5 :     return GDALPamDataset::GetMetadata(pszDomain);
    2257             : }
    2258             : 
    2259             : /************************************************************************/
    2260             : /*                           GetGeoTransform()                          */
    2261             : /************************************************************************/
    2262             : 
    2263           0 : CPLErr OGRSQLiteDataSource::GetGeoTransform(GDALGeoTransform &gt) const
    2264             : {
    2265           0 :     if (m_bGeoTransformValid)
    2266             :     {
    2267           0 :         gt = m_gt;
    2268           0 :         return CE_None;
    2269             :     }
    2270           0 :     return GDALPamDataset::GetGeoTransform(gt);
    2271             : }
    2272             : 
    2273             : /************************************************************************/
    2274             : /*                            GetSpatialRef()                           */
    2275             : /************************************************************************/
    2276             : 
    2277           0 : const OGRSpatialReference *OGRSQLiteDataSource::GetSpatialRef() const
    2278             : {
    2279           0 :     if (!m_oSRS.IsEmpty())
    2280           0 :         return &m_oSRS;
    2281           0 :     return GDALPamDataset::GetSpatialRef();
    2282             : }

Generated by: LCOV version 1.14