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

Generated by: LCOV version 1.14