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: 2024-11-25 13:07:18 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_adfGeoTransform[0] = dfMinX;
     318             :     m_adfGeoTransform[1] = (dfMaxX - dfMinX) / nRasterXSize;
     319             :     m_adfGeoTransform[2] = 0.0;
     320             :     m_adfGeoTransform[3] = dfMaxY;
     321             :     m_adfGeoTransform[4] = 0.0;
     322             :     m_adfGeoTransform[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_adfGeoTransform[1]) < 1e-5 * m_adfGeoTransform[1])
     840             :         return;
     841             : 
     842             :     for (size_t i = 0; i < m_apoOverviewDS.size(); ++i)
     843             :     {
     844             :         if (fabs(dfXRes - m_apoOverviewDS[i]->m_adfGeoTransform[1]) <
     845             :             1e-5 * m_apoOverviewDS[i]->m_adfGeoTransform[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_adfGeoTransform[0] = m_adfGeoTransform[0];
     859             :     poOvrDS->m_adfGeoTransform[1] = dfXRes;
     860             :     poOvrDS->m_adfGeoTransform[3] = m_adfGeoTransform[3];
     861             :     poOvrDS->m_adfGeoTransform[5] = -dfYRes;
     862             :     const double dfMinX = m_adfGeoTransform[0];
     863             :     const double dfMaxX = dfMinX + m_adfGeoTransform[1] * nRasterXSize;
     864             :     const double dfMaxY = m_adfGeoTransform[3];
     865             :     const double dfMinY = dfMaxY + m_adfGeoTransform[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 double *padfGeoTransform = poGDS->GetGeoTransform();
    1050             :     const double dfMinX =
    1051             :         padfGeoTransform[0] + nBlockXOff * nBlockXSize * padfGeoTransform[1];
    1052             :     const double dfMaxX = dfMinX + nBlockXSize * padfGeoTransform[1];
    1053             :     const double dfMaxY =
    1054             :         padfGeoTransform[3] + nBlockYOff * nBlockYSize * padfGeoTransform[5];
    1055             :     const double dfMinY = dfMaxY + nBlockYSize * padfGeoTransform[5];
    1056             :     unsigned char *pBuffer = nullptr;
    1057             :     int nBufSize = 0;
    1058             : 
    1059             :     sqlite3 *hDB =
    1060             :         poGDS->GetParentDS() ? poGDS->GetParentDS()->GetDB() : poGDS->GetDB();
    1061             :     rl2CoveragePtr cov = poGDS->GetParentDS()
    1062             :                              ? poGDS->GetParentDS()->GetRL2CoveragePtr()
    1063             :                              : poGDS->GetRL2CoveragePtr();
    1064             :     unsigned char nSampleType = 0;
    1065             :     unsigned char nPixelType = 0;
    1066             :     unsigned char l_nBands = 0;
    1067             :     rl2_get_coverage_type(cov, &nSampleType, &nPixelType, &l_nBands);
    1068             : 
    1069             :     unsigned char nOutPixel = nPixelType;
    1070             :     if (nPixelType == RL2_PIXEL_MONOCHROME && nSampleType == RL2_SAMPLE_1_BIT)
    1071             :     {
    1072             :         nOutPixel = RL2_PIXEL_GRAYSCALE;
    1073             :     }
    1074             : 
    1075             :     const GIntBig nSectionId = poGDS->GetSectionId();
    1076             :     if (nSectionId >= 0 &&
    1077             :         (poGDS->IsRL2MixedResolutions() || poGDS->GetParentDS() == nullptr))
    1078             :     {
    1079             :         int ret = rl2_get_section_raw_raster_data(
    1080             :             hDB, nMaxThreads, cov, nSectionId, nBlockXSize, nBlockYSize, dfMinX,
    1081             :             dfMinY, dfMaxX, dfMaxY, padfGeoTransform[1],
    1082             :             fabs(padfGeoTransform[5]), &pBuffer, &nBufSize,
    1083             :             nullptr,  // palette
    1084             :             nOutPixel);
    1085             :         if (ret != RL2_OK)
    1086             :             return CE_Failure;
    1087             :     }
    1088             :     else
    1089             :     {
    1090             :         int ret = rl2_get_raw_raster_data(
    1091             :             hDB, nMaxThreads, cov, nBlockXSize, nBlockYSize, dfMinX, dfMinY,
    1092             :             dfMaxX, dfMaxY, padfGeoTransform[1], fabs(padfGeoTransform[5]),
    1093             :             &pBuffer, &nBufSize,
    1094             :             nullptr,  // palette
    1095             :             nOutPixel);
    1096             :         if (ret != RL2_OK)
    1097             :             return CE_Failure;
    1098             :     }
    1099             : 
    1100             :     const int nDTSize = GDALGetDataTypeSizeBytes(eDataType);
    1101             :     const int nExpectedBytesOnBand = nBlockXSize * nBlockYSize * nDTSize;
    1102             :     const int nBands = poGDS->GetRasterCount();
    1103             :     const int nExpectedBytesAllBands = nExpectedBytesOnBand * nBands;
    1104             :     if (nBufSize != nExpectedBytesAllBands)
    1105             :     {
    1106             :         CPLDebug("SQLite", "Got %d bytes instead of %d", nBufSize,
    1107             :                  nExpectedBytesAllBands);
    1108             :         rl2_free(pBuffer);
    1109             :         return CE_Failure;
    1110             :     }
    1111             : 
    1112             :     if (nPixelType == RL2_PIXEL_MONOCHROME && nSampleType == RL2_SAMPLE_1_BIT &&
    1113             :         !poGDS->HasPromote1BitAS8Bit() && poGDS->GetParentDS() != nullptr)
    1114             :     {
    1115             :         GByte *pabyDstData = static_cast<GByte *>(pData);
    1116             :         for (int i = 0; i < nExpectedBytesAllBands; i++)
    1117             :         {
    1118             :             pabyDstData[i] = (pBuffer[i] > 127) ? 1 : 0;
    1119             :         }
    1120             :     }
    1121             :     else
    1122             :     {
    1123             :         GDALCopyWords(pBuffer + (nBand - 1) * nDTSize, eDataType,
    1124             :                       nDTSize * nBands, pData, eDataType, nDTSize,
    1125             :                       nBlockXSize * nBlockYSize);
    1126             :     }
    1127             : 
    1128             :     if (nBands > 1)
    1129             :     {
    1130             :         for (int iBand = 1; iBand <= nBands; ++iBand)
    1131             :         {
    1132             :             if (iBand == nBand)
    1133             :                 continue;
    1134             : 
    1135             :             GDALRasterBlock *poBlock =
    1136             :                 reinterpret_cast<RL2RasterBand *>(poGDS->GetRasterBand(iBand))
    1137             :                     ->TryGetLockedBlockRef(nBlockXOff, nBlockYOff);
    1138             :             if (poBlock != nullptr)
    1139             :             {
    1140             :                 poBlock->DropLock();
    1141             :                 continue;
    1142             :             }
    1143             :             poBlock =
    1144             :                 reinterpret_cast<RL2RasterBand *>(poGDS->GetRasterBand(iBand))
    1145             :                     ->GetLockedBlockRef(nBlockXOff, nBlockYOff, TRUE);
    1146             :             if (poBlock == nullptr)
    1147             :                 continue;
    1148             :             void *pDest = poBlock->GetDataRef();
    1149             :             GDALCopyWords(pBuffer + (iBand - 1) * nDTSize, eDataType,
    1150             :                           nDTSize * nBands, pDest, eDataType, nDTSize,
    1151             :                           nBlockXSize * nBlockYSize);
    1152             : 
    1153             :             poBlock->DropLock();
    1154             :         }
    1155             :     }
    1156             : 
    1157             :     rl2_free(pBuffer);
    1158             : 
    1159             :     return CE_None;
    1160             : }
    1161             : 
    1162             : /************************************************************************/
    1163             : /*                          GetNoDataValue()                            */
    1164             : /************************************************************************/
    1165             : 
    1166             : template <class T>
    1167             : static T GetNoDataValue(GDALDataset *poSrcDS, int nBand, T nDefault)
    1168             : {
    1169             :     int bHasNoData = FALSE;
    1170             :     double dfNoData =
    1171             :         poSrcDS->GetRasterBand(nBand)->GetNoDataValue(&bHasNoData);
    1172             :     if (bHasNoData)
    1173             :         return static_cast<T>(dfNoData);
    1174             :     return static_cast<T>(nDefault);
    1175             : }
    1176             : 
    1177             : /************************************************************************/
    1178             : /*                          CreateNoData()                              */
    1179             : /************************************************************************/
    1180             : 
    1181             : static rl2PixelPtr CreateNoData(unsigned char nSampleType,
    1182             :                                 unsigned char nPixelType,
    1183             :                                 unsigned char nBandCount, GDALDataset *poSrcDS)
    1184             : {
    1185             :     // creating a default NO-DATA value
    1186             :     rl2PixelPtr pxl = rl2_create_pixel(nSampleType, nPixelType, nBandCount);
    1187             :     if (pxl == nullptr)
    1188             :         return nullptr;
    1189             :     switch (nPixelType)
    1190             :     {
    1191             :         case RL2_PIXEL_MONOCHROME:
    1192             :             rl2_set_pixel_sample_1bit(pxl,
    1193             :                                       GetNoDataValue<GByte>(poSrcDS, 1, 0));
    1194             :             break;
    1195             :         case RL2_PIXEL_PALETTE:
    1196             :             switch (nSampleType)
    1197             :             {
    1198             :                 case RL2_SAMPLE_1_BIT:
    1199             :                     rl2_set_pixel_sample_1bit(
    1200             :                         pxl, GetNoDataValue<GByte>(poSrcDS, 1, 0));
    1201             :                     break;
    1202             :                 case RL2_SAMPLE_2_BIT:
    1203             :                     rl2_set_pixel_sample_2bit(
    1204             :                         pxl, GetNoDataValue<GByte>(poSrcDS, 1, 0));
    1205             :                     break;
    1206             :                 case RL2_SAMPLE_4_BIT:
    1207             :                     rl2_set_pixel_sample_4bit(
    1208             :                         pxl, GetNoDataValue<GByte>(poSrcDS, 1, 0));
    1209             :                     break;
    1210             :                 case RL2_SAMPLE_UINT8:
    1211             :                     rl2_set_pixel_sample_uint8(
    1212             :                         pxl, 0, GetNoDataValue<GByte>(poSrcDS, 1, 0));
    1213             :                     break;
    1214             :                 default:
    1215             :                     CPLAssert(false);
    1216             :                     break;
    1217             :             }
    1218             :             break;
    1219             :         case RL2_PIXEL_GRAYSCALE:
    1220             :             switch (nSampleType)
    1221             :             {
    1222             :                 case RL2_SAMPLE_1_BIT:
    1223             :                     rl2_set_pixel_sample_1bit(
    1224             :                         pxl, GetNoDataValue<GByte>(poSrcDS, 1, 1));
    1225             :                     break;
    1226             :                 case RL2_SAMPLE_2_BIT:
    1227             :                     rl2_set_pixel_sample_2bit(
    1228             :                         pxl, GetNoDataValue<GByte>(poSrcDS, 1, 3));
    1229             :                     break;
    1230             :                 case RL2_SAMPLE_4_BIT:
    1231             :                     rl2_set_pixel_sample_4bit(
    1232             :                         pxl, GetNoDataValue<GByte>(poSrcDS, 1, 15));
    1233             :                     break;
    1234             :                 case RL2_SAMPLE_UINT8:
    1235             :                     rl2_set_pixel_sample_uint8(
    1236             :                         pxl, 0, GetNoDataValue<GByte>(poSrcDS, 1, 255));
    1237             :                     break;
    1238             :                 case RL2_SAMPLE_UINT16:
    1239             :                     rl2_set_pixel_sample_uint16(
    1240             :                         pxl, 0, GetNoDataValue<GUInt16>(poSrcDS, 1, 0));
    1241             :                     break;
    1242             :                 default:
    1243             :                     CPLAssert(false);
    1244             :                     break;
    1245             :             }
    1246             :             break;
    1247             :         case RL2_PIXEL_RGB:
    1248             :             switch (nSampleType)
    1249             :             {
    1250             :                 case RL2_SAMPLE_UINT8:
    1251             :                     rl2_set_pixel_sample_uint8(
    1252             :                         pxl, 0, GetNoDataValue<GByte>(poSrcDS, 1, 255));
    1253             :                     rl2_set_pixel_sample_uint8(
    1254             :                         pxl, 1, GetNoDataValue<GByte>(poSrcDS, 2, 255));
    1255             :                     rl2_set_pixel_sample_uint8(
    1256             :                         pxl, 2, GetNoDataValue<GByte>(poSrcDS, 3, 255));
    1257             :                     break;
    1258             :                 case RL2_SAMPLE_UINT16:
    1259             :                     rl2_set_pixel_sample_uint16(
    1260             :                         pxl, 0, GetNoDataValue<GUInt16>(poSrcDS, 1, 0));
    1261             :                     rl2_set_pixel_sample_uint16(
    1262             :                         pxl, 1, GetNoDataValue<GUInt16>(poSrcDS, 2, 0));
    1263             :                     rl2_set_pixel_sample_uint16(
    1264             :                         pxl, 2, GetNoDataValue<GUInt16>(poSrcDS, 3, 0));
    1265             :                     break;
    1266             :                 default:
    1267             :                     CPLAssert(false);
    1268             :                     break;
    1269             :             }
    1270             :             break;
    1271             :         case RL2_PIXEL_DATAGRID:
    1272             :             switch (nSampleType)
    1273             :             {
    1274             :                 case RL2_SAMPLE_INT8:
    1275             :                     rl2_set_pixel_sample_int8(
    1276             :                         pxl, GetNoDataValue<char>(poSrcDS, 1, 0));
    1277             :                     break;
    1278             :                 case RL2_SAMPLE_UINT8:
    1279             :                     rl2_set_pixel_sample_uint8(
    1280             :                         pxl, 0, GetNoDataValue<GByte>(poSrcDS, 1, 0));
    1281             :                     break;
    1282             :                 case RL2_SAMPLE_INT16:
    1283             :                     rl2_set_pixel_sample_int16(
    1284             :                         pxl, GetNoDataValue<GInt16>(poSrcDS, 1, 0));
    1285             :                     break;
    1286             :                 case RL2_SAMPLE_UINT16:
    1287             :                     rl2_set_pixel_sample_uint16(
    1288             :                         pxl, 0, GetNoDataValue<GUInt16>(poSrcDS, 1, 0));
    1289             :                     break;
    1290             :                 case RL2_SAMPLE_INT32:
    1291             :                     rl2_set_pixel_sample_int32(
    1292             :                         pxl, GetNoDataValue<GInt32>(poSrcDS, 1, 0));
    1293             :                     break;
    1294             :                 case RL2_SAMPLE_UINT32:
    1295             :                     rl2_set_pixel_sample_uint32(
    1296             :                         pxl, GetNoDataValue<GUInt32>(poSrcDS, 1, 0));
    1297             :                     break;
    1298             :                 case RL2_SAMPLE_FLOAT:
    1299             :                     rl2_set_pixel_sample_float(
    1300             :                         pxl, GetNoDataValue<float>(poSrcDS, 1, 0));
    1301             :                     break;
    1302             :                 case RL2_SAMPLE_DOUBLE:
    1303             :                     rl2_set_pixel_sample_double(
    1304             :                         pxl, GetNoDataValue<double>(poSrcDS, 1, 0));
    1305             :                     break;
    1306             :                 default:
    1307             :                     CPLAssert(false);
    1308             :                     break;
    1309             :             }
    1310             :             break;
    1311             :         case RL2_PIXEL_MULTIBAND:
    1312             :             switch (nSampleType)
    1313             :             {
    1314             :                 case RL2_SAMPLE_UINT8:
    1315             :                     for (unsigned int nb = 0; nb < nBandCount; nb++)
    1316             :                         rl2_set_pixel_sample_uint8(
    1317             :                             pxl, nb,
    1318             :                             GetNoDataValue<GByte>(poSrcDS, nb + 1, 255));
    1319             :                     break;
    1320             :                 case RL2_SAMPLE_UINT16:
    1321             :                     for (unsigned int nb = 0; nb < nBandCount; nb++)
    1322             :                         rl2_set_pixel_sample_uint16(
    1323             :                             pxl, nb,
    1324             :                             GetNoDataValue<GUInt16>(poSrcDS, nb + 1, 0));
    1325             :                     break;
    1326             :                 default:
    1327             :                     CPLAssert(false);
    1328             :                     break;
    1329             :             }
    1330             :             break;
    1331             :         default:
    1332             :             CPLAssert(false);
    1333             :             break;
    1334             :     }
    1335             :     return pxl;
    1336             : }
    1337             : 
    1338             : /************************************************************************/
    1339             : /*                       RasterLite2Callback()                          */
    1340             : /************************************************************************/
    1341             : 
    1342             : typedef struct
    1343             : {
    1344             :     GDALDataset *poSrcDS;
    1345             :     unsigned char nPixelType;
    1346             :     unsigned char nSampleType;
    1347             :     rl2PalettePtr pPalette;
    1348             :     GDALProgressFunc pfnProgress;
    1349             :     void *pProgressData;
    1350             :     double adfGeoTransform[6];
    1351             : } RasterLite2CallbackData;
    1352             : 
    1353             : static int RasterLite2Callback(void *data, double dfTileMinX, double dfTileMinY,
    1354             :                                double dfTileMaxX, double dfTileMaxY,
    1355             :                                unsigned char *pabyBuffer,
    1356             :                                rl2PalettePtr *pOutPalette)
    1357             : {
    1358             : #ifdef DEBUG_VERBOSE
    1359             :     CPLDebug("SQLite", "RasterLite2Callback(%f %f %f %f)", dfTileMinX,
    1360             :              dfTileMinY, dfTileMaxX, dfTileMaxY);
    1361             : #endif
    1362             :     RasterLite2CallbackData *pCbkData =
    1363             :         static_cast<RasterLite2CallbackData *>(data);
    1364             :     if (pOutPalette)
    1365             :     {
    1366             :         if (pCbkData->pPalette)
    1367             :             *pOutPalette = rl2_clone_palette(pCbkData->pPalette);
    1368             :         else
    1369             :             *pOutPalette = nullptr;
    1370             :     }
    1371             :     int nXOff =
    1372             :         static_cast<int>(0.5 + (dfTileMinX - pCbkData->adfGeoTransform[0]) /
    1373             :                                    pCbkData->adfGeoTransform[1]);
    1374             :     int nXOff2 =
    1375             :         static_cast<int>(0.5 + (dfTileMaxX - pCbkData->adfGeoTransform[0]) /
    1376             :                                    pCbkData->adfGeoTransform[1]);
    1377             :     int nYOff =
    1378             :         static_cast<int>(0.5 + (dfTileMaxY - pCbkData->adfGeoTransform[3]) /
    1379             :                                    pCbkData->adfGeoTransform[5]);
    1380             :     int nYOff2 =
    1381             :         static_cast<int>(0.5 + (dfTileMinY - pCbkData->adfGeoTransform[3]) /
    1382             :                                    pCbkData->adfGeoTransform[5]);
    1383             :     int nReqXSize = nXOff2 - nXOff;
    1384             :     bool bZeroInitialize = false;
    1385             :     if (nXOff2 > pCbkData->poSrcDS->GetRasterXSize())
    1386             :     {
    1387             :         bZeroInitialize = true;
    1388             :         nReqXSize = pCbkData->poSrcDS->GetRasterXSize() - nXOff;
    1389             :     }
    1390             :     int nReqYSize = nYOff2 - nYOff;
    1391             :     if (nYOff2 > pCbkData->poSrcDS->GetRasterYSize())
    1392             :     {
    1393             :         bZeroInitialize = true;
    1394             :         nReqYSize = pCbkData->poSrcDS->GetRasterYSize() - nYOff;
    1395             :     }
    1396             : 
    1397             :     GDALDataType eDT = pCbkData->poSrcDS->GetRasterBand(1)->GetRasterDataType();
    1398             :     int nDTSize = GDALGetDataTypeSizeBytes(eDT);
    1399             :     int nBands = pCbkData->poSrcDS->GetRasterCount();
    1400             :     if (bZeroInitialize)
    1401             :     {
    1402             :         memset(pabyBuffer, 0,
    1403             :                static_cast<size_t>(nXOff2 - nXOff) * (nYOff2 - nYOff) * nBands *
    1404             :                    nDTSize);
    1405             :     }
    1406             : 
    1407             :     const GSpacing nPixelSpacing = static_cast<GSpacing>(nDTSize) * nBands;
    1408             :     const GSpacing nLineSpacing = nPixelSpacing * (nXOff2 - nXOff);
    1409             :     CPLErr eErr = pCbkData->poSrcDS->RasterIO(
    1410             :         GF_Read, nXOff, nYOff, nReqXSize, nReqYSize, pabyBuffer, nReqXSize,
    1411             :         nReqYSize, eDT, nBands, nullptr, nPixelSpacing, nLineSpacing, nDTSize,
    1412             :         nullptr);
    1413             :     if (eErr != CE_None)
    1414             :         return FALSE;
    1415             : 
    1416             :     if (pCbkData->pfnProgress &&
    1417             :         !pCbkData->pfnProgress(static_cast<double>(nYOff + nReqYSize) /
    1418             :                                    pCbkData->poSrcDS->GetRasterYSize(),
    1419             :                                "", pCbkData->pProgressData))
    1420             :     {
    1421             :         return FALSE;
    1422             :     }
    1423             : 
    1424             :     int nMaxVal = 0;
    1425             :     if (pCbkData->nSampleType == RL2_SAMPLE_1_BIT)
    1426             :     {
    1427             :         nMaxVal = 1;
    1428             :     }
    1429             :     else if (pCbkData->nSampleType == RL2_SAMPLE_2_BIT)
    1430             :     {
    1431             :         nMaxVal = 3;
    1432             :     }
    1433             :     else if (pCbkData->nSampleType == RL2_SAMPLE_4_BIT)
    1434             :     {
    1435             :         nMaxVal = 7;
    1436             :     }
    1437             :     if (nMaxVal != 0)
    1438             :     {
    1439             :         bool bClamped = false;
    1440             :         for (int iY = 0; iY < nReqYSize; ++iY)
    1441             :         {
    1442             :             for (int iX = 0; iX < nReqXSize; ++iX)
    1443             :             {
    1444             :                 GByte *pbyVal = pabyBuffer +
    1445             :                                 static_cast<size_t>(iY) * (nXOff2 - nXOff) + iX;
    1446             :                 if (*pbyVal > nMaxVal)
    1447             :                 {
    1448             :                     if (!bClamped)
    1449             :                     {
    1450             :                         bClamped = true;
    1451             :                         CPLError(CE_Warning, CPLE_AppDefined,
    1452             :                                  "One or several values above %d have "
    1453             :                                  "been clamped",
    1454             :                                  nMaxVal);
    1455             :                     }
    1456             :                     *pbyVal = nMaxVal;
    1457             :                 }
    1458             :             }
    1459             :         }
    1460             :     }
    1461             : 
    1462             :     return TRUE;
    1463             : }
    1464             : 
    1465             : /************************************************************************/
    1466             : /*                    OGRSQLiteDriverCreateCopy()                       */
    1467             : /************************************************************************/
    1468             : 
    1469             : GDALDataset *OGRSQLiteDriverCreateCopy(const char *pszName,
    1470             :                                        GDALDataset *poSrcDS, int /* bStrict */,
    1471             :                                        char **papszOptions,
    1472             :                                        GDALProgressFunc pfnProgress,
    1473             :                                        void *pProgressData)
    1474             : {
    1475             :     if (poSrcDS->GetRasterCount() == 0 || poSrcDS->GetRasterCount() > 255)
    1476             :     {
    1477             :         CPLError(CE_Failure, CPLE_NotSupported, "Unsupported band count");
    1478             :         return nullptr;
    1479             :     }
    1480             : 
    1481             :     double adfGeoTransform[6];
    1482             :     if (poSrcDS->GetGeoTransform(adfGeoTransform) == CE_None &&
    1483             :         (adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0))
    1484             :     {
    1485             :         CPLError(CE_Failure, CPLE_NotSupported,
    1486             :                  "Raster with rotation/shearing geotransform terms "
    1487             :                  "are not supported");
    1488             :         return nullptr;
    1489             :     }
    1490             : 
    1491             :     if (CSLFetchNameValue(papszOptions, "APPEND_SUBDATASET") &&
    1492             :         !CSLFetchNameValue(papszOptions, "COVERAGE"))
    1493             :     {
    1494             :         CPLError(CE_Failure, CPLE_AppDefined,
    1495             :                  "COVERAGE must be specified with APPEND_SUBDATASET=YES");
    1496             :         return nullptr;
    1497             :     }
    1498             : 
    1499             :     GDALDataType eDT = poSrcDS->GetRasterBand(1)->GetRasterDataType();
    1500             : 
    1501             :     unsigned char nSampleType = RL2_SAMPLE_UINT8;
    1502             :     unsigned char nPixelType = RL2_PIXEL_GRAYSCALE;
    1503             :     unsigned char nBandCount =
    1504             :         static_cast<unsigned char>(poSrcDS->GetRasterCount());
    1505             : 
    1506             :     const char *pszPixelType = CSLFetchNameValue(papszOptions, "PIXEL_TYPE");
    1507             :     if (pszPixelType)
    1508             :     {
    1509             :         if (EQUAL(pszPixelType, "MONOCHROME"))
    1510             :             nPixelType = RL2_PIXEL_MONOCHROME;
    1511             :         else if (EQUAL(pszPixelType, "PALETTE"))
    1512             :             nPixelType = RL2_PIXEL_PALETTE;
    1513             :         else if (EQUAL(pszPixelType, "GRAYSCALE"))
    1514             :             nPixelType = RL2_PIXEL_GRAYSCALE;
    1515             :         else if (EQUAL(pszPixelType, "RGB"))
    1516             :             nPixelType = RL2_PIXEL_RGB;
    1517             :         else if (EQUAL(pszPixelType, "MULTIBAND"))
    1518             :             nPixelType = RL2_PIXEL_MULTIBAND;
    1519             :         else if (EQUAL(pszPixelType, "DATAGRID"))
    1520             :             nPixelType = RL2_PIXEL_DATAGRID;
    1521             :     }
    1522             :     else
    1523             :     {
    1524             :         // Guess a reasonable pixel type from band characteristics
    1525             :         if (nBandCount == 1 &&
    1526             :             poSrcDS->GetRasterBand(1)->GetColorTable() != nullptr)
    1527             :         {
    1528             :             nPixelType = RL2_PIXEL_PALETTE;
    1529             :         }
    1530             :         else if (nBandCount == 3 && (eDT == GDT_Byte || eDT == GDT_UInt16) &&
    1531             :                  poSrcDS->GetRasterBand(1)->GetColorInterpretation() ==
    1532             :                      GCI_RedBand &&
    1533             :                  poSrcDS->GetRasterBand(2)->GetColorInterpretation() ==
    1534             :                      GCI_GreenBand &&
    1535             :                  poSrcDS->GetRasterBand(3)->GetColorInterpretation() ==
    1536             :                      GCI_BlueBand)
    1537             :         {
    1538             :             nPixelType = RL2_PIXEL_RGB;
    1539             :         }
    1540             :         else if (nBandCount > 1 && (eDT == GDT_Byte || eDT == GDT_UInt16))
    1541             :         {
    1542             :             nPixelType = RL2_PIXEL_MULTIBAND;
    1543             :         }
    1544             :         else if (nBandCount == 1 && eDT != GDT_Byte)
    1545             :         {
    1546             :             nPixelType = RL2_PIXEL_DATAGRID;
    1547             :         }
    1548             :     }
    1549             : 
    1550             :     // Deal with NBITS
    1551             :     const char *pszNBITS = CSLFetchNameValue(papszOptions, "NBITS");
    1552             :     int nBITS = 0;
    1553             :     if (pszNBITS != nullptr)
    1554             :     {
    1555             :         nBITS = atoi(pszNBITS);
    1556             :         if (nBITS != 1 && nBITS != 2 && nBITS != 4 && nBITS != 8)
    1557             :         {
    1558             :             CPLError(CE_Failure, CPLE_NotSupported, "Unsupported NBITS value");
    1559             :             return nullptr;
    1560             :         }
    1561             :     }
    1562             :     else
    1563             :     {
    1564             :         pszNBITS = poSrcDS->GetRasterBand(1)->GetMetadataItem(
    1565             :             "NBITS", "IMAGE_STRUCTURE");
    1566             :         if (pszNBITS != nullptr)
    1567             :         {
    1568             :             nBITS = atoi(pszNBITS);
    1569             :         }
    1570             :     }
    1571             : 
    1572             :     if (nBITS > 0 && nBITS <= 8 && eDT != GDT_Byte)
    1573             :     {
    1574             :         CPLError(CE_Failure, CPLE_NotSupported,
    1575             :                  "NBITS <= 8 only compatible with Byte data type");
    1576             :         return nullptr;
    1577             :     }
    1578             : 
    1579             :     if (nBITS == 1)
    1580             :     {
    1581             :         nSampleType = RL2_SAMPLE_1_BIT;
    1582             :         if (nPixelType != RL2_PIXEL_PALETTE && pszPixelType == nullptr)
    1583             :             nPixelType = RL2_PIXEL_MONOCHROME;
    1584             :     }
    1585             :     else if (nBITS == 2)
    1586             :     {
    1587             :         nSampleType = RL2_SAMPLE_2_BIT;
    1588             :         if (nPixelType != RL2_PIXEL_PALETTE && pszPixelType == nullptr)
    1589             :             nPixelType = RL2_PIXEL_GRAYSCALE;
    1590             :     }
    1591             :     else if (nBITS == 4)
    1592             :     {
    1593             :         nSampleType = RL2_SAMPLE_4_BIT;
    1594             :         if (nPixelType != RL2_PIXEL_PALETTE && pszPixelType == nullptr)
    1595             :             nPixelType = RL2_PIXEL_GRAYSCALE;
    1596             :     }
    1597             : 
    1598             :     if (nPixelType == RL2_PIXEL_MONOCHROME)
    1599             :     {
    1600             :         if (eDT != GDT_Byte)
    1601             :         {
    1602             :             CPLError(CE_Failure, CPLE_NotSupported,
    1603             :                      "Incompatible data type for MONOCHROME");
    1604             :             return nullptr;
    1605             :         }
    1606             :         // Force 1 bit
    1607             :         nSampleType = RL2_SAMPLE_1_BIT;
    1608             :     }
    1609             : 
    1610             :     // Guess sample type in other cases
    1611             :     if (eDT == GDT_Int8)
    1612             :         nSampleType = RL2_SAMPLE_INT8;
    1613             :     else if (eDT == GDT_UInt16)
    1614             :         nSampleType = RL2_SAMPLE_UINT16;
    1615             :     else if (eDT == GDT_Int16)
    1616             :         nSampleType = RL2_SAMPLE_INT16;
    1617             :     else if (eDT == GDT_UInt32)
    1618             :         nSampleType = RL2_SAMPLE_UINT32;
    1619             :     else if (eDT == GDT_Int32)
    1620             :         nSampleType = RL2_SAMPLE_INT32;
    1621             :     else if (eDT == GDT_Float32)
    1622             :         nSampleType = RL2_SAMPLE_FLOAT;
    1623             :     else if (eDT == GDT_Float64)
    1624             :         nSampleType = RL2_SAMPLE_DOUBLE;
    1625             :     else if (eDT != GDT_Byte)
    1626             :     {
    1627             :         CPLError(CE_Failure, CPLE_NotSupported, "Unsupported data type");
    1628             :         return nullptr;
    1629             :     }
    1630             : 
    1631             :     unsigned char nCompression = RL2_COMPRESSION_NONE;
    1632             :     int nQuality = 100;
    1633             :     const char *pszCompression = CSLFetchNameValue(papszOptions, "COMPRESS");
    1634             :     if (pszCompression)
    1635             :     {
    1636             :         if (EQUAL(pszCompression, "NONE"))
    1637             :             nCompression = RL2_COMPRESSION_NONE;
    1638             :         else if (EQUAL(pszCompression, "DEFLATE"))
    1639             :             nCompression = RL2_COMPRESSION_DEFLATE;
    1640             :         else if (EQUAL(pszCompression, "LZMA"))
    1641             :             nCompression = RL2_COMPRESSION_LZMA;
    1642             :         else if (EQUAL(pszCompression, "PNG"))
    1643             :             nCompression = RL2_COMPRESSION_PNG;
    1644             :         else if (EQUAL(pszCompression, "CCITTFAX4"))
    1645             :             nCompression = RL2_COMPRESSION_CCITTFAX4;
    1646             :         else if (EQUAL(pszCompression, "JPEG"))
    1647             :         {
    1648             :             nCompression = RL2_COMPRESSION_JPEG;
    1649             :             nQuality = 75;
    1650             :         }
    1651             :         else if (EQUAL(pszCompression, "WEBP"))
    1652             :         {
    1653             :             nCompression = RL2_COMPRESSION_LOSSY_WEBP;
    1654             :             nQuality = 75;
    1655             :         }
    1656             :         else if (EQUAL(pszCompression, "JPEG2000"))
    1657             :         {
    1658             :             nCompression = RL2_COMPRESSION_LOSSY_JP2;
    1659             :             nQuality = 20;
    1660             :         }
    1661             :         else
    1662             :         {
    1663             :             CPLError(CE_Failure, CPLE_NotSupported, "Unsupported compression");
    1664             :             return nullptr;
    1665             :         }
    1666             :         if (!rl2_is_supported_codec(nCompression))
    1667             :         {
    1668             :             CPLError(CE_Failure, CPLE_NotSupported,
    1669             :                      "librasterlite2 is not built with support for "
    1670             :                      "this compression method.");
    1671             :             return nullptr;
    1672             :         }
    1673             :     }
    1674             : 
    1675             :     // Compatibility checks:
    1676             :     // see
    1677             :     // https://www.gaia-gis.it/fossil/librasterlite2/wiki?name=reference_table
    1678             :     if (nPixelType == RL2_PIXEL_MONOCHROME)
    1679             :     {
    1680             :         if (nBandCount != 1)
    1681             :         {
    1682             :             CPLError(CE_Failure, CPLE_NotSupported,
    1683             :                      "Unsupported band count with MONOCHROME");
    1684             :             return nullptr;
    1685             :         }
    1686             :         CPLAssert(nSampleType == RL2_SAMPLE_1_BIT);
    1687             :     }
    1688             :     else if (nPixelType == RL2_PIXEL_PALETTE)
    1689             :     {
    1690             :         if (nBandCount != 1)
    1691             :         {
    1692             :             CPLError(CE_Failure, CPLE_NotSupported,
    1693             :                      "Unsupported band count with PALETTE");
    1694             :             return nullptr;
    1695             :         }
    1696             :         if (nSampleType != RL2_SAMPLE_1_BIT &&
    1697             :             nSampleType != RL2_SAMPLE_2_BIT &&
    1698             :             nSampleType != RL2_SAMPLE_4_BIT && nSampleType != RL2_SAMPLE_UINT8)
    1699             :         {
    1700             :             CPLError(CE_Failure, CPLE_NotSupported,
    1701             :                      "Unsupported sample type with PALETTE");
    1702             :             return nullptr;
    1703             :         }
    1704             :     }
    1705             :     else if (nPixelType == RL2_PIXEL_GRAYSCALE)
    1706             :     {
    1707             :         if (nBandCount != 1)
    1708             :         {
    1709             :             CPLError(CE_Failure, CPLE_NotSupported,
    1710             :                      "Unsupported band count with GRAYSCALE");
    1711             :             return nullptr;
    1712             :         }
    1713             :         if (nSampleType != RL2_SAMPLE_2_BIT &&
    1714             :             nSampleType != RL2_SAMPLE_4_BIT && nSampleType != RL2_SAMPLE_UINT8)
    1715             :         {
    1716             :             CPLError(CE_Failure, CPLE_NotSupported,
    1717             :                      "Unsupported sample type with GRAYSCALE");
    1718             :             return nullptr;
    1719             :         }
    1720             :     }
    1721             :     else if (nPixelType == RL2_PIXEL_RGB)
    1722             :     {
    1723             :         if (nBandCount != 3)
    1724             :         {
    1725             :             CPLError(CE_Failure, CPLE_NotSupported,
    1726             :                      "Unsupported band count with RGB");
    1727             :             return nullptr;
    1728             :         }
    1729             :         if (nSampleType != RL2_SAMPLE_UINT8 && nSampleType != RL2_SAMPLE_UINT16)
    1730             :         {
    1731             :             CPLError(CE_Failure, CPLE_NotSupported,
    1732             :                      "Unsupported sample type with RGB");
    1733             :             return nullptr;
    1734             :         }
    1735             :     }
    1736             :     else if (nPixelType == RL2_PIXEL_MULTIBAND)
    1737             :     {
    1738             :         if (nBandCount == 1)
    1739             :         {
    1740             :             CPLError(CE_Failure, CPLE_NotSupported,
    1741             :                      "Unsupported band count with MULTIBAND");
    1742             :             return nullptr;
    1743             :         }
    1744             :         if (nSampleType != RL2_SAMPLE_UINT8 && nSampleType != RL2_SAMPLE_UINT16)
    1745             :         {
    1746             :             CPLError(CE_Failure, CPLE_NotSupported,
    1747             :                      "Unsupported sample type with MULTIBAND");
    1748             :             return nullptr;
    1749             :         }
    1750             :     }
    1751             :     else if (nPixelType == RL2_PIXEL_DATAGRID)
    1752             :     {
    1753             :         if (nBandCount != 1)
    1754             :         {
    1755             :             CPLError(CE_Failure, CPLE_NotSupported,
    1756             :                      "Unsupported band count with DATAGRID");
    1757             :             return nullptr;
    1758             :         }
    1759             :         if (nSampleType != RL2_SAMPLE_INT8 && nSampleType != RL2_SAMPLE_UINT8 &&
    1760             :             nSampleType != RL2_SAMPLE_INT16 &&
    1761             :             nSampleType != RL2_SAMPLE_UINT16 &&
    1762             :             nSampleType != RL2_SAMPLE_INT32 &&
    1763             :             nSampleType != RL2_SAMPLE_UINT32 &&
    1764             :             nSampleType != RL2_SAMPLE_FLOAT && nSampleType != RL2_SAMPLE_DOUBLE)
    1765             :         {
    1766             :             CPLError(CE_Failure, CPLE_NotSupported,
    1767             :                      "Unsupported sample type with DATAGRID");
    1768             :             return nullptr;
    1769             :         }
    1770             :     }
    1771             : 
    1772             :     // Other compatibility checks based on compression
    1773             :     if (nPixelType == RL2_PIXEL_MONOCHROME)
    1774             :     {
    1775             :         if (nCompression != RL2_COMPRESSION_NONE &&
    1776             :             nCompression != RL2_COMPRESSION_DEFLATE &&
    1777             :             nCompression != RL2_COMPRESSION_DEFLATE_NO &&
    1778             :             nCompression != RL2_COMPRESSION_LZMA &&
    1779             :             nCompression != RL2_COMPRESSION_LZMA_NO &&
    1780             :             nCompression != RL2_COMPRESSION_CCITTFAX4 &&
    1781             :             nCompression != RL2_COMPRESSION_PNG)
    1782             :         {
    1783             :             CPLError(CE_Failure, CPLE_NotSupported,
    1784             :                      "Unsupported compression with MONOCHROME");
    1785             :             return nullptr;
    1786             :         }
    1787             :     }
    1788             :     else if (nPixelType == RL2_PIXEL_PALETTE)
    1789             :     {
    1790             :         if (nCompression != RL2_COMPRESSION_NONE &&
    1791             :             nCompression != RL2_COMPRESSION_DEFLATE &&
    1792             :             nCompression != RL2_COMPRESSION_DEFLATE_NO &&
    1793             :             nCompression != RL2_COMPRESSION_LZMA &&
    1794             :             nCompression != RL2_COMPRESSION_LZMA_NO &&
    1795             :             nCompression != RL2_COMPRESSION_PNG)
    1796             :         {
    1797             :             CPLError(CE_Failure, CPLE_NotSupported,
    1798             :                      "Unsupported compression with PALETTE");
    1799             :             return nullptr;
    1800             :         }
    1801             :     }
    1802             :     else if (nPixelType == RL2_PIXEL_GRAYSCALE)
    1803             :     {
    1804             :         if (nCompression == RL2_COMPRESSION_CCITTFAX4)
    1805             :         {
    1806             :             CPLError(CE_Failure, CPLE_NotSupported,
    1807             :                      "Unsupported compression with GRAYSCALE");
    1808             :             return nullptr;
    1809             :         }
    1810             :     }
    1811             :     else if (nPixelType == RL2_PIXEL_RGB && nSampleType == RL2_SAMPLE_UINT8)
    1812             :     {
    1813             :         if (nCompression == RL2_COMPRESSION_CCITTFAX4)
    1814             :         {
    1815             :             CPLError(CE_Failure, CPLE_NotSupported,
    1816             :                      "Unsupported compression with RGB UINT8");
    1817             :             return nullptr;
    1818             :         }
    1819             :     }
    1820             :     else if (nPixelType == RL2_PIXEL_RGB && nSampleType == RL2_SAMPLE_UINT16)
    1821             :     {
    1822             :         if (nCompression == RL2_COMPRESSION_CCITTFAX4 ||
    1823             :             nCompression == RL2_COMPRESSION_JPEG ||
    1824             :             nCompression == RL2_COMPRESSION_LOSSY_WEBP ||
    1825             :             nCompression == RL2_COMPRESSION_LOSSLESS_WEBP)
    1826             :         {
    1827             :             CPLError(CE_Failure, CPLE_NotSupported,
    1828             :                      "Unsupported compression with RGB UINT16");
    1829             :             return nullptr;
    1830             :         }
    1831             :     }
    1832             :     else if (nPixelType == RL2_PIXEL_MULTIBAND &&
    1833             :              nSampleType == RL2_SAMPLE_UINT8 &&
    1834             :              (nBandCount == 3 || nBandCount == 4))
    1835             :     {
    1836             :         if (nCompression == RL2_COMPRESSION_CCITTFAX4 ||
    1837             :             nCompression == RL2_COMPRESSION_JPEG)
    1838             :         {
    1839             :             CPLError(CE_Failure, CPLE_NotSupported,
    1840             :                      "Unsupported compression with MULTIBAND UINT8 %d bands",
    1841             :                      nBandCount);
    1842             :             return nullptr;
    1843             :         }
    1844             :     }
    1845             :     else if (nPixelType == RL2_PIXEL_MULTIBAND &&
    1846             :              nSampleType == RL2_SAMPLE_UINT16 &&
    1847             :              (nBandCount == 3 || nBandCount == 4))
    1848             :     {
    1849             :         if (nCompression == RL2_COMPRESSION_CCITTFAX4 ||
    1850             :             nCompression == RL2_COMPRESSION_JPEG ||
    1851             :             nCompression == RL2_COMPRESSION_LOSSY_WEBP ||
    1852             :             nCompression == RL2_COMPRESSION_LOSSLESS_WEBP)
    1853             :         {
    1854             :             CPLError(CE_Failure, CPLE_NotSupported,
    1855             :                      "Unsupported compression with MULTIBAND UINT16 %d bands",
    1856             :                      nBandCount);
    1857             :             return nullptr;
    1858             :         }
    1859             :     }
    1860             :     else if (nPixelType == RL2_PIXEL_MULTIBAND)
    1861             :     {
    1862             :         if (nCompression != RL2_COMPRESSION_NONE &&
    1863             :             nCompression != RL2_COMPRESSION_DEFLATE &&
    1864             :             nCompression != RL2_COMPRESSION_DEFLATE_NO &&
    1865             :             nCompression != RL2_COMPRESSION_LZMA &&
    1866             :             nCompression != RL2_COMPRESSION_LZMA_NO)
    1867             :         {
    1868             :             CPLError(CE_Failure, CPLE_NotSupported,
    1869             :                      "Unsupported compression with MULTIBAND %s %d bands",
    1870             :                      (nSampleType == RL2_SAMPLE_UINT8) ? "UINT8" : "UINT16",
    1871             :                      nBandCount);
    1872             :             return nullptr;
    1873             :         }
    1874             :     }
    1875             :     else if (nPixelType == RL2_PIXEL_DATAGRID &&
    1876             :              (nSampleType == RL2_SAMPLE_UINT8 ||
    1877             :               nSampleType == RL2_SAMPLE_UINT16))
    1878             :     {
    1879             :         if (nCompression == RL2_COMPRESSION_CCITTFAX4 ||
    1880             :             nCompression == RL2_COMPRESSION_JPEG ||
    1881             :             nCompression == RL2_COMPRESSION_LOSSY_WEBP ||
    1882             :             nCompression == RL2_COMPRESSION_LOSSLESS_WEBP)
    1883             :         {
    1884             :             CPLError(CE_Failure, CPLE_NotSupported,
    1885             :                      "Unsupported compression with DATAGRID %s",
    1886             :                      (nSampleType == RL2_SAMPLE_UINT8) ? "UINT8" : "UINT16");
    1887             :             return nullptr;
    1888             :         }
    1889             :     }
    1890             :     else if (nPixelType == RL2_PIXEL_DATAGRID &&
    1891             :              nSampleType != RL2_SAMPLE_UINT8 &&
    1892             :              nSampleType != RL2_SAMPLE_UINT16)
    1893             :     {
    1894             :         if (nCompression != RL2_COMPRESSION_NONE &&
    1895             :             nCompression != RL2_COMPRESSION_DEFLATE &&
    1896             :             nCompression != RL2_COMPRESSION_DEFLATE_NO &&
    1897             :             nCompression != RL2_COMPRESSION_LZMA &&
    1898             :             nCompression != RL2_COMPRESSION_LZMA_NO)
    1899             :         {
    1900             :             CPLError(CE_Failure, CPLE_NotSupported,
    1901             :                      "Unsupported compression with DATAGRID %s",
    1902             :                      GDALGetDataTypeName(eDT));
    1903             :             return nullptr;
    1904             :         }
    1905             :     }
    1906             : 
    1907             :     const char *pszQuality = CSLFetchNameValue(papszOptions, "QUALITY");
    1908             :     if (pszQuality)
    1909             :     {
    1910             :         nQuality = atoi(pszQuality);
    1911             :         if (nQuality == 100 && nCompression == RL2_COMPRESSION_LOSSY_JP2)
    1912             :             nCompression = RL2_COMPRESSION_LOSSLESS_JP2;
    1913             :         else if (nQuality == 100 && nCompression == RL2_COMPRESSION_LOSSY_WEBP)
    1914             :             nCompression = RL2_COMPRESSION_LOSSLESS_WEBP;
    1915             :     }
    1916             : 
    1917             :     unsigned int nTileWidth =
    1918             :         atoi(CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", "512"));
    1919             :     unsigned int nTileHeight =
    1920             :         atoi(CSLFetchNameValueDef(papszOptions, "BLOCKYSIZE", "512"));
    1921             : 
    1922             :     /* -------------------------------------------------------------------- */
    1923             :     /*      Try to create datasource.                                       */
    1924             :     /* -------------------------------------------------------------------- */
    1925             :     OGRSQLiteDataSource *poDS = new OGRSQLiteDataSource();
    1926             : 
    1927             :     if (CSLFetchNameValue(papszOptions, "APPEND_SUBDATASET"))
    1928             :     {
    1929             :         GDALOpenInfo oOpenInfo(pszName, GDAL_OF_RASTER | GDAL_OF_VECTOR |
    1930             :                                             GDAL_OF_UPDATE);
    1931             :         if (!poDS->Open(&oOpenInfo))
    1932             :         {
    1933             :             delete poDS;
    1934             :             return nullptr;
    1935             :         }
    1936             :     }
    1937             :     else
    1938             :     {
    1939             :         char **papszNewOptions = CSLDuplicate(papszOptions);
    1940             :         papszNewOptions = CSLSetNameValue(papszNewOptions, "SPATIALITE", "YES");
    1941             :         if (!poDS->Create(pszName, papszNewOptions))
    1942             :         {
    1943             :             CSLDestroy(papszNewOptions);
    1944             :             delete poDS;
    1945             :             return nullptr;
    1946             :         }
    1947             :         CSLDestroy(papszNewOptions);
    1948             :     }
    1949             : 
    1950             :     /* -------------------------------------------------------------------- */
    1951             :     /*      Try to get the SRS Id of this spatial reference system,         */
    1952             :     /*      adding to the srs table if needed.                              */
    1953             :     /* -------------------------------------------------------------------- */
    1954             :     int nSRSId = 0;
    1955             :     const char *pszSRID = CSLFetchNameValue(papszOptions, "SRID");
    1956             : 
    1957             :     if (pszSRID != nullptr)
    1958             :     {
    1959             :         nSRSId = atoi(pszSRID);
    1960             :         if (nSRSId > 0)
    1961             :         {
    1962             :             OGRSpatialReference *poSRSFetched = poDS->FetchSRS(nSRSId);
    1963             :             if (poSRSFetched == nullptr)
    1964             :             {
    1965             :                 CPLError(CE_Warning, CPLE_AppDefined,
    1966             :                          "SRID %d will be used, but no matching SRS is "
    1967             :                          "defined in spatial_ref_sys",
    1968             :                          nSRSId);
    1969             :             }
    1970             :         }
    1971             :     }
    1972             :     else
    1973             :     {
    1974             :         const OGRSpatialReference *poSRS = poSrcDS->GetSpatialRef();
    1975             :         if (poSRS)
    1976             :         {
    1977             :             nSRSId = poDS->FetchSRSId(poSRS);
    1978             :         }
    1979             :     }
    1980             : 
    1981             :     poDS->StartTransaction();
    1982             : 
    1983             :     char **papszResults = nullptr;
    1984             :     int nRowCount = 0;
    1985             :     int nColCount = 0;
    1986             :     sqlite3_get_table(poDS->GetDB(),
    1987             :                       "SELECT * FROM sqlite_master WHERE "
    1988             :                       "name = 'raster_coverages' AND type = 'table'",
    1989             :                       &papszResults, &nRowCount, &nColCount, nullptr);
    1990             :     sqlite3_free_table(papszResults);
    1991             :     if (nRowCount == 0)
    1992             :     {
    1993             :         char *pszErrMsg = nullptr;
    1994             :         int ret =
    1995             :             sqlite3_exec(poDS->GetDB(), "SELECT CreateRasterCoveragesTable()",
    1996             :                          nullptr, nullptr, &pszErrMsg);
    1997             :         if (ret != SQLITE_OK)
    1998             :         {
    1999             :             CPLError(CE_Failure, CPLE_AppDefined,
    2000             :                      "CreateRasterCoveragesTable() failed: %s", pszErrMsg);
    2001             :             sqlite3_free(pszErrMsg);
    2002             :             delete poDS;
    2003             :             return nullptr;
    2004             :         }
    2005             :     }
    2006             : 
    2007             :     CPLString osCoverageName(CSLFetchNameValueDef(papszOptions, "COVERAGE",
    2008             :                                                   CPLGetBasename(pszName)));
    2009             :     // Check if the coverage already exists
    2010             :     rl2CoveragePtr cvg = nullptr;
    2011             :     char *pszSQL = sqlite3_mprintf(
    2012             :         "SELECT coverage_name "
    2013             :         "FROM raster_coverages WHERE coverage_name = '%q' LIMIT 1",
    2014             :         osCoverageName.c_str());
    2015             :     sqlite3_get_table(poDS->GetDB(), pszSQL, &papszResults, &nRowCount,
    2016             :                       &nColCount, nullptr);
    2017             :     sqlite3_free(pszSQL);
    2018             :     sqlite3_free_table(papszResults);
    2019             :     if (nRowCount == 1)
    2020             :     {
    2021             :         cvg = rl2_create_coverage_from_dbms(poDS->GetDB(), nullptr,
    2022             :                                             osCoverageName);
    2023             :         if (cvg == nullptr)
    2024             :         {
    2025             :             delete poDS;
    2026             :             return nullptr;
    2027             :         }
    2028             :     }
    2029             : 
    2030             :     rl2PalettePtr pPalette = nullptr;
    2031             :     if (nPixelType == RL2_PIXEL_PALETTE)
    2032             :     {
    2033             :         GDALColorTable *poCT = poSrcDS->GetRasterBand(1)->GetColorTable();
    2034             :         if (poCT == nullptr)
    2035             :         {
    2036             :             CPLError(CE_Failure, CPLE_AppDefined, "Missing color table");
    2037             :             delete poDS;
    2038             :             return nullptr;
    2039             :         }
    2040             : 
    2041             :         const int nColors = poCT->GetColorEntryCount();
    2042             :         pPalette = rl2_create_palette(nColors);
    2043             :         for (int i = 0; i < nColors; ++i)
    2044             :         {
    2045             :             const GDALColorEntry *poCE = poCT->GetColorEntry(i);
    2046             :             rl2_set_palette_color(pPalette, i, static_cast<GByte>(poCE->c1),
    2047             :                                   static_cast<GByte>(poCE->c2),
    2048             :                                   static_cast<GByte>(poCE->c3));
    2049             :         }
    2050             :     }
    2051             : 
    2052             :     if (cvg == nullptr)
    2053             :     {
    2054             :         const double dfXRes = adfGeoTransform[1];
    2055             :         const double dfYRes = fabs(adfGeoTransform[5]);
    2056             :         const bool bStrictResolution = true;
    2057             :         const bool bMixedResolutions = false;
    2058             :         const bool bSectionPaths = false;
    2059             :         const bool bSectionMD5 = false;
    2060             :         const bool bSectionSummary = false;
    2061             :         const bool bIsQueryable = false;
    2062             : 
    2063             :         rl2PixelPtr pNoData =
    2064             :             CreateNoData(nSampleType, nPixelType, nBandCount, poSrcDS);
    2065             :         if (pNoData == nullptr)
    2066             :         {
    2067             :             delete poDS;
    2068             :             if (pPalette)
    2069             :                 rl2_destroy_palette(pPalette);
    2070             :             return nullptr;
    2071             :         }
    2072             : 
    2073             :         if (rl2_create_dbms_coverage(
    2074             :                 poDS->GetDB(), osCoverageName, nSampleType, nPixelType,
    2075             :                 nBandCount, nCompression, nQuality, nTileWidth, nTileHeight,
    2076             :                 nSRSId, dfXRes, dfYRes, pNoData, pPalette, bStrictResolution,
    2077             :                 bMixedResolutions, bSectionPaths, bSectionMD5, bSectionSummary,
    2078             :                 bIsQueryable) != RL2_OK)
    2079             :         {
    2080             :             CPLError(CE_Failure, CPLE_AppDefined,
    2081             :                      "rl2_create_dbms_coverage() failed");
    2082             :             rl2_destroy_pixel(pNoData);
    2083             :             if (pPalette)
    2084             :                 rl2_destroy_palette(pPalette);
    2085             :             delete poDS;
    2086             :             return nullptr;
    2087             :         }
    2088             : 
    2089             :         rl2_destroy_pixel(pNoData);
    2090             :     }
    2091             : 
    2092             :     if (cvg == nullptr)
    2093             :     {
    2094             :         cvg = rl2_create_coverage_from_dbms(poDS->GetDB(), nullptr,
    2095             :                                             osCoverageName);
    2096             :         if (cvg == nullptr)
    2097             :         {
    2098             :             if (pPalette)
    2099             :                 rl2_destroy_palette(pPalette);
    2100             :             delete poDS;
    2101             :             return nullptr;
    2102             :         }
    2103             :     }
    2104             : 
    2105             :     if (adfGeoTransform[5] > 0)
    2106             :         adfGeoTransform[5] = -adfGeoTransform[5];
    2107             :     double dfXMin = adfGeoTransform[0];
    2108             :     double dfXMax = dfXMin + adfGeoTransform[1] * poSrcDS->GetRasterXSize();
    2109             :     double dfYMax = adfGeoTransform[3];
    2110             :     double dfYMin = dfYMax + adfGeoTransform[5] * poSrcDS->GetRasterYSize();
    2111             : 
    2112             :     CPLString osSectionName(
    2113             :         CSLFetchNameValueDef(papszOptions, "SECTION", CPLGetBasename(pszName)));
    2114             :     const bool bPyramidize = CPLFetchBool(papszOptions, "PYRAMIDIZE", false);
    2115             :     RasterLite2CallbackData cbk_data;
    2116             :     cbk_data.poSrcDS = poSrcDS;
    2117             :     cbk_data.nPixelType = nPixelType;
    2118             :     cbk_data.nSampleType = nSampleType;
    2119             :     cbk_data.pPalette = pPalette;
    2120             :     cbk_data.pfnProgress = pfnProgress;
    2121             :     cbk_data.pProgressData = pProgressData;
    2122             :     memcpy(&cbk_data.adfGeoTransform, adfGeoTransform, sizeof(adfGeoTransform));
    2123             : 
    2124             :     if (rl2_load_raw_tiles_into_dbms(
    2125             :             poDS->GetDB(), poDS->GetRL2Context(), cvg, osSectionName,
    2126             :             poSrcDS->GetRasterXSize(), poSrcDS->GetRasterYSize(), nSRSId,
    2127             :             dfXMin, dfYMin, dfXMax, dfYMax, RasterLite2Callback, &cbk_data,
    2128             :             bPyramidize) != RL2_OK)
    2129             :     {
    2130             :         CPLError(CE_Failure, CPLE_AppDefined,
    2131             :                  "rl2_load_raw_tiles_into_dbms() failed");
    2132             :         delete poDS;
    2133             :         rl2_destroy_coverage(cvg);
    2134             :         if (pPalette)
    2135             :             rl2_destroy_palette(pPalette);
    2136             :         return nullptr;
    2137             :     }
    2138             : 
    2139             :     rl2_destroy_coverage(cvg);
    2140             :     if (pPalette)
    2141             :         rl2_destroy_palette(pPalette);
    2142             : 
    2143             :     poDS->CommitTransaction();
    2144             : 
    2145             :     delete poDS;
    2146             : 
    2147             :     poDS = new OGRSQLiteDataSource();
    2148             :     GDALOpenInfo oOpenInfo(
    2149             :         CPLSPrintf("RASTERLITE2:%s:%s",
    2150             :                    EscapeNameAndQuoteIfNeeded(pszName).c_str(),
    2151             :                    EscapeNameAndQuoteIfNeeded(osCoverageName).c_str()),
    2152             :         GDAL_OF_RASTER | GDAL_OF_UPDATE);
    2153             :     poDS->Open(&oOpenInfo);
    2154             :     return poDS;
    2155             : }
    2156             : 
    2157             : /************************************************************************/
    2158             : /*                          IBuildOverviews()                           */
    2159             : /************************************************************************/
    2160             : 
    2161             : CPLErr OGRSQLiteDataSource::IBuildOverviews(
    2162             :     const char *pszResampling, int nOverviews, const int *panOverviewList,
    2163             :     int nBandsIn, const int * /*panBandList */,
    2164             :     GDALProgressFunc /*pfnProgress*/, void * /*pProgressData*/,
    2165             :     CSLConstList /* papszOptions */)
    2166             : 
    2167             : {
    2168             :     if (nBandsIn != nBands)
    2169             :     {
    2170             :         CPLError(CE_Failure, CPLE_AppDefined,
    2171             :                  "Only build of all bands is supported");
    2172             :     }
    2173             : 
    2174             :     if (nOverviews == 0)
    2175             :     {
    2176             :         int ret;
    2177             :         if (m_bRL2MixedResolutions && m_nSectionId >= 0)
    2178             :         {
    2179             :             ret =
    2180             :                 rl2_delete_section_pyramid(hDB, m_osCoverageName, m_nSectionId);
    2181             :         }
    2182             :         else
    2183             :         {
    2184             :             ret = rl2_delete_all_pyramids(hDB, m_osCoverageName);
    2185             :         }
    2186             :         if (ret != RL2_OK)
    2187             :         {
    2188             :             CPLError(CE_Failure, CPLE_AppDefined,
    2189             :                      "Deletion of pyramids failed");
    2190             :             return CE_Failure;
    2191             :         }
    2192             :     }
    2193             :     else
    2194             :     {
    2195             :         if (!STARTS_WITH_CI(pszResampling, "NEAR"))
    2196             :         {
    2197             :             CPLError(CE_Warning, CPLE_AppDefined,
    2198             :                      "Resampling method is ignored. Using librasterlite2 own "
    2199             :                      "method");
    2200             :         }
    2201             :         for (int i = 0; i < nOverviews; ++i)
    2202             :         {
    2203             :             if (!CPLIsPowerOfTwo(panOverviewList[i]))
    2204             :             {
    2205             :                 CPLError(CE_Failure, CPLE_NotSupported,
    2206             :                          "Only power-of-two overview factors are supported");
    2207             :                 return CE_Failure;
    2208             :             }
    2209             :         }
    2210             : 
    2211             :         const int bForcedRebuild = 1;
    2212             :         const int bVerbose = 0;
    2213             :         const int bVirtualLevels = 1;
    2214             :         int ret;
    2215             :         if (m_bRL2MixedResolutions)
    2216             :         {
    2217             :             if (m_nSectionId >= 0)
    2218             :             {
    2219             :                 ret = rl2_build_section_pyramid(hDB, GetRL2Context(),
    2220             :                                                 m_osCoverageName, m_nSectionId,
    2221             :                                                 bForcedRebuild, bVerbose);
    2222             :             }
    2223             :             else
    2224             :             {
    2225             :                 ret = rl2_build_monolithic_pyramid(hDB, GetRL2Context(),
    2226             :                                                    m_osCoverageName,
    2227             :                                                    bVirtualLevels, bVerbose);
    2228             :             }
    2229             :         }
    2230             :         else
    2231             :         {
    2232             :             ret = rl2_build_monolithic_pyramid(hDB, GetRL2Context(),
    2233             :                                                m_osCoverageName, bVirtualLevels,
    2234             :                                                bVerbose);
    2235             :         }
    2236             :         if (ret != RL2_OK)
    2237             :         {
    2238             :             CPLError(CE_Failure, CPLE_AppDefined, "Build of pyramids failed");
    2239             :             return CE_Failure;
    2240             :         }
    2241             :     }
    2242             : 
    2243             :     for (size_t i = 0; i < m_apoOverviewDS.size(); ++i)
    2244             :         delete m_apoOverviewDS[i];
    2245             :     m_apoOverviewDS.clear();
    2246             :     ListOverviews();
    2247             : 
    2248             :     return CE_None;
    2249             : }
    2250             : 
    2251             : #endif  // HAVE_RASTERLITE2
    2252             : 
    2253             : /************************************************************************/
    2254             : /*                             GetMetadata()                            */
    2255             : /************************************************************************/
    2256             : 
    2257           5 : char **OGRSQLiteDataSource::GetMetadata(const char *pszDomain)
    2258             : {
    2259           5 :     if (pszDomain != nullptr && EQUAL(pszDomain, "SUBDATASETS") &&
    2260           0 :         m_aosSubDatasets.size() > 2)
    2261             :     {
    2262           0 :         return m_aosSubDatasets.List();
    2263             :     }
    2264           5 :     return GDALPamDataset::GetMetadata(pszDomain);
    2265             : }
    2266             : 
    2267             : /************************************************************************/
    2268             : /*                           GetGeoTransform()                          */
    2269             : /************************************************************************/
    2270             : 
    2271           0 : CPLErr OGRSQLiteDataSource::GetGeoTransform(double *padfGeoTransform)
    2272             : {
    2273           0 :     if (m_bGeoTransformValid)
    2274             :     {
    2275           0 :         memcpy(padfGeoTransform, m_adfGeoTransform, 6 * sizeof(double));
    2276           0 :         return CE_None;
    2277             :     }
    2278           0 :     return GDALPamDataset::GetGeoTransform(padfGeoTransform);
    2279             : }
    2280             : 
    2281             : /************************************************************************/
    2282             : /*                            GetSpatialRef()                           */
    2283             : /************************************************************************/
    2284             : 
    2285           0 : const OGRSpatialReference *OGRSQLiteDataSource::GetSpatialRef() const
    2286             : {
    2287           0 :     if (!m_oSRS.IsEmpty())
    2288           0 :         return &m_oSRS;
    2289           0 :     return GDALPamDataset::GetSpatialRef();
    2290             : }

Generated by: LCOV version 1.14