• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

OSGeo / gdal / 15885686134

25 Jun 2025 07:44PM UTC coverage: 71.084%. Remained the same
15885686134

push

github

rouault
gdal_priv.h: fix C++11 compatibility

573814 of 807237 relevant lines covered (71.08%)

250621.56 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

27.78
/ogr/ogrsf_frmts/sqlite/rasterlite2.cpp
1
/******************************************************************************
2
 *
3
 * Project:  OpenGIS Simple Features Reference Implementation
4
 * Purpose:  Implements RasterLite2 support class.
5
 * Author:   Even Rouault <even.rouault at spatialys.com>
6
 *
7
 ******************************************************************************
8
 *
9
 * CREDITS: The RasterLite2 module has been completely funded by:
10
 * Regione Toscana - Settore Sistema Informativo Territoriale ed
11
 * Ambientale (GDAL/RasterLite2 driver)
12
 * CIG: 644544015A
13
 *
14
 ******************************************************************************
15
 * Copyright (c) 2016, Even Rouault <even.rouault at spatialys.com>
16
 *
17
 * SPDX-License-Identifier: MIT
18
 ****************************************************************************/
19

20
#include "cpl_port.h"
21
#include "ogr_sqlite.h"
22
#include "ogrsqliteutility.h"
23
#include "rasterlite2_header.h"
24

25
#include <cstring>
26
#include <algorithm>
27

28
#include "cpl_error.h"
29
#include "cpl_string.h"
30

31
#ifdef HAVE_RASTERLITE2
32

33
static CPLString EscapeNameAndQuoteIfNeeded(const char *pszName)
34
{
35
    if (strchr(pszName, '"') == nullptr && strchr(pszName, ':') == nullptr)
36
        return pszName;
37
    return '"' + SQLEscapeName(pszName) + '"';
38
}
39

40
#endif
41

42
/************************************************************************/
43
/*                            OpenRaster()                              */
44
/************************************************************************/
45

46
bool OGRSQLiteDataSource::OpenRaster()
3✔
47
{
48
#ifdef HAVE_RASTERLITE2
49
    /* -------------------------------------------------------------------- */
50
    /*      Detect RasterLite2 coverages.                                   */
51
    /* -------------------------------------------------------------------- */
52
    char **papszResults = nullptr;
53
    int nRowCount = 0, nColCount = 0;
54
    int rc = sqlite3_get_table(hDB,
55
                               "SELECT name FROM sqlite_master WHERE "
56
                               "type = 'table' AND name = 'raster_coverages'",
57
                               &papszResults, &nRowCount, &nColCount, nullptr);
58
    sqlite3_free_table(papszResults);
59
    if (!(rc == SQLITE_OK && nRowCount == 1))
60
    {
61
        return false;
62
    }
63

64
    papszResults = nullptr;
65
    nRowCount = 0;
66
    nColCount = 0;
67
    rc = sqlite3_get_table(hDB,
68
                           "SELECT coverage_name, title, abstract "
69
                           "FROM raster_coverages "
70
                           "LIMIT 10000",
71
                           &papszResults, &nRowCount, &nColCount, nullptr);
72
    if (!(rc == SQLITE_OK && nRowCount > 0))
73
    {
74
        sqlite3_free_table(papszResults);
75
        return false;
76
    }
77
    for (int i = 0; i < nRowCount; ++i)
78
    {
79
        const char *const *papszRow = papszResults + i * 3 + 3;
80
        const char *pszCoverageName = papszRow[0];
81
        const char *pszTitle = papszRow[1];
82
        const char *pszAbstract = papszRow[2];
83
        if (pszCoverageName != nullptr)
84
        {
85
            rl2CoveragePtr cvg =
86
                rl2_create_coverage_from_dbms(hDB, nullptr, pszCoverageName);
87
            if (cvg != nullptr)
88
            {
89
                const int nIdx = m_aosSubDatasets.size() / 2 + 1;
90
                m_aosSubDatasets.AddNameValue(
91
                    CPLSPrintf("SUBDATASET_%d_NAME", nIdx),
92
                    CPLSPrintf(
93
                        "RASTERLITE2:%s:%s",
94
                        EscapeNameAndQuoteIfNeeded(m_pszFilename).c_str(),
95
                        EscapeNameAndQuoteIfNeeded(pszCoverageName).c_str()));
96
                CPLString osDesc("Coverage ");
97
                osDesc += pszCoverageName;
98
                if (pszTitle != nullptr && pszTitle[0] != '\0' &&
99
                    !EQUAL(pszTitle, "*** missing Title ***"))
100
                {
101
                    osDesc += ", title = ";
102
                    osDesc += pszTitle;
103
                }
104
                if (pszAbstract != nullptr && pszAbstract[0] != '\0' &&
105
                    !EQUAL(pszAbstract, "*** missing Abstract ***"))
106
                {
107
                    osDesc += ", abstract = ";
108
                    osDesc += pszAbstract;
109
                }
110
                m_aosSubDatasets.AddNameValue(
111
                    CPLSPrintf("SUBDATASET_%d_DESC", nIdx), osDesc.c_str());
112

113
                rl2_destroy_coverage(cvg);
114
            }
115
        }
116
    }
117
    sqlite3_free_table(papszResults);
118

119
    if (m_aosSubDatasets.size() == 2)
120
    {
121
        const char *pszSubDSName =
122
            m_aosSubDatasets.FetchNameValue("SUBDATASET_1_NAME");
123
        if (pszSubDSName)
124
        {
125
            return OpenRasterSubDataset(pszSubDSName);
126
        }
127
    }
128

129
    return !m_aosSubDatasets.empty();
130
#else
131
    return false;
3✔
132
#endif
133
}
134

135
/************************************************************************/
136
/*                        OpenRasterSubDataset()                        */
137
/************************************************************************/
138

139
bool OGRSQLiteDataSource::OpenRasterSubDataset(
×
140
    CPL_UNUSED const char *pszConnectionId)
141
{
142
#ifdef HAVE_RASTERLITE2
143
    if (!STARTS_WITH_CI(pszConnectionId, "RASTERLITE2:"))
144
        return false;
145

146
    char **papszTokens =
147
        CSLTokenizeString2(pszConnectionId, ":", CSLT_HONOURSTRINGS);
148
    if (CSLCount(papszTokens) < 3)
149
    {
150
        CSLDestroy(papszTokens);
151
        return false;
152
    }
153

154
    m_aosSubDatasets.Clear();
155

156
    m_osCoverageName = SQLUnescape(papszTokens[2]);
157
    m_nSectionId =
158
        (CSLCount(papszTokens) >= 4) ? CPLAtoGIntBig(papszTokens[3]) : -1;
159

160
    CSLDestroy(papszTokens);
161

162
    m_pRL2Coverage =
163
        rl2_create_coverage_from_dbms(hDB, nullptr, m_osCoverageName);
164
    if (m_pRL2Coverage == nullptr)
165
    {
166
        CPLError(CE_Failure, CPLE_AppDefined, "Invalid coverage: %s",
167
                 m_osCoverageName.c_str());
168
        return false;
169
    }
170

171
    bool bSingleSection = false;
172
    if (m_nSectionId < 0)
173
    {
174
        CPLString osSectionTableName(
175
            CPLSPrintf("%s_sections", m_osCoverageName.c_str()));
176
        int nRowCount2 = 0;
177
        int nColCount2 = 0;
178
        char **papszResults2 = nullptr;
179
        char *pszSQL =
180
            sqlite3_mprintf("SELECT section_id, section_name FROM \"%w\" "
181
                            "ORDER BY section_id "
182
                            "LIMIT 1000000",
183
                            osSectionTableName.c_str());
184
        int rc = sqlite3_get_table(hDB, pszSQL, &papszResults2, &nRowCount2,
185
                                   &nColCount2, nullptr);
186
        sqlite3_free(pszSQL);
187
        if (rc == SQLITE_OK)
188
        {
189
            for (int j = 0; j < nRowCount2; ++j)
190
            {
191
                const char *const *papszRow2 = papszResults2 + j * 2 + 2;
192
                const char *pszSectionId = papszRow2[0];
193
                const char *pszSectionName = papszRow2[1];
194
                if (pszSectionName != nullptr && pszSectionId != nullptr)
195
                {
196
                    if (nRowCount2 > 1)
197
                    {
198
                        const int nIdx = m_aosSubDatasets.size() / 2 + 1;
199
                        m_aosSubDatasets.AddNameValue(
200
                            CPLSPrintf("SUBDATASET_%d_NAME", nIdx),
201
                            CPLSPrintf(
202
                                "RASTERLITE2:%s:%s:%s:%s",
203
                                EscapeNameAndQuoteIfNeeded(m_pszFilename)
204
                                    .c_str(),
205
                                EscapeNameAndQuoteIfNeeded(m_osCoverageName)
206
                                    .c_str(),
207
                                pszSectionId,
208
                                EscapeNameAndQuoteIfNeeded(pszSectionName)
209
                                    .c_str()));
210
                        m_aosSubDatasets.AddNameValue(
211
                            CPLSPrintf("SUBDATASET_%d_DESC", nIdx),
212
                            CPLSPrintf("Coverage %s, section %s / %s",
213
                                       m_osCoverageName.c_str(), pszSectionName,
214
                                       pszSectionId));
215
                    }
216
                    else
217
                    {
218
                        m_nSectionId = CPLAtoGIntBig(pszSectionId);
219
                        bSingleSection = true;
220
                    }
221
                }
222
            }
223
        }
224
        sqlite3_free_table(papszResults2);
225
    }
226

227
    double dfXRes = 0.0;
228
    double dfYRes = 0.0;
229

230
    double dfMinX = 0.0;
231
    double dfMinY = 0.0;
232
    double dfMaxX = 0.0;
233
    double dfMaxY = 0.0;
234
    unsigned int nWidth = 0;
235
    unsigned int nHeight = 0;
236

237
    // Get extent and resolution
238
    if (m_nSectionId >= 0)
239
    {
240
        int ret = rl2_resolve_base_resolution_from_dbms(
241
            hDB, nullptr, m_osCoverageName,
242
            TRUE,  // by_section
243
            m_nSectionId, &dfXRes, &dfYRes);
244
        if (ret != RL2_OK)
245
        {
246
            CPLError(CE_Failure, CPLE_AppDefined,
247
                     "rl2_resolve_base_resolution_from_dbms() failed / "
248
                     "Invalid section: " CPL_FRMT_GIB,
249
                     m_nSectionId);
250
            return false;
251
        }
252

253
        ret = rl2_resolve_full_section_from_dbms(
254
            hDB, nullptr, m_osCoverageName, m_nSectionId, dfXRes, dfYRes,
255
            &dfMinX, &dfMinY, &dfMaxX, &dfMaxY, &nWidth, &nHeight);
256
        if (ret != RL2_OK || nWidth == 0 || nWidth > INT_MAX || nHeight == 0 ||
257
            nHeight > INT_MAX)
258
        {
259
            CPLError(CE_Failure, CPLE_AppDefined,
260
                     "rl2_resolve_full_section_from_dbms() failed / "
261
                     "Invalid section: " CPL_FRMT_GIB,
262
                     m_nSectionId);
263
            return false;
264
        }
265
    }
266
    else
267
    {
268
        rl2_get_coverage_resolution(m_pRL2Coverage, &dfXRes, &dfYRes);
269

270
        char *pszSQL = sqlite3_mprintf(
271
            "SELECT extent_minx, extent_miny, extent_maxx, extent_maxy "
272
            "FROM raster_coverages WHERE "
273
            "Lower(coverage_name) = Lower('%q') "
274
            "LIMIT 1",
275
            m_osCoverageName.c_str());
276
        char **papszResults = nullptr;
277
        int nRowCount = 0;
278
        int nColCount = 0;
279
        int rc = sqlite3_get_table(hDB, pszSQL, &papszResults, &nRowCount,
280
                                   &nColCount, nullptr);
281
        sqlite3_free(pszSQL);
282
        if (rc == SQLITE_OK)
283
        {
284
            if (nRowCount == 1)
285
            {
286
                const char *pszMinX = papszResults[4 + 0];
287
                const char *pszMinY = papszResults[4 + 1];
288
                const char *pszMaxX = papszResults[4 + 2];
289
                const char *pszMaxY = papszResults[4 + 3];
290
                if (pszMinX != nullptr && pszMinY != nullptr &&
291
                    pszMaxX != nullptr && pszMaxY != nullptr)
292
                {
293
                    dfMinX = CPLAtof(pszMinX);
294
                    dfMinY = CPLAtof(pszMinY);
295
                    dfMaxX = CPLAtof(pszMaxX);
296
                    dfMaxY = CPLAtof(pszMaxY);
297
                }
298
            }
299
            sqlite3_free_table(papszResults);
300
        }
301
        double dfWidth = 0.5 + (dfMaxX - dfMinX) / dfXRes;
302
        double dfHeight = 0.5 + (dfMaxY - dfMinY) / dfYRes;
303
        if (dfWidth <= 0.5 || dfHeight <= 0.5 || dfWidth > INT_MAX ||
304
            dfHeight > INT_MAX)
305
        {
306
            CPLError(CE_Failure, CPLE_AppDefined, "Invalid dimensions");
307
            return false;
308
        }
309
        nWidth = static_cast<int>(dfWidth);
310
        nHeight = static_cast<int>(dfHeight);
311
    }
312

313
    // Compute dimension and geotransform
314
    nRasterXSize = static_cast<int>(nWidth);
315
    nRasterYSize = static_cast<int>(nHeight);
316
    m_bGeoTransformValid = true;
317
    m_gt[0] = dfMinX;
318
    m_gt[1] = (dfMaxX - dfMinX) / nRasterXSize;
319
    m_gt[2] = 0.0;
320
    m_gt[3] = dfMaxY;
321
    m_gt[4] = 0.0;
322
    m_gt[5] = -(dfMaxY - dfMinY) / nRasterYSize;
323

324
    // Get SRS
325
    int nSRID = 0;
326
    if (rl2_get_coverage_srid(m_pRL2Coverage, &nSRID) == RL2_OK)
327
    {
328
        OGRSpatialReference *poSRS = FetchSRS(nSRID);
329
        if (poSRS != nullptr)
330
        {
331
            m_oSRS = *poSRS;
332
            m_oSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);
333
        }
334
    }
335

336
    // Get pixel information and number of bands
337
    unsigned char nSampleType = 0;
338
    unsigned char nPixelType = 0;
339
    unsigned char l_nBands = 0;
340
    rl2_get_coverage_type(m_pRL2Coverage, &nSampleType, &nPixelType, &l_nBands);
341
    if (!GDALCheckBandCount(l_nBands, FALSE))
342
        return false;
343
    int nBits = 0;
344
    GDALDataType eDT = GDT_Unknown;
345
    switch (nSampleType)
346
    {
347
        default:
348
        case RL2_SAMPLE_UNKNOWN:
349
        {
350
            CPLError(CE_Failure, CPLE_AppDefined, "Unknown sample type");
351
            return false;
352
        }
353
        case RL2_SAMPLE_1_BIT:
354
        {
355
            if (nPixelType == RL2_PIXEL_MONOCHROME)
356
            {
357
                m_bPromote1BitAs8Bit =
358
                    CPLFetchBool(papszOpenOptions, "1BIT_AS_8BIT", true);
359
            }
360
            nBits = 1;
361
            eDT = GDT_Byte;
362
            break;
363
        }
364
        case RL2_SAMPLE_2_BIT:
365
        {
366
            nBits = 2;
367
            eDT = GDT_Byte;
368
            break;
369
        }
370
        case RL2_SAMPLE_4_BIT:
371
        {
372
            nBits = 4;
373
            eDT = GDT_Byte;
374
            break;
375
        }
376
        case RL2_SAMPLE_INT8:
377
        {
378
            nBits = 8;
379
            eDT = GDT_Int8;
380
            break;
381
        }
382
        case RL2_SAMPLE_UINT8:
383
        {
384
            nBits = 8;
385
            eDT = GDT_Byte;
386
            break;
387
        }
388
        case RL2_SAMPLE_INT16:
389
        {
390
            nBits = 16;
391
            eDT = GDT_Int16;
392
            break;
393
        }
394
        case RL2_SAMPLE_UINT16:
395
        {
396
            nBits = 16;
397
            eDT = GDT_UInt16;
398
            break;
399
        }
400
        case RL2_SAMPLE_INT32:
401
        {
402
            nBits = 32;
403
            eDT = GDT_Int32;
404
            break;
405
        }
406
        case RL2_SAMPLE_UINT32:
407
        {
408
            nBits = 32;
409
            eDT = GDT_UInt32;
410
            break;
411
        }
412
        case RL2_SAMPLE_FLOAT:
413
        {
414
            nBits = 32;
415
            eDT = GDT_Float32;
416
            break;
417
        }
418
        case RL2_SAMPLE_DOUBLE:
419
        {
420
            nBits = 64;
421
            eDT = GDT_Float64;
422
            break;
423
        }
424
    }
425

426
    // Get information about compression (informative)
427
    unsigned char nCompression = 0;
428
    int nQuality = 0;
429
    rl2_get_coverage_compression(m_pRL2Coverage, &nCompression, &nQuality);
430
    const char *pszCompression = nullptr;
431
    switch (nCompression)
432
    {
433
        case RL2_COMPRESSION_DEFLATE:
434
        case RL2_COMPRESSION_DEFLATE_NO:
435
            pszCompression = "DEFLATE";
436
            break;
437
        case RL2_COMPRESSION_LZMA:
438
        case RL2_COMPRESSION_LZMA_NO:
439
            pszCompression = "LZMA";
440
            break;
441
        case RL2_COMPRESSION_GIF:
442
            pszCompression = "GIF";
443
            break;
444
        case RL2_COMPRESSION_JPEG:
445
            pszCompression = "JPEG";
446
            break;
447
        case RL2_COMPRESSION_PNG:
448
            pszCompression = "PNG";
449
            break;
450
        case RL2_COMPRESSION_LOSSY_WEBP:
451
            pszCompression = "WEBP";
452
            break;
453
        case RL2_COMPRESSION_LOSSLESS_WEBP:
454
            pszCompression = "WEBP_LOSSLESS";
455
            break;
456
        case RL2_COMPRESSION_CCITTFAX3:
457
            pszCompression = "CCITTFAX3";
458
            break;
459
        case RL2_COMPRESSION_CCITTFAX4:
460
            pszCompression = "CCITTFAX4";
461
            break;
462
        case RL2_COMPRESSION_LZW:
463
            pszCompression = "LZW";
464
            break;
465
        case RL2_COMPRESSION_LOSSY_JP2:
466
            pszCompression = "JPEG2000";
467
            break;
468
        case RL2_COMPRESSION_LOSSLESS_JP2:
469
            pszCompression = "JPEG2000_LOSSLESS";
470
            break;
471
        default:
472
            break;
473
    }
474

475
    if (pszCompression != nullptr)
476
    {
477
        GDALDataset::SetMetadataItem("COMPRESSION", pszCompression,
478
                                     "IMAGE_STRUCTURE");
479
    }
480

481
    if (nQuality != 0 && (nCompression == RL2_COMPRESSION_JPEG ||
482
                          nCompression == RL2_COMPRESSION_LOSSY_WEBP ||
483
                          nCompression == RL2_COMPRESSION_LOSSY_JP2))
484
    {
485
        GDALDataset::SetMetadataItem("QUALITY", CPLSPrintf("%d", nQuality),
486
                                     "IMAGE_STRUCTURE");
487
    }
488

489
    // Get tile dimensions
490
    unsigned int nTileWidth = 0;
491
    unsigned int nTileHeight = 0;
492
    rl2_get_coverage_tile_size(m_pRL2Coverage, &nTileWidth, &nTileHeight);
493
    if (nTileWidth == 0 || nTileHeight == 0 || nTileWidth > INT_MAX ||
494
        nTileHeight > INT_MAX)
495
    {
496
        CPLError(CE_Failure, CPLE_AppDefined, "Invalid block size");
497
        return false;
498
    }
499
    const int nBlockXSize = static_cast<int>(nTileWidth);
500
    const int nBlockYSize = static_cast<int>(nTileHeight);
501

502
    // Fetch nodata values
503
    std::vector<double> adfNoDataValues;
504
    rl2PixelPtr noDataPtr = rl2_get_coverage_no_data(m_pRL2Coverage);
505
    if (noDataPtr != nullptr)
506
    {
507
        unsigned char noDataSampleType = 0;
508
        unsigned char noDataPixelType = 0;
509
        unsigned char noDataBands = 0;
510
        if (rl2_get_pixel_type(noDataPtr, &noDataSampleType, &noDataPixelType,
511
                               &noDataBands) == RL2_OK &&
512
            noDataSampleType == nSampleType && noDataPixelType == nPixelType &&
513
            noDataBands == l_nBands)
514
        {
515
            for (int i = 0; i < l_nBands; ++i)
516
            {
517
                double dfNoDataValue = 0.0;
518
                switch (nSampleType)
519
                {
520
                    default:
521
                    {
522
                        break;
523
                    }
524
                    case RL2_SAMPLE_1_BIT:
525
                    {
526
                        unsigned char nVal = 0;
527
                        rl2_get_pixel_sample_1bit(noDataPtr, &nVal);
528
                        dfNoDataValue = nVal;
529
                        break;
530
                    }
531
                    case RL2_SAMPLE_2_BIT:
532
                    {
533
                        unsigned char nVal = 0;
534
                        rl2_get_pixel_sample_2bit(noDataPtr, &nVal);
535
                        dfNoDataValue = nVal;
536
                        break;
537
                    }
538
                    case RL2_SAMPLE_4_BIT:
539
                    {
540
                        unsigned char nVal = 0;
541
                        rl2_get_pixel_sample_4bit(noDataPtr, &nVal);
542
                        dfNoDataValue = nVal;
543
                        break;
544
                    }
545
                    case RL2_SAMPLE_INT8:
546
                    {
547
                        char nVal = 0;
548
                        rl2_get_pixel_sample_int8(noDataPtr, &nVal);
549
                        dfNoDataValue = nVal;
550
                        break;
551
                    }
552
                    case RL2_SAMPLE_UINT8:
553
                    {
554
                        unsigned char nVal = 0;
555
                        rl2_get_pixel_sample_uint8(noDataPtr, i, &nVal);
556
                        dfNoDataValue = nVal;
557
                        break;
558
                    }
559
                    case RL2_SAMPLE_INT16:
560
                    {
561
                        short nVal = 0;
562
                        rl2_get_pixel_sample_int16(noDataPtr, &nVal);
563
                        dfNoDataValue = nVal;
564
                        break;
565
                    }
566
                    case RL2_SAMPLE_UINT16:
567
                    {
568
                        unsigned short nVal = 0;
569
                        rl2_get_pixel_sample_uint16(noDataPtr, i, &nVal);
570
                        dfNoDataValue = nVal;
571
                        break;
572
                    }
573
                    case RL2_SAMPLE_INT32:
574
                    {
575
                        int nVal = 0;
576
                        rl2_get_pixel_sample_int32(noDataPtr, &nVal);
577
                        dfNoDataValue = nVal;
578
                        break;
579
                    }
580
                    case RL2_SAMPLE_UINT32:
581
                    {
582
                        unsigned int nVal = 0;
583
                        rl2_get_pixel_sample_uint32(noDataPtr, &nVal);
584
                        dfNoDataValue = nVal;
585
                        break;
586
                    }
587
                    case RL2_SAMPLE_FLOAT:
588
                    {
589
                        float fVal = 0.0f;
590
                        rl2_get_pixel_sample_float(noDataPtr, &fVal);
591
                        dfNoDataValue = fVal;
592
                        break;
593
                    }
594
                    case RL2_SAMPLE_DOUBLE:
595
                    {
596
                        double dfVal = 0.0;
597
                        rl2_get_pixel_sample_double(noDataPtr, &dfVal);
598
                        dfNoDataValue = dfVal;
599
                        break;
600
                    }
601
                }
602

603
                adfNoDataValues.push_back(dfNoDataValue);
604
            }
605
        }
606

607
        // Do not destroy noDataPtr. It belongs to m_pRL2Coverage
608
    }
609

610
    // The nodata concept in RasterLite2 is equivalent to the NODATA_VALUES
611
    // one of GDAL: the nodata value must be matched simultaneously on all
612
    // bands.
613
    if (adfNoDataValues.size() == l_nBands && l_nBands > 1)
614
    {
615
        CPLString osNoDataValues;
616
        for (int i = 0; i < l_nBands; i++)
617
        {
618
            if (!osNoDataValues.empty())
619
                osNoDataValues += " ";
620
            osNoDataValues += CPLSPrintf("%g", adfNoDataValues[i]);
621
        }
622
        GDALDataset::SetMetadataItem("NODATA_VALUES", osNoDataValues.c_str());
623
    }
624

625
    for (int iBand = 1; iBand <= l_nBands; ++iBand)
626
    {
627
        const bool bHasNoData = adfNoDataValues.size() == 1 && l_nBands == 1;
628
        const double dfNoDataValue = bHasNoData ? adfNoDataValues[0] : 0.0;
629
        SetBand(iBand,
630
                new RL2RasterBand(iBand, nPixelType, eDT, nBits,
631
                                  m_bPromote1BitAs8Bit, nBlockXSize,
632
                                  nBlockYSize, bHasNoData, dfNoDataValue));
633
    }
634

635
    // Fetch statistics
636
    if (m_nSectionId < 0 || bSingleSection)
637
    {
638
        rl2RasterStatisticsPtr pStatistics =
639
            rl2_create_raster_statistics_from_dbms(hDB, nullptr,
640
                                                   m_osCoverageName);
641
        if (pStatistics != nullptr)
642
        {
643
            for (int iBand = 1; iBand <= l_nBands; ++iBand)
644
            {
645
                GDALRasterBand *poBand = GetRasterBand(iBand);
646
                double dfMin = 0.0;
647
                double dfMax = 0.0;
648
                double dfMean = 0.0;
649
                double dfVariance = 0.0;
650
                double dfStdDev = 0.0;
651
                if (!(nBits == 1 && m_bPromote1BitAs8Bit) &&
652
                    rl2_get_band_statistics(
653
                        pStatistics, static_cast<unsigned char>(iBand - 1),
654
                        &dfMin, &dfMax, &dfMean, &dfVariance,
655
                        &dfStdDev) == RL2_OK)
656
                {
657
                    poBand->GDALRasterBand::SetMetadataItem(
658
                        "STATISTICS_MINIMUM", CPLSPrintf("%.16g", dfMin));
659
                    poBand->GDALRasterBand::SetMetadataItem(
660
                        "STATISTICS_MAXIMUM", CPLSPrintf("%.16g", dfMax));
661
                    poBand->GDALRasterBand::SetMetadataItem(
662
                        "STATISTICS_MEAN", CPLSPrintf("%.16g", dfMean));
663
                    poBand->GDALRasterBand::SetMetadataItem(
664
                        "STATISTICS_STDDEV", CPLSPrintf("%.16g", dfStdDev));
665
                }
666
            }
667
            rl2_destroy_raster_statistics(pStatistics);
668
        }
669
    }
670

671
    // Fetch other metadata
672
    char *pszSQL =
673
        sqlite3_mprintf("SELECT title, abstract FROM raster_coverages WHERE "
674
                        "Lower(coverage_name) = Lower('%q') LIMIT 1",
675
                        m_osCoverageName.c_str());
676
    char **papszResults = nullptr;
677
    int nRowCount = 0;
678
    int nColCount = 0;
679
    int rc = sqlite3_get_table(hDB, pszSQL, &papszResults, &nRowCount,
680
                               &nColCount, nullptr);
681
    sqlite3_free(pszSQL);
682
    if (rc == SQLITE_OK)
683
    {
684
        if (nRowCount == 1)
685
        {
686
            const char *pszTitle = papszResults[2 + 0];
687
            const char *pszAbstract = papszResults[2 + 1];
688
            if (pszTitle != nullptr && pszTitle[0] != '\0' &&
689
                !EQUAL(pszTitle, "*** missing Title ***"))
690
            {
691
                GDALDataset::SetMetadataItem("COVERAGE_TITLE", pszTitle);
692
            }
693
            if (pszAbstract != nullptr && pszAbstract[0] != '\0' &&
694
                !EQUAL(pszAbstract, "*** missing Abstract ***"))
695
            {
696
                GDALDataset::SetMetadataItem("COVERAGE_ABSTRACT", pszAbstract);
697
            }
698
        }
699
        sqlite3_free_table(papszResults);
700
    }
701

702
    if (m_nSectionId >= 0)
703
    {
704
        papszResults = nullptr;
705
        nRowCount = 0;
706
        nColCount = 0;
707
        pszSQL =
708
            sqlite3_mprintf("SELECT summary FROM \"%w\" WHERE "
709
                            "section_id = %d LIMIT 1",
710
                            CPLSPrintf("%s_sections", m_osCoverageName.c_str()),
711
                            static_cast<int>(m_nSectionId));
712
        rc = sqlite3_get_table(hDB, pszSQL, &papszResults, &nRowCount,
713
                               &nColCount, nullptr);
714
        sqlite3_free(pszSQL);
715
        if (rc == SQLITE_OK)
716
        {
717
            if (nRowCount == 1)
718
            {
719
                const char *pszSummary = papszResults[1 + 0];
720
                if (pszSummary != nullptr && pszSummary[0] != '\0')
721
                {
722
                    GDALDataset::SetMetadataItem("SECTION_SUMMARY", pszSummary);
723
                }
724
            }
725
            sqlite3_free_table(papszResults);
726
        }
727
    }
728

729
    // Instantiate overviews
730
    int nStrictResolution = 0;
731
    int nMixedResolutions = 0;
732
    int nSectionPaths = 0;
733
    int nSectionMD5 = 0;
734
    int nSectionSummary = 0;
735
    rl2_get_coverage_policies(m_pRL2Coverage, &nStrictResolution,
736
                              &nMixedResolutions, &nSectionPaths, &nSectionMD5,
737
                              &nSectionSummary);
738
    m_bRL2MixedResolutions = CPL_TO_BOOL(nMixedResolutions);
739

740
    ListOverviews();
741

742
    return true;
743
#else   // !defined(HAVE_RASTERLITE2)
744
    return false;
×
745
#endif  // HAVE_RASTERLITE2
746
}
747

748
#ifdef HAVE_RASTERLITE2
749

750
/************************************************************************/
751
/*                          ListOverviews()                             */
752
/************************************************************************/
753

754
void OGRSQLiteDataSource::ListOverviews()
755
{
756
    if (!m_bRL2MixedResolutions || m_nSectionId >= 0)
757
    {
758
        char *pszSQL;
759
        if (!m_bRL2MixedResolutions)
760
        {
761
            pszSQL = sqlite3_mprintf(
762
                "SELECT x_resolution_1_1, y_resolution_1_1, "
763
                "x_resolution_1_2, y_resolution_1_2, "
764
                "x_resolution_1_4, y_resolution_1_4,"
765
                "x_resolution_1_8, y_resolution_1_8 "
766
                "FROM \"%w\" ORDER BY pyramid_level "
767
                "LIMIT 1000",
768
                CPLSPrintf("%s_levels", m_osCoverageName.c_str()));
769
        }
770
        else
771
        {
772
            pszSQL = sqlite3_mprintf(
773
                "SELECT x_resolution_1_1, y_resolution_1_1, "
774
                "x_resolution_1_2, y_resolution_1_2, "
775
                "x_resolution_1_4, y_resolution_1_4,"
776
                "x_resolution_1_8, y_resolution_1_8 "
777
                "FROM \"%w\" WHERE section_id = %d "
778
                "ORDER BY pyramid_level "
779
                "LIMIT 1000",
780
                CPLSPrintf("%s_section_levels", m_osCoverageName.c_str()),
781
                static_cast<int>(m_nSectionId));
782
        }
783
        char **papszResults = nullptr;
784
        int nRowCount = 0;
785
        int nColCount = 0;
786
        char *pszErrMsg = nullptr;
787
        int rc = sqlite3_get_table(hDB, pszSQL, &papszResults, &nRowCount,
788
                                   &nColCount, &pszErrMsg);
789
        sqlite3_free(pszSQL);
790
        if (pszErrMsg)
791
            CPLDebug("SQLite", "%s", pszErrMsg);
792
        sqlite3_free(pszErrMsg);
793
        if (rc == SQLITE_OK)
794
        {
795
            for (int i = 0; i < nRowCount; ++i)
796
            {
797
                const char *const *papszRow = papszResults + i * 8 + 8;
798
                const char *pszXRes1 = papszRow[0];
799
                const char *pszYRes1 = papszRow[1];
800
                const char *pszXRes2 = papszRow[2];
801
                const char *pszYRes2 = papszRow[3];
802
                const char *pszXRes4 = papszRow[4];
803
                const char *pszYRes4 = papszRow[5];
804
                const char *pszXRes8 = papszRow[6];
805
                const char *pszYRes8 = papszRow[7];
806
                if (pszXRes1 != nullptr && pszYRes1 != nullptr)
807
                {
808
                    CreateRL2OverviewDatasetIfNeeded(CPLAtof(pszXRes1),
809
                                                     CPLAtof(pszYRes1));
810
                }
811
                if (pszXRes2 != nullptr && pszYRes2 != nullptr)
812
                {
813
                    CreateRL2OverviewDatasetIfNeeded(CPLAtof(pszXRes2),
814
                                                     CPLAtof(pszYRes2));
815
                }
816
                if (pszXRes4 != nullptr && pszYRes4 != nullptr)
817
                {
818
                    CreateRL2OverviewDatasetIfNeeded(CPLAtof(pszXRes4),
819
                                                     CPLAtof(pszYRes4));
820
                }
821
                if (pszXRes8 != nullptr && pszYRes8 != nullptr)
822
                {
823
                    CreateRL2OverviewDatasetIfNeeded(CPLAtof(pszXRes8),
824
                                                     CPLAtof(pszYRes8));
825
                }
826
            }
827
            sqlite3_free_table(papszResults);
828
        }
829
    }
830
}
831

832
/************************************************************************/
833
/*                    CreateRL2OverviewDatasetIfNeeded()                   */
834
/************************************************************************/
835

836
void OGRSQLiteDataSource::CreateRL2OverviewDatasetIfNeeded(double dfXRes,
837
                                                           double dfYRes)
838
{
839
    if (fabs(dfXRes - m_gt[1]) < 1e-5 * m_gt[1])
840
        return;
841

842
    for (size_t i = 0; i < m_apoOverviewDS.size(); ++i)
843
    {
844
        if (fabs(dfXRes - m_apoOverviewDS[i]->m_gt[1]) <
845
            1e-5 * m_apoOverviewDS[i]->m_gt[1])
846
        {
847
            return;
848
        }
849
    }
850

851
    OGRSQLiteDataSource *poOvrDS = new OGRSQLiteDataSource();
852
    poOvrDS->bIsInternal = true;
853
    poOvrDS->m_poParentDS = this;
854
    poOvrDS->m_osCoverageName = m_osCoverageName;
855
    poOvrDS->m_nSectionId = m_nSectionId;
856
    poOvrDS->m_bPromote1BitAs8Bit = m_bPromote1BitAs8Bit;
857
    poOvrDS->m_bRL2MixedResolutions = m_bRL2MixedResolutions;
858
    poOvrDS->m_gt[0] = m_gt[0];
859
    poOvrDS->m_gt[1] = dfXRes;
860
    poOvrDS->m_gt[3] = m_gt[3];
861
    poOvrDS->m_gt[5] = -dfYRes;
862
    const double dfMinX = m_gt[0];
863
    const double dfMaxX = dfMinX + m_gt[1] * nRasterXSize;
864
    const double dfMaxY = m_gt[3];
865
    const double dfMinY = dfMaxY + m_gt[5] * nRasterYSize;
866
    poOvrDS->nRasterXSize = static_cast<int>(0.5 + (dfMaxX - dfMinX) / dfXRes);
867
    poOvrDS->nRasterYSize = static_cast<int>(0.5 + (dfMaxY - dfMinY) / dfYRes);
868
    if (poOvrDS->nRasterXSize <= 1 || poOvrDS->nRasterYSize <= 1 ||
869
        (poOvrDS->nRasterXSize < 64 && poOvrDS->nRasterYSize < 64 &&
870
         !CPLTestBool(CPLGetConfigOption("RL2_SHOW_ALL_PYRAMID_LEVELS", "NO"))))
871
    {
872
        delete poOvrDS;
873
        return;
874
    }
875
    for (int iBand = 1; iBand <= nBands; ++iBand)
876
    {
877
        poOvrDS->SetBand(iBand,
878
                         new RL2RasterBand(reinterpret_cast<RL2RasterBand *>(
879
                             GetRasterBand(iBand))));
880
    }
881
    m_apoOverviewDS.push_back(poOvrDS);
882
}
883

884
/************************************************************************/
885
/*                            RL2RasterBand()                           */
886
/************************************************************************/
887

888
RL2RasterBand::RL2RasterBand(int nBandIn, int nPixelType, GDALDataType eDT,
889
                             int nBits, bool bPromote1BitAs8Bit,
890
                             int nBlockXSizeIn, int nBlockYSizeIn,
891
                             bool bHasNoDataIn, double dfNoDataValueIn)
892
    : m_bHasNoData(bHasNoDataIn), m_dfNoDataValue(dfNoDataValueIn),
893
      m_eColorInterp(GCI_Undefined), m_poCT(nullptr)
894
{
895
    eDataType = eDT;
896
    nBlockXSize = nBlockXSizeIn;
897
    nBlockYSize = nBlockYSizeIn;
898
    if ((nBits % 8) != 0)
899
    {
900
        GDALRasterBand::SetMetadataItem(
901
            (nBits == 1 && bPromote1BitAs8Bit) ? "SOURCE_NBITS" : "NBITS",
902
            CPLSPrintf("%d", nBits), "IMAGE_STRUCTURE");
903
    }
904

905
    if (nPixelType == RL2_PIXEL_MONOCHROME || nPixelType == RL2_PIXEL_GRAYSCALE)
906
    {
907
        m_eColorInterp = GCI_GrayIndex;
908
    }
909
    else if (nPixelType == RL2_PIXEL_PALETTE)
910
    {
911
        m_eColorInterp = GCI_PaletteIndex;
912
    }
913
    else if (nPixelType == RL2_PIXEL_RGB)
914
    {
915
        m_eColorInterp =
916
            static_cast<GDALColorInterp>(GCI_RedBand + nBandIn - 1);
917
    }
918
}
919

920
/************************************************************************/
921
/*                            RL2RasterBand()                           */
922
/************************************************************************/
923

924
RL2RasterBand::RL2RasterBand(const RL2RasterBand *poOther)
925
{
926
    eDataType = poOther->eDataType;
927
    nBlockXSize = poOther->nBlockXSize;
928
    nBlockYSize = poOther->nBlockYSize;
929
    GDALRasterBand::SetMetadataItem(
930
        "NBITS",
931
        const_cast<RL2RasterBand *>(poOther)->GetMetadataItem(
932
            "NBITS", "IMAGE_STRUCTURE"),
933
        "IMAGE_STRUCTURE");
934
    m_eColorInterp = poOther->m_eColorInterp;
935
    m_bHasNoData = poOther->m_bHasNoData;
936
    m_dfNoDataValue = poOther->m_dfNoDataValue;
937
    m_poCT = nullptr;
938
}
939

940
/************************************************************************/
941
/*                           ~RL2RasterBand()                           */
942
/************************************************************************/
943

944
RL2RasterBand::~RL2RasterBand()
945
{
946
    delete m_poCT;
947
}
948

949
/************************************************************************/
950
/*                          GetColorTable()                             */
951
/************************************************************************/
952

953
GDALColorTable *RL2RasterBand::GetColorTable()
954
{
955
    OGRSQLiteDataSource *poGDS = reinterpret_cast<OGRSQLiteDataSource *>(poDS);
956
    if (m_poCT == nullptr && m_eColorInterp == GCI_PaletteIndex)
957
    {
958
        rl2PalettePtr palettePtr = rl2_get_dbms_palette(
959
            poGDS->GetDB(), nullptr,
960
            rl2_get_coverage_name(poGDS->GetRL2CoveragePtr()));
961
        if (palettePtr)
962
        {
963
            m_poCT = new GDALColorTable();
964
            unsigned short nEntries = 0;
965
            unsigned char *pabyR = nullptr;
966
            unsigned char *pabyG = nullptr;
967
            unsigned char *pabyB = nullptr;
968
            if (rl2_get_palette_colors(palettePtr, &nEntries, &pabyR, &pabyG,
969
                                       &pabyB) == RL2_OK)
970
            {
971
                for (int i = 0; i < nEntries; ++i)
972
                {
973
                    GDALColorEntry sEntry;
974
                    sEntry.c1 = pabyR[i];
975
                    sEntry.c2 = pabyG[i];
976
                    sEntry.c3 = pabyB[i];
977
                    sEntry.c4 =
978
                        (m_bHasNoData && i == m_dfNoDataValue) ? 0 : 255;
979
                    m_poCT->SetColorEntry(i, &sEntry);
980
                }
981
                rl2_free(pabyR);
982
                rl2_free(pabyG);
983
                rl2_free(pabyB);
984
            }
985
            rl2_destroy_palette(palettePtr);
986
        }
987
    }
988
    return m_poCT;
989
}
990

991
/************************************************************************/
992
/*                          GetOverviewCount()                          */
993
/************************************************************************/
994

995
int RL2RasterBand::GetOverviewCount()
996
{
997
    OGRSQLiteDataSource *poGDS = reinterpret_cast<OGRSQLiteDataSource *>(poDS);
998
    int nRet = static_cast<int>(poGDS->GetOverviews().size());
999
    if (nRet > 0)
1000
        return nRet;
1001
    return GDALPamRasterBand::GetOverviewCount();
1002
}
1003

1004
/************************************************************************/
1005
/*                           GetOverview()                              */
1006
/************************************************************************/
1007

1008
GDALRasterBand *RL2RasterBand::GetOverview(int nIdx)
1009
{
1010
    OGRSQLiteDataSource *poGDS = reinterpret_cast<OGRSQLiteDataSource *>(poDS);
1011
    int nOvr = static_cast<int>(poGDS->GetOverviews().size());
1012
    if (nOvr > 0)
1013
    {
1014
        if (nIdx < 0 || nIdx >= nOvr)
1015
            return nullptr;
1016
        return poGDS->GetOverviews()[nIdx]->GetRasterBand(nBand);
1017
    }
1018
    return GDALPamRasterBand::GetOverview(nIdx);
1019
}
1020

1021
/************************************************************************/
1022
/*                          GetNoDataValue()                            */
1023
/************************************************************************/
1024

1025
double RL2RasterBand::GetNoDataValue(int *pbSuccess)
1026
{
1027
    if (m_bHasNoData)
1028
    {
1029
        if (pbSuccess)
1030
            *pbSuccess = TRUE;
1031
        return m_dfNoDataValue;
1032
    }
1033
    return GDALPamRasterBand::GetNoDataValue(pbSuccess);
1034
}
1035

1036
/************************************************************************/
1037
/*                             IReadBlock()                             */
1038
/************************************************************************/
1039

1040
CPLErr RL2RasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pData)
1041
{
1042
    OGRSQLiteDataSource *poGDS = reinterpret_cast<OGRSQLiteDataSource *>(poDS);
1043
#ifdef DEBUG_VERBOSE
1044
    CPLDebug("SQLite", "IReadBlock(ds=%p, band=%d, x=%d, y=%d)", poGDS, nBand,
1045
             nBlockXOff, nBlockYOff);
1046
#endif
1047

1048
    const int nMaxThreads = 1;
1049
    const auto &gt = poGDS->GetGeoTransform();
1050
    const double dfMinX = gt[0] + nBlockXOff * nBlockXSize * gt[1];
1051
    const double dfMaxX = dfMinX + nBlockXSize * gt[1];
1052
    const double dfMaxY = gt[3] + nBlockYOff * nBlockYSize * gt[5];
1053
    const double dfMinY = dfMaxY + nBlockYSize * gt[5];
1054
    unsigned char *pBuffer = nullptr;
1055
    int nBufSize = 0;
1056

1057
    sqlite3 *hDB =
1058
        poGDS->GetParentDS() ? poGDS->GetParentDS()->GetDB() : poGDS->GetDB();
1059
    rl2CoveragePtr cov = poGDS->GetParentDS()
1060
                             ? poGDS->GetParentDS()->GetRL2CoveragePtr()
1061
                             : poGDS->GetRL2CoveragePtr();
1062
    unsigned char nSampleType = 0;
1063
    unsigned char nPixelType = 0;
1064
    unsigned char l_nBands = 0;
1065
    rl2_get_coverage_type(cov, &nSampleType, &nPixelType, &l_nBands);
1066

1067
    unsigned char nOutPixel = nPixelType;
1068
    if (nPixelType == RL2_PIXEL_MONOCHROME && nSampleType == RL2_SAMPLE_1_BIT)
1069
    {
1070
        nOutPixel = RL2_PIXEL_GRAYSCALE;
1071
    }
1072

1073
    const GIntBig nSectionId = poGDS->GetSectionId();
1074
    if (nSectionId >= 0 &&
1075
        (poGDS->IsRL2MixedResolutions() || poGDS->GetParentDS() == nullptr))
1076
    {
1077
        int ret = rl2_get_section_raw_raster_data(
1078
            hDB, nMaxThreads, cov, nSectionId, nBlockXSize, nBlockYSize, dfMinX,
1079
            dfMinY, dfMaxX, dfMaxY, gt[1], fabs(gt[5]), &pBuffer, &nBufSize,
1080
            nullptr,  // palette
1081
            nOutPixel);
1082
        if (ret != RL2_OK)
1083
            return CE_Failure;
1084
    }
1085
    else
1086
    {
1087
        int ret = rl2_get_raw_raster_data(
1088
            hDB, nMaxThreads, cov, nBlockXSize, nBlockYSize, dfMinX, dfMinY,
1089
            dfMaxX, dfMaxY, gt[1], fabs(gt[5]), &pBuffer, &nBufSize,
1090
            nullptr,  // palette
1091
            nOutPixel);
1092
        if (ret != RL2_OK)
1093
            return CE_Failure;
1094
    }
1095

1096
    const int nDTSize = GDALGetDataTypeSizeBytes(eDataType);
1097
    const int nExpectedBytesOnBand = nBlockXSize * nBlockYSize * nDTSize;
1098
    const int nBands = poGDS->GetRasterCount();
1099
    const int nExpectedBytesAllBands = nExpectedBytesOnBand * nBands;
1100
    if (nBufSize != nExpectedBytesAllBands)
1101
    {
1102
        CPLDebug("SQLite", "Got %d bytes instead of %d", nBufSize,
1103
                 nExpectedBytesAllBands);
1104
        rl2_free(pBuffer);
1105
        return CE_Failure;
1106
    }
1107

1108
    if (nPixelType == RL2_PIXEL_MONOCHROME && nSampleType == RL2_SAMPLE_1_BIT &&
1109
        !poGDS->HasPromote1BitAS8Bit() && poGDS->GetParentDS() != nullptr)
1110
    {
1111
        GByte *pabyDstData = static_cast<GByte *>(pData);
1112
        for (int i = 0; i < nExpectedBytesAllBands; i++)
1113
        {
1114
            pabyDstData[i] = (pBuffer[i] > 127) ? 1 : 0;
1115
        }
1116
    }
1117
    else
1118
    {
1119
        GDALCopyWords(pBuffer + (nBand - 1) * nDTSize, eDataType,
1120
                      nDTSize * nBands, pData, eDataType, nDTSize,
1121
                      nBlockXSize * nBlockYSize);
1122
    }
1123

1124
    if (nBands > 1)
1125
    {
1126
        for (int iBand = 1; iBand <= nBands; ++iBand)
1127
        {
1128
            if (iBand == nBand)
1129
                continue;
1130

1131
            GDALRasterBlock *poBlock =
1132
                reinterpret_cast<RL2RasterBand *>(poGDS->GetRasterBand(iBand))
1133
                    ->TryGetLockedBlockRef(nBlockXOff, nBlockYOff);
1134
            if (poBlock != nullptr)
1135
            {
1136
                poBlock->DropLock();
1137
                continue;
1138
            }
1139
            poBlock =
1140
                reinterpret_cast<RL2RasterBand *>(poGDS->GetRasterBand(iBand))
1141
                    ->GetLockedBlockRef(nBlockXOff, nBlockYOff, TRUE);
1142
            if (poBlock == nullptr)
1143
                continue;
1144
            void *pDest = poBlock->GetDataRef();
1145
            GDALCopyWords(pBuffer + (iBand - 1) * nDTSize, eDataType,
1146
                          nDTSize * nBands, pDest, eDataType, nDTSize,
1147
                          nBlockXSize * nBlockYSize);
1148

1149
            poBlock->DropLock();
1150
        }
1151
    }
1152

1153
    rl2_free(pBuffer);
1154

1155
    return CE_None;
1156
}
1157

1158
/************************************************************************/
1159
/*                          GetNoDataValue()                            */
1160
/************************************************************************/
1161

1162
template <class T>
1163
static T GetNoDataValue(GDALDataset *poSrcDS, int nBand, T nDefault)
1164
{
1165
    int bHasNoData = FALSE;
1166
    double dfNoData =
1167
        poSrcDS->GetRasterBand(nBand)->GetNoDataValue(&bHasNoData);
1168
    if (bHasNoData)
1169
        return static_cast<T>(dfNoData);
1170
    return static_cast<T>(nDefault);
1171
}
1172

1173
/************************************************************************/
1174
/*                          CreateNoData()                              */
1175
/************************************************************************/
1176

1177
static rl2PixelPtr CreateNoData(unsigned char nSampleType,
1178
                                unsigned char nPixelType,
1179
                                unsigned char nBandCount, GDALDataset *poSrcDS)
1180
{
1181
    // creating a default NO-DATA value
1182
    rl2PixelPtr pxl = rl2_create_pixel(nSampleType, nPixelType, nBandCount);
1183
    if (pxl == nullptr)
1184
        return nullptr;
1185
    switch (nPixelType)
1186
    {
1187
        case RL2_PIXEL_MONOCHROME:
1188
            rl2_set_pixel_sample_1bit(pxl,
1189
                                      GetNoDataValue<GByte>(poSrcDS, 1, 0));
1190
            break;
1191
        case RL2_PIXEL_PALETTE:
1192
            switch (nSampleType)
1193
            {
1194
                case RL2_SAMPLE_1_BIT:
1195
                    rl2_set_pixel_sample_1bit(
1196
                        pxl, GetNoDataValue<GByte>(poSrcDS, 1, 0));
1197
                    break;
1198
                case RL2_SAMPLE_2_BIT:
1199
                    rl2_set_pixel_sample_2bit(
1200
                        pxl, GetNoDataValue<GByte>(poSrcDS, 1, 0));
1201
                    break;
1202
                case RL2_SAMPLE_4_BIT:
1203
                    rl2_set_pixel_sample_4bit(
1204
                        pxl, GetNoDataValue<GByte>(poSrcDS, 1, 0));
1205
                    break;
1206
                case RL2_SAMPLE_UINT8:
1207
                    rl2_set_pixel_sample_uint8(
1208
                        pxl, 0, GetNoDataValue<GByte>(poSrcDS, 1, 0));
1209
                    break;
1210
                default:
1211
                    CPLAssert(false);
1212
                    break;
1213
            }
1214
            break;
1215
        case RL2_PIXEL_GRAYSCALE:
1216
            switch (nSampleType)
1217
            {
1218
                case RL2_SAMPLE_1_BIT:
1219
                    rl2_set_pixel_sample_1bit(
1220
                        pxl, GetNoDataValue<GByte>(poSrcDS, 1, 1));
1221
                    break;
1222
                case RL2_SAMPLE_2_BIT:
1223
                    rl2_set_pixel_sample_2bit(
1224
                        pxl, GetNoDataValue<GByte>(poSrcDS, 1, 3));
1225
                    break;
1226
                case RL2_SAMPLE_4_BIT:
1227
                    rl2_set_pixel_sample_4bit(
1228
                        pxl, GetNoDataValue<GByte>(poSrcDS, 1, 15));
1229
                    break;
1230
                case RL2_SAMPLE_UINT8:
1231
                    rl2_set_pixel_sample_uint8(
1232
                        pxl, 0, GetNoDataValue<GByte>(poSrcDS, 1, 255));
1233
                    break;
1234
                case RL2_SAMPLE_UINT16:
1235
                    rl2_set_pixel_sample_uint16(
1236
                        pxl, 0, GetNoDataValue<GUInt16>(poSrcDS, 1, 0));
1237
                    break;
1238
                default:
1239
                    CPLAssert(false);
1240
                    break;
1241
            }
1242
            break;
1243
        case RL2_PIXEL_RGB:
1244
            switch (nSampleType)
1245
            {
1246
                case RL2_SAMPLE_UINT8:
1247
                    rl2_set_pixel_sample_uint8(
1248
                        pxl, 0, GetNoDataValue<GByte>(poSrcDS, 1, 255));
1249
                    rl2_set_pixel_sample_uint8(
1250
                        pxl, 1, GetNoDataValue<GByte>(poSrcDS, 2, 255));
1251
                    rl2_set_pixel_sample_uint8(
1252
                        pxl, 2, GetNoDataValue<GByte>(poSrcDS, 3, 255));
1253
                    break;
1254
                case RL2_SAMPLE_UINT16:
1255
                    rl2_set_pixel_sample_uint16(
1256
                        pxl, 0, GetNoDataValue<GUInt16>(poSrcDS, 1, 0));
1257
                    rl2_set_pixel_sample_uint16(
1258
                        pxl, 1, GetNoDataValue<GUInt16>(poSrcDS, 2, 0));
1259
                    rl2_set_pixel_sample_uint16(
1260
                        pxl, 2, GetNoDataValue<GUInt16>(poSrcDS, 3, 0));
1261
                    break;
1262
                default:
1263
                    CPLAssert(false);
1264
                    break;
1265
            }
1266
            break;
1267
        case RL2_PIXEL_DATAGRID:
1268
            switch (nSampleType)
1269
            {
1270
                case RL2_SAMPLE_INT8:
1271
                    rl2_set_pixel_sample_int8(
1272
                        pxl, GetNoDataValue<char>(poSrcDS, 1, 0));
1273
                    break;
1274
                case RL2_SAMPLE_UINT8:
1275
                    rl2_set_pixel_sample_uint8(
1276
                        pxl, 0, GetNoDataValue<GByte>(poSrcDS, 1, 0));
1277
                    break;
1278
                case RL2_SAMPLE_INT16:
1279
                    rl2_set_pixel_sample_int16(
1280
                        pxl, GetNoDataValue<GInt16>(poSrcDS, 1, 0));
1281
                    break;
1282
                case RL2_SAMPLE_UINT16:
1283
                    rl2_set_pixel_sample_uint16(
1284
                        pxl, 0, GetNoDataValue<GUInt16>(poSrcDS, 1, 0));
1285
                    break;
1286
                case RL2_SAMPLE_INT32:
1287
                    rl2_set_pixel_sample_int32(
1288
                        pxl, GetNoDataValue<GInt32>(poSrcDS, 1, 0));
1289
                    break;
1290
                case RL2_SAMPLE_UINT32:
1291
                    rl2_set_pixel_sample_uint32(
1292
                        pxl, GetNoDataValue<GUInt32>(poSrcDS, 1, 0));
1293
                    break;
1294
                case RL2_SAMPLE_FLOAT:
1295
                    rl2_set_pixel_sample_float(
1296
                        pxl, GetNoDataValue<float>(poSrcDS, 1, 0));
1297
                    break;
1298
                case RL2_SAMPLE_DOUBLE:
1299
                    rl2_set_pixel_sample_double(
1300
                        pxl, GetNoDataValue<double>(poSrcDS, 1, 0));
1301
                    break;
1302
                default:
1303
                    CPLAssert(false);
1304
                    break;
1305
            }
1306
            break;
1307
        case RL2_PIXEL_MULTIBAND:
1308
            switch (nSampleType)
1309
            {
1310
                case RL2_SAMPLE_UINT8:
1311
                    for (unsigned int nb = 0; nb < nBandCount; nb++)
1312
                        rl2_set_pixel_sample_uint8(
1313
                            pxl, nb,
1314
                            GetNoDataValue<GByte>(poSrcDS, nb + 1, 255));
1315
                    break;
1316
                case RL2_SAMPLE_UINT16:
1317
                    for (unsigned int nb = 0; nb < nBandCount; nb++)
1318
                        rl2_set_pixel_sample_uint16(
1319
                            pxl, nb,
1320
                            GetNoDataValue<GUInt16>(poSrcDS, nb + 1, 0));
1321
                    break;
1322
                default:
1323
                    CPLAssert(false);
1324
                    break;
1325
            }
1326
            break;
1327
        default:
1328
            CPLAssert(false);
1329
            break;
1330
    }
1331
    return pxl;
1332
}
1333

1334
/************************************************************************/
1335
/*                       RasterLite2Callback()                          */
1336
/************************************************************************/
1337

1338
struct RasterLite2CallbackData
1339
{
1340
    GDALDataset *poSrcDS{};
1341
    unsigned char nPixelType{};
1342
    unsigned char nSampleType{};
1343
    rl2PalettePtr pPalette{};
1344
    GDALProgressFunc pfnProgress{};
1345
    void *pProgressData{};
1346
    GDALGeoTransform gt{};
1347
};
1348

1349
static int RasterLite2Callback(void *data, double dfTileMinX, double dfTileMinY,
1350
                               double dfTileMaxX, double dfTileMaxY,
1351
                               unsigned char *pabyBuffer,
1352
                               rl2PalettePtr *pOutPalette)
1353
{
1354
#ifdef DEBUG_VERBOSE
1355
    CPLDebug("SQLite", "RasterLite2Callback(%f %f %f %f)", dfTileMinX,
1356
             dfTileMinY, dfTileMaxX, dfTileMaxY);
1357
#endif
1358
    RasterLite2CallbackData *pCbkData =
1359
        static_cast<RasterLite2CallbackData *>(data);
1360
    if (pOutPalette)
1361
    {
1362
        if (pCbkData->pPalette)
1363
            *pOutPalette = rl2_clone_palette(pCbkData->pPalette);
1364
        else
1365
            *pOutPalette = nullptr;
1366
    }
1367
    int nXOff = static_cast<int>(0.5 + (dfTileMinX - pCbkData->gt[0]) /
1368
                                           pCbkData->gt[1]);
1369
    int nXOff2 = static_cast<int>(0.5 + (dfTileMaxX - pCbkData->gt[0]) /
1370
                                            pCbkData->gt[1]);
1371
    int nYOff = static_cast<int>(0.5 + (dfTileMaxY - pCbkData->gt[3]) /
1372
                                           pCbkData->gt[5]);
1373
    int nYOff2 = static_cast<int>(0.5 + (dfTileMinY - pCbkData->gt[3]) /
1374
                                            pCbkData->gt[5]);
1375
    int nReqXSize = nXOff2 - nXOff;
1376
    bool bZeroInitialize = false;
1377
    if (nXOff2 > pCbkData->poSrcDS->GetRasterXSize())
1378
    {
1379
        bZeroInitialize = true;
1380
        nReqXSize = pCbkData->poSrcDS->GetRasterXSize() - nXOff;
1381
    }
1382
    int nReqYSize = nYOff2 - nYOff;
1383
    if (nYOff2 > pCbkData->poSrcDS->GetRasterYSize())
1384
    {
1385
        bZeroInitialize = true;
1386
        nReqYSize = pCbkData->poSrcDS->GetRasterYSize() - nYOff;
1387
    }
1388

1389
    GDALDataType eDT = pCbkData->poSrcDS->GetRasterBand(1)->GetRasterDataType();
1390
    int nDTSize = GDALGetDataTypeSizeBytes(eDT);
1391
    int nBands = pCbkData->poSrcDS->GetRasterCount();
1392
    if (bZeroInitialize)
1393
    {
1394
        memset(pabyBuffer, 0,
1395
               static_cast<size_t>(nXOff2 - nXOff) * (nYOff2 - nYOff) * nBands *
1396
                   nDTSize);
1397
    }
1398

1399
    const GSpacing nPixelSpacing = static_cast<GSpacing>(nDTSize) * nBands;
1400
    const GSpacing nLineSpacing = nPixelSpacing * (nXOff2 - nXOff);
1401
    CPLErr eErr = pCbkData->poSrcDS->RasterIO(
1402
        GF_Read, nXOff, nYOff, nReqXSize, nReqYSize, pabyBuffer, nReqXSize,
1403
        nReqYSize, eDT, nBands, nullptr, nPixelSpacing, nLineSpacing, nDTSize,
1404
        nullptr);
1405
    if (eErr != CE_None)
1406
        return FALSE;
1407

1408
    if (pCbkData->pfnProgress &&
1409
        !pCbkData->pfnProgress(static_cast<double>(nYOff + nReqYSize) /
1410
                                   pCbkData->poSrcDS->GetRasterYSize(),
1411
                               "", pCbkData->pProgressData))
1412
    {
1413
        return FALSE;
1414
    }
1415

1416
    int nMaxVal = 0;
1417
    if (pCbkData->nSampleType == RL2_SAMPLE_1_BIT)
1418
    {
1419
        nMaxVal = 1;
1420
    }
1421
    else if (pCbkData->nSampleType == RL2_SAMPLE_2_BIT)
1422
    {
1423
        nMaxVal = 3;
1424
    }
1425
    else if (pCbkData->nSampleType == RL2_SAMPLE_4_BIT)
1426
    {
1427
        nMaxVal = 7;
1428
    }
1429
    if (nMaxVal != 0)
1430
    {
1431
        bool bClamped = false;
1432
        for (int iY = 0; iY < nReqYSize; ++iY)
1433
        {
1434
            for (int iX = 0; iX < nReqXSize; ++iX)
1435
            {
1436
                GByte *pbyVal = pabyBuffer +
1437
                                static_cast<size_t>(iY) * (nXOff2 - nXOff) + iX;
1438
                if (*pbyVal > nMaxVal)
1439
                {
1440
                    if (!bClamped)
1441
                    {
1442
                        bClamped = true;
1443
                        CPLError(CE_Warning, CPLE_AppDefined,
1444
                                 "One or several values above %d have "
1445
                                 "been clamped",
1446
                                 nMaxVal);
1447
                    }
1448
                    *pbyVal = nMaxVal;
1449
                }
1450
            }
1451
        }
1452
    }
1453

1454
    return TRUE;
1455
}
1456

1457
/************************************************************************/
1458
/*                    OGRSQLiteDriverCreateCopy()                       */
1459
/************************************************************************/
1460

1461
GDALDataset *OGRSQLiteDriverCreateCopy(const char *pszName,
1462
                                       GDALDataset *poSrcDS, int /* bStrict */,
1463
                                       char **papszOptions,
1464
                                       GDALProgressFunc pfnProgress,
1465
                                       void *pProgressData)
1466
{
1467
    if (poSrcDS->GetRasterCount() == 0 || poSrcDS->GetRasterCount() > 255)
1468
    {
1469
        CPLError(CE_Failure, CPLE_NotSupported, "Unsupported band count");
1470
        return nullptr;
1471
    }
1472

1473
    GDALGeoTransform gt;
1474
    if (poSrcDS->GetGeoTransform(gt) == CE_None &&
1475
        (gt[2] != 0.0 || gt[4] != 0.0))
1476
    {
1477
        CPLError(CE_Failure, CPLE_NotSupported,
1478
                 "Raster with rotation/shearing geotransform terms "
1479
                 "are not supported");
1480
        return nullptr;
1481
    }
1482

1483
    if (CSLFetchNameValue(papszOptions, "APPEND_SUBDATASET") &&
1484
        !CSLFetchNameValue(papszOptions, "COVERAGE"))
1485
    {
1486
        CPLError(CE_Failure, CPLE_AppDefined,
1487
                 "COVERAGE must be specified with APPEND_SUBDATASET=YES");
1488
        return nullptr;
1489
    }
1490

1491
    GDALDataType eDT = poSrcDS->GetRasterBand(1)->GetRasterDataType();
1492

1493
    unsigned char nSampleType = RL2_SAMPLE_UINT8;
1494
    unsigned char nPixelType = RL2_PIXEL_GRAYSCALE;
1495
    unsigned char nBandCount =
1496
        static_cast<unsigned char>(poSrcDS->GetRasterCount());
1497

1498
    const char *pszPixelType = CSLFetchNameValue(papszOptions, "PIXEL_TYPE");
1499
    if (pszPixelType)
1500
    {
1501
        if (EQUAL(pszPixelType, "MONOCHROME"))
1502
            nPixelType = RL2_PIXEL_MONOCHROME;
1503
        else if (EQUAL(pszPixelType, "PALETTE"))
1504
            nPixelType = RL2_PIXEL_PALETTE;
1505
        else if (EQUAL(pszPixelType, "GRAYSCALE"))
1506
            nPixelType = RL2_PIXEL_GRAYSCALE;
1507
        else if (EQUAL(pszPixelType, "RGB"))
1508
            nPixelType = RL2_PIXEL_RGB;
1509
        else if (EQUAL(pszPixelType, "MULTIBAND"))
1510
            nPixelType = RL2_PIXEL_MULTIBAND;
1511
        else if (EQUAL(pszPixelType, "DATAGRID"))
1512
            nPixelType = RL2_PIXEL_DATAGRID;
1513
    }
1514
    else
1515
    {
1516
        // Guess a reasonable pixel type from band characteristics
1517
        if (nBandCount == 1 &&
1518
            poSrcDS->GetRasterBand(1)->GetColorTable() != nullptr)
1519
        {
1520
            nPixelType = RL2_PIXEL_PALETTE;
1521
        }
1522
        else if (nBandCount == 3 && (eDT == GDT_Byte || eDT == GDT_UInt16) &&
1523
                 poSrcDS->GetRasterBand(1)->GetColorInterpretation() ==
1524
                     GCI_RedBand &&
1525
                 poSrcDS->GetRasterBand(2)->GetColorInterpretation() ==
1526
                     GCI_GreenBand &&
1527
                 poSrcDS->GetRasterBand(3)->GetColorInterpretation() ==
1528
                     GCI_BlueBand)
1529
        {
1530
            nPixelType = RL2_PIXEL_RGB;
1531
        }
1532
        else if (nBandCount > 1 && (eDT == GDT_Byte || eDT == GDT_UInt16))
1533
        {
1534
            nPixelType = RL2_PIXEL_MULTIBAND;
1535
        }
1536
        else if (nBandCount == 1 && eDT != GDT_Byte)
1537
        {
1538
            nPixelType = RL2_PIXEL_DATAGRID;
1539
        }
1540
    }
1541

1542
    // Deal with NBITS
1543
    const char *pszNBITS = CSLFetchNameValue(papszOptions, "NBITS");
1544
    int nBITS = 0;
1545
    if (pszNBITS != nullptr)
1546
    {
1547
        nBITS = atoi(pszNBITS);
1548
        if (nBITS != 1 && nBITS != 2 && nBITS != 4 && nBITS != 8)
1549
        {
1550
            CPLError(CE_Failure, CPLE_NotSupported, "Unsupported NBITS value");
1551
            return nullptr;
1552
        }
1553
    }
1554
    else
1555
    {
1556
        pszNBITS = poSrcDS->GetRasterBand(1)->GetMetadataItem(
1557
            "NBITS", "IMAGE_STRUCTURE");
1558
        if (pszNBITS != nullptr)
1559
        {
1560
            nBITS = atoi(pszNBITS);
1561
        }
1562
    }
1563

1564
    if (nBITS > 0 && nBITS <= 8 && eDT != GDT_Byte)
1565
    {
1566
        CPLError(CE_Failure, CPLE_NotSupported,
1567
                 "NBITS <= 8 only compatible with Byte data type");
1568
        return nullptr;
1569
    }
1570

1571
    if (nBITS == 1)
1572
    {
1573
        nSampleType = RL2_SAMPLE_1_BIT;
1574
        if (nPixelType != RL2_PIXEL_PALETTE && pszPixelType == nullptr)
1575
            nPixelType = RL2_PIXEL_MONOCHROME;
1576
    }
1577
    else if (nBITS == 2)
1578
    {
1579
        nSampleType = RL2_SAMPLE_2_BIT;
1580
        if (nPixelType != RL2_PIXEL_PALETTE && pszPixelType == nullptr)
1581
            nPixelType = RL2_PIXEL_GRAYSCALE;
1582
    }
1583
    else if (nBITS == 4)
1584
    {
1585
        nSampleType = RL2_SAMPLE_4_BIT;
1586
        if (nPixelType != RL2_PIXEL_PALETTE && pszPixelType == nullptr)
1587
            nPixelType = RL2_PIXEL_GRAYSCALE;
1588
    }
1589

1590
    if (nPixelType == RL2_PIXEL_MONOCHROME)
1591
    {
1592
        if (eDT != GDT_Byte)
1593
        {
1594
            CPLError(CE_Failure, CPLE_NotSupported,
1595
                     "Incompatible data type for MONOCHROME");
1596
            return nullptr;
1597
        }
1598
        // Force 1 bit
1599
        nSampleType = RL2_SAMPLE_1_BIT;
1600
    }
1601

1602
    // Guess sample type in other cases
1603
    if (eDT == GDT_Int8)
1604
        nSampleType = RL2_SAMPLE_INT8;
1605
    else if (eDT == GDT_UInt16)
1606
        nSampleType = RL2_SAMPLE_UINT16;
1607
    else if (eDT == GDT_Int16)
1608
        nSampleType = RL2_SAMPLE_INT16;
1609
    else if (eDT == GDT_UInt32)
1610
        nSampleType = RL2_SAMPLE_UINT32;
1611
    else if (eDT == GDT_Int32)
1612
        nSampleType = RL2_SAMPLE_INT32;
1613
    else if (eDT == GDT_Float32)
1614
        nSampleType = RL2_SAMPLE_FLOAT;
1615
    else if (eDT == GDT_Float64)
1616
        nSampleType = RL2_SAMPLE_DOUBLE;
1617
    else if (eDT != GDT_Byte)
1618
    {
1619
        CPLError(CE_Failure, CPLE_NotSupported, "Unsupported data type");
1620
        return nullptr;
1621
    }
1622

1623
    unsigned char nCompression = RL2_COMPRESSION_NONE;
1624
    int nQuality = 100;
1625
    const char *pszCompression = CSLFetchNameValue(papszOptions, "COMPRESS");
1626
    if (pszCompression)
1627
    {
1628
        if (EQUAL(pszCompression, "NONE"))
1629
            nCompression = RL2_COMPRESSION_NONE;
1630
        else if (EQUAL(pszCompression, "DEFLATE"))
1631
            nCompression = RL2_COMPRESSION_DEFLATE;
1632
        else if (EQUAL(pszCompression, "LZMA"))
1633
            nCompression = RL2_COMPRESSION_LZMA;
1634
        else if (EQUAL(pszCompression, "PNG"))
1635
            nCompression = RL2_COMPRESSION_PNG;
1636
        else if (EQUAL(pszCompression, "CCITTFAX4"))
1637
            nCompression = RL2_COMPRESSION_CCITTFAX4;
1638
        else if (EQUAL(pszCompression, "JPEG"))
1639
        {
1640
            nCompression = RL2_COMPRESSION_JPEG;
1641
            nQuality = 75;
1642
        }
1643
        else if (EQUAL(pszCompression, "WEBP"))
1644
        {
1645
            nCompression = RL2_COMPRESSION_LOSSY_WEBP;
1646
            nQuality = 75;
1647
        }
1648
        else if (EQUAL(pszCompression, "JPEG2000"))
1649
        {
1650
            nCompression = RL2_COMPRESSION_LOSSY_JP2;
1651
            nQuality = 20;
1652
        }
1653
        else
1654
        {
1655
            CPLError(CE_Failure, CPLE_NotSupported, "Unsupported compression");
1656
            return nullptr;
1657
        }
1658
        if (!rl2_is_supported_codec(nCompression))
1659
        {
1660
            CPLError(CE_Failure, CPLE_NotSupported,
1661
                     "librasterlite2 is not built with support for "
1662
                     "this compression method.");
1663
            return nullptr;
1664
        }
1665
    }
1666

1667
    // Compatibility checks:
1668
    // see
1669
    // https://www.gaia-gis.it/fossil/librasterlite2/wiki?name=reference_table
1670
    if (nPixelType == RL2_PIXEL_MONOCHROME)
1671
    {
1672
        if (nBandCount != 1)
1673
        {
1674
            CPLError(CE_Failure, CPLE_NotSupported,
1675
                     "Unsupported band count with MONOCHROME");
1676
            return nullptr;
1677
        }
1678
        CPLAssert(nSampleType == RL2_SAMPLE_1_BIT);
1679
    }
1680
    else if (nPixelType == RL2_PIXEL_PALETTE)
1681
    {
1682
        if (nBandCount != 1)
1683
        {
1684
            CPLError(CE_Failure, CPLE_NotSupported,
1685
                     "Unsupported band count with PALETTE");
1686
            return nullptr;
1687
        }
1688
        if (nSampleType != RL2_SAMPLE_1_BIT &&
1689
            nSampleType != RL2_SAMPLE_2_BIT &&
1690
            nSampleType != RL2_SAMPLE_4_BIT && nSampleType != RL2_SAMPLE_UINT8)
1691
        {
1692
            CPLError(CE_Failure, CPLE_NotSupported,
1693
                     "Unsupported sample type with PALETTE");
1694
            return nullptr;
1695
        }
1696
    }
1697
    else if (nPixelType == RL2_PIXEL_GRAYSCALE)
1698
    {
1699
        if (nBandCount != 1)
1700
        {
1701
            CPLError(CE_Failure, CPLE_NotSupported,
1702
                     "Unsupported band count with GRAYSCALE");
1703
            return nullptr;
1704
        }
1705
        if (nSampleType != RL2_SAMPLE_2_BIT &&
1706
            nSampleType != RL2_SAMPLE_4_BIT && nSampleType != RL2_SAMPLE_UINT8)
1707
        {
1708
            CPLError(CE_Failure, CPLE_NotSupported,
1709
                     "Unsupported sample type with GRAYSCALE");
1710
            return nullptr;
1711
        }
1712
    }
1713
    else if (nPixelType == RL2_PIXEL_RGB)
1714
    {
1715
        if (nBandCount != 3)
1716
        {
1717
            CPLError(CE_Failure, CPLE_NotSupported,
1718
                     "Unsupported band count with RGB");
1719
            return nullptr;
1720
        }
1721
        if (nSampleType != RL2_SAMPLE_UINT8 && nSampleType != RL2_SAMPLE_UINT16)
1722
        {
1723
            CPLError(CE_Failure, CPLE_NotSupported,
1724
                     "Unsupported sample type with RGB");
1725
            return nullptr;
1726
        }
1727
    }
1728
    else if (nPixelType == RL2_PIXEL_MULTIBAND)
1729
    {
1730
        if (nBandCount == 1)
1731
        {
1732
            CPLError(CE_Failure, CPLE_NotSupported,
1733
                     "Unsupported band count with MULTIBAND");
1734
            return nullptr;
1735
        }
1736
        if (nSampleType != RL2_SAMPLE_UINT8 && nSampleType != RL2_SAMPLE_UINT16)
1737
        {
1738
            CPLError(CE_Failure, CPLE_NotSupported,
1739
                     "Unsupported sample type with MULTIBAND");
1740
            return nullptr;
1741
        }
1742
    }
1743
    else if (nPixelType == RL2_PIXEL_DATAGRID)
1744
    {
1745
        if (nBandCount != 1)
1746
        {
1747
            CPLError(CE_Failure, CPLE_NotSupported,
1748
                     "Unsupported band count with DATAGRID");
1749
            return nullptr;
1750
        }
1751
        if (nSampleType != RL2_SAMPLE_INT8 && nSampleType != RL2_SAMPLE_UINT8 &&
1752
            nSampleType != RL2_SAMPLE_INT16 &&
1753
            nSampleType != RL2_SAMPLE_UINT16 &&
1754
            nSampleType != RL2_SAMPLE_INT32 &&
1755
            nSampleType != RL2_SAMPLE_UINT32 &&
1756
            nSampleType != RL2_SAMPLE_FLOAT && nSampleType != RL2_SAMPLE_DOUBLE)
1757
        {
1758
            CPLError(CE_Failure, CPLE_NotSupported,
1759
                     "Unsupported sample type with DATAGRID");
1760
            return nullptr;
1761
        }
1762
    }
1763

1764
    // Other compatibility checks based on compression
1765
    if (nPixelType == RL2_PIXEL_MONOCHROME)
1766
    {
1767
        if (nCompression != RL2_COMPRESSION_NONE &&
1768
            nCompression != RL2_COMPRESSION_DEFLATE &&
1769
            nCompression != RL2_COMPRESSION_DEFLATE_NO &&
1770
            nCompression != RL2_COMPRESSION_LZMA &&
1771
            nCompression != RL2_COMPRESSION_LZMA_NO &&
1772
            nCompression != RL2_COMPRESSION_CCITTFAX4 &&
1773
            nCompression != RL2_COMPRESSION_PNG)
1774
        {
1775
            CPLError(CE_Failure, CPLE_NotSupported,
1776
                     "Unsupported compression with MONOCHROME");
1777
            return nullptr;
1778
        }
1779
    }
1780
    else if (nPixelType == RL2_PIXEL_PALETTE)
1781
    {
1782
        if (nCompression != RL2_COMPRESSION_NONE &&
1783
            nCompression != RL2_COMPRESSION_DEFLATE &&
1784
            nCompression != RL2_COMPRESSION_DEFLATE_NO &&
1785
            nCompression != RL2_COMPRESSION_LZMA &&
1786
            nCompression != RL2_COMPRESSION_LZMA_NO &&
1787
            nCompression != RL2_COMPRESSION_PNG)
1788
        {
1789
            CPLError(CE_Failure, CPLE_NotSupported,
1790
                     "Unsupported compression with PALETTE");
1791
            return nullptr;
1792
        }
1793
    }
1794
    else if (nPixelType == RL2_PIXEL_GRAYSCALE)
1795
    {
1796
        if (nCompression == RL2_COMPRESSION_CCITTFAX4)
1797
        {
1798
            CPLError(CE_Failure, CPLE_NotSupported,
1799
                     "Unsupported compression with GRAYSCALE");
1800
            return nullptr;
1801
        }
1802
    }
1803
    else if (nPixelType == RL2_PIXEL_RGB && nSampleType == RL2_SAMPLE_UINT8)
1804
    {
1805
        if (nCompression == RL2_COMPRESSION_CCITTFAX4)
1806
        {
1807
            CPLError(CE_Failure, CPLE_NotSupported,
1808
                     "Unsupported compression with RGB UINT8");
1809
            return nullptr;
1810
        }
1811
    }
1812
    else if (nPixelType == RL2_PIXEL_RGB && nSampleType == RL2_SAMPLE_UINT16)
1813
    {
1814
        if (nCompression == RL2_COMPRESSION_CCITTFAX4 ||
1815
            nCompression == RL2_COMPRESSION_JPEG ||
1816
            nCompression == RL2_COMPRESSION_LOSSY_WEBP ||
1817
            nCompression == RL2_COMPRESSION_LOSSLESS_WEBP)
1818
        {
1819
            CPLError(CE_Failure, CPLE_NotSupported,
1820
                     "Unsupported compression with RGB UINT16");
1821
            return nullptr;
1822
        }
1823
    }
1824
    else if (nPixelType == RL2_PIXEL_MULTIBAND &&
1825
             nSampleType == RL2_SAMPLE_UINT8 &&
1826
             (nBandCount == 3 || nBandCount == 4))
1827
    {
1828
        if (nCompression == RL2_COMPRESSION_CCITTFAX4 ||
1829
            nCompression == RL2_COMPRESSION_JPEG)
1830
        {
1831
            CPLError(CE_Failure, CPLE_NotSupported,
1832
                     "Unsupported compression with MULTIBAND UINT8 %d bands",
1833
                     nBandCount);
1834
            return nullptr;
1835
        }
1836
    }
1837
    else if (nPixelType == RL2_PIXEL_MULTIBAND &&
1838
             nSampleType == RL2_SAMPLE_UINT16 &&
1839
             (nBandCount == 3 || nBandCount == 4))
1840
    {
1841
        if (nCompression == RL2_COMPRESSION_CCITTFAX4 ||
1842
            nCompression == RL2_COMPRESSION_JPEG ||
1843
            nCompression == RL2_COMPRESSION_LOSSY_WEBP ||
1844
            nCompression == RL2_COMPRESSION_LOSSLESS_WEBP)
1845
        {
1846
            CPLError(CE_Failure, CPLE_NotSupported,
1847
                     "Unsupported compression with MULTIBAND UINT16 %d bands",
1848
                     nBandCount);
1849
            return nullptr;
1850
        }
1851
    }
1852
    else if (nPixelType == RL2_PIXEL_MULTIBAND)
1853
    {
1854
        if (nCompression != RL2_COMPRESSION_NONE &&
1855
            nCompression != RL2_COMPRESSION_DEFLATE &&
1856
            nCompression != RL2_COMPRESSION_DEFLATE_NO &&
1857
            nCompression != RL2_COMPRESSION_LZMA &&
1858
            nCompression != RL2_COMPRESSION_LZMA_NO)
1859
        {
1860
            CPLError(CE_Failure, CPLE_NotSupported,
1861
                     "Unsupported compression with MULTIBAND %s %d bands",
1862
                     (nSampleType == RL2_SAMPLE_UINT8) ? "UINT8" : "UINT16",
1863
                     nBandCount);
1864
            return nullptr;
1865
        }
1866
    }
1867
    else if (nPixelType == RL2_PIXEL_DATAGRID &&
1868
             (nSampleType == RL2_SAMPLE_UINT8 ||
1869
              nSampleType == RL2_SAMPLE_UINT16))
1870
    {
1871
        if (nCompression == RL2_COMPRESSION_CCITTFAX4 ||
1872
            nCompression == RL2_COMPRESSION_JPEG ||
1873
            nCompression == RL2_COMPRESSION_LOSSY_WEBP ||
1874
            nCompression == RL2_COMPRESSION_LOSSLESS_WEBP)
1875
        {
1876
            CPLError(CE_Failure, CPLE_NotSupported,
1877
                     "Unsupported compression with DATAGRID %s",
1878
                     (nSampleType == RL2_SAMPLE_UINT8) ? "UINT8" : "UINT16");
1879
            return nullptr;
1880
        }
1881
    }
1882
    else if (nPixelType == RL2_PIXEL_DATAGRID &&
1883
             nSampleType != RL2_SAMPLE_UINT8 &&
1884
             nSampleType != RL2_SAMPLE_UINT16)
1885
    {
1886
        if (nCompression != RL2_COMPRESSION_NONE &&
1887
            nCompression != RL2_COMPRESSION_DEFLATE &&
1888
            nCompression != RL2_COMPRESSION_DEFLATE_NO &&
1889
            nCompression != RL2_COMPRESSION_LZMA &&
1890
            nCompression != RL2_COMPRESSION_LZMA_NO)
1891
        {
1892
            CPLError(CE_Failure, CPLE_NotSupported,
1893
                     "Unsupported compression with DATAGRID %s",
1894
                     GDALGetDataTypeName(eDT));
1895
            return nullptr;
1896
        }
1897
    }
1898

1899
    const char *pszQuality = CSLFetchNameValue(papszOptions, "QUALITY");
1900
    if (pszQuality)
1901
    {
1902
        nQuality = atoi(pszQuality);
1903
        if (nQuality == 100 && nCompression == RL2_COMPRESSION_LOSSY_JP2)
1904
            nCompression = RL2_COMPRESSION_LOSSLESS_JP2;
1905
        else if (nQuality == 100 && nCompression == RL2_COMPRESSION_LOSSY_WEBP)
1906
            nCompression = RL2_COMPRESSION_LOSSLESS_WEBP;
1907
    }
1908

1909
    unsigned int nTileWidth =
1910
        atoi(CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", "512"));
1911
    unsigned int nTileHeight =
1912
        atoi(CSLFetchNameValueDef(papszOptions, "BLOCKYSIZE", "512"));
1913

1914
    /* -------------------------------------------------------------------- */
1915
    /*      Try to create datasource.                                       */
1916
    /* -------------------------------------------------------------------- */
1917
    OGRSQLiteDataSource *poDS = new OGRSQLiteDataSource();
1918

1919
    if (CSLFetchNameValue(papszOptions, "APPEND_SUBDATASET"))
1920
    {
1921
        GDALOpenInfo oOpenInfo(pszName, GDAL_OF_RASTER | GDAL_OF_VECTOR |
1922
                                            GDAL_OF_UPDATE);
1923
        if (!poDS->Open(&oOpenInfo))
1924
        {
1925
            delete poDS;
1926
            return nullptr;
1927
        }
1928
    }
1929
    else
1930
    {
1931
        char **papszNewOptions = CSLDuplicate(papszOptions);
1932
        papszNewOptions = CSLSetNameValue(papszNewOptions, "SPATIALITE", "YES");
1933
        if (!poDS->Create(pszName, papszNewOptions))
1934
        {
1935
            CSLDestroy(papszNewOptions);
1936
            delete poDS;
1937
            return nullptr;
1938
        }
1939
        CSLDestroy(papszNewOptions);
1940
    }
1941

1942
    /* -------------------------------------------------------------------- */
1943
    /*      Try to get the SRS Id of this spatial reference system,         */
1944
    /*      adding to the srs table if needed.                              */
1945
    /* -------------------------------------------------------------------- */
1946
    int nSRSId = 0;
1947
    const char *pszSRID = CSLFetchNameValue(papszOptions, "SRID");
1948

1949
    if (pszSRID != nullptr)
1950
    {
1951
        nSRSId = atoi(pszSRID);
1952
        if (nSRSId > 0)
1953
        {
1954
            OGRSpatialReference *poSRSFetched = poDS->FetchSRS(nSRSId);
1955
            if (poSRSFetched == nullptr)
1956
            {
1957
                CPLError(CE_Warning, CPLE_AppDefined,
1958
                         "SRID %d will be used, but no matching SRS is "
1959
                         "defined in spatial_ref_sys",
1960
                         nSRSId);
1961
            }
1962
        }
1963
    }
1964
    else
1965
    {
1966
        const OGRSpatialReference *poSRS = poSrcDS->GetSpatialRef();
1967
        if (poSRS)
1968
        {
1969
            nSRSId = poDS->FetchSRSId(poSRS);
1970
        }
1971
    }
1972

1973
    poDS->StartTransaction();
1974

1975
    char **papszResults = nullptr;
1976
    int nRowCount = 0;
1977
    int nColCount = 0;
1978
    sqlite3_get_table(poDS->GetDB(),
1979
                      "SELECT * FROM sqlite_master WHERE "
1980
                      "name = 'raster_coverages' AND type = 'table'",
1981
                      &papszResults, &nRowCount, &nColCount, nullptr);
1982
    sqlite3_free_table(papszResults);
1983
    if (nRowCount == 0)
1984
    {
1985
        char *pszErrMsg = nullptr;
1986
        int ret =
1987
            sqlite3_exec(poDS->GetDB(), "SELECT CreateRasterCoveragesTable()",
1988
                         nullptr, nullptr, &pszErrMsg);
1989
        if (ret != SQLITE_OK)
1990
        {
1991
            CPLError(CE_Failure, CPLE_AppDefined,
1992
                     "CreateRasterCoveragesTable() failed: %s", pszErrMsg);
1993
            sqlite3_free(pszErrMsg);
1994
            delete poDS;
1995
            return nullptr;
1996
        }
1997
    }
1998

1999
    const std::string osCoverageName(CSLFetchNameValueDef(
2000
        papszOptions, "COVERAGE", CPLGetBasenameSafe(pszName).c_str()));
2001
    // Check if the coverage already exists
2002
    rl2CoveragePtr cvg = nullptr;
2003
    char *pszSQL = sqlite3_mprintf(
2004
        "SELECT coverage_name "
2005
        "FROM raster_coverages WHERE coverage_name = '%q' LIMIT 1",
2006
        osCoverageName.c_str());
2007
    sqlite3_get_table(poDS->GetDB(), pszSQL, &papszResults, &nRowCount,
2008
                      &nColCount, nullptr);
2009
    sqlite3_free(pszSQL);
2010
    sqlite3_free_table(papszResults);
2011
    if (nRowCount == 1)
2012
    {
2013
        cvg = rl2_create_coverage_from_dbms(poDS->GetDB(), nullptr,
2014
                                            osCoverageName.c_str());
2015
        if (cvg == nullptr)
2016
        {
2017
            delete poDS;
2018
            return nullptr;
2019
        }
2020
    }
2021

2022
    rl2PalettePtr pPalette = nullptr;
2023
    if (nPixelType == RL2_PIXEL_PALETTE)
2024
    {
2025
        GDALColorTable *poCT = poSrcDS->GetRasterBand(1)->GetColorTable();
2026
        if (poCT == nullptr)
2027
        {
2028
            CPLError(CE_Failure, CPLE_AppDefined, "Missing color table");
2029
            delete poDS;
2030
            return nullptr;
2031
        }
2032

2033
        const int nColors = poCT->GetColorEntryCount();
2034
        pPalette = rl2_create_palette(nColors);
2035
        for (int i = 0; i < nColors; ++i)
2036
        {
2037
            const GDALColorEntry *poCE = poCT->GetColorEntry(i);
2038
            rl2_set_palette_color(pPalette, i, static_cast<GByte>(poCE->c1),
2039
                                  static_cast<GByte>(poCE->c2),
2040
                                  static_cast<GByte>(poCE->c3));
2041
        }
2042
    }
2043

2044
    if (cvg == nullptr)
2045
    {
2046
        const double dfXRes = gt[1];
2047
        const double dfYRes = fabs(gt[5]);
2048
        const bool bStrictResolution = true;
2049
        const bool bMixedResolutions = false;
2050
        const bool bSectionPaths = false;
2051
        const bool bSectionMD5 = false;
2052
        const bool bSectionSummary = false;
2053
        const bool bIsQueryable = false;
2054

2055
        rl2PixelPtr pNoData =
2056
            CreateNoData(nSampleType, nPixelType, nBandCount, poSrcDS);
2057
        if (pNoData == nullptr)
2058
        {
2059
            delete poDS;
2060
            if (pPalette)
2061
                rl2_destroy_palette(pPalette);
2062
            return nullptr;
2063
        }
2064

2065
        if (rl2_create_dbms_coverage(
2066
                poDS->GetDB(), osCoverageName.c_str(), nSampleType, nPixelType,
2067
                nBandCount, nCompression, nQuality, nTileWidth, nTileHeight,
2068
                nSRSId, dfXRes, dfYRes, pNoData, pPalette, bStrictResolution,
2069
                bMixedResolutions, bSectionPaths, bSectionMD5, bSectionSummary,
2070
                bIsQueryable) != RL2_OK)
2071
        {
2072
            CPLError(CE_Failure, CPLE_AppDefined,
2073
                     "rl2_create_dbms_coverage() failed");
2074
            rl2_destroy_pixel(pNoData);
2075
            if (pPalette)
2076
                rl2_destroy_palette(pPalette);
2077
            delete poDS;
2078
            return nullptr;
2079
        }
2080

2081
        rl2_destroy_pixel(pNoData);
2082
    }
2083

2084
    if (cvg == nullptr)
2085
    {
2086
        cvg = rl2_create_coverage_from_dbms(poDS->GetDB(), nullptr,
2087
                                            osCoverageName.c_str());
2088
        if (cvg == nullptr)
2089
        {
2090
            if (pPalette)
2091
                rl2_destroy_palette(pPalette);
2092
            delete poDS;
2093
            return nullptr;
2094
        }
2095
    }
2096

2097
    if (gt[5] > 0)
2098
        gt[5] = -gt[5];
2099
    double dfXMin = gt[0];
2100
    double dfXMax = dfXMin + gt[1] * poSrcDS->GetRasterXSize();
2101
    double dfYMax = gt[3];
2102
    double dfYMin = dfYMax + gt[5] * poSrcDS->GetRasterYSize();
2103

2104
    CPLString osSectionName(CSLFetchNameValueDef(
2105
        papszOptions, "SECTION", CPLGetBasenameSafe(pszName).c_str()));
2106
    const bool bPyramidize = CPLFetchBool(papszOptions, "PYRAMIDIZE", false);
2107
    RasterLite2CallbackData cbk_data;
2108
    cbk_data.poSrcDS = poSrcDS;
2109
    cbk_data.nPixelType = nPixelType;
2110
    cbk_data.nSampleType = nSampleType;
2111
    cbk_data.pPalette = pPalette;
2112
    cbk_data.pfnProgress = pfnProgress;
2113
    cbk_data.pProgressData = pProgressData;
2114
    cbk_data.gt = gt;
2115

2116
    if (rl2_load_raw_tiles_into_dbms(
2117
            poDS->GetDB(), poDS->GetRL2Context(), cvg, osSectionName,
2118
            poSrcDS->GetRasterXSize(), poSrcDS->GetRasterYSize(), nSRSId,
2119
            dfXMin, dfYMin, dfXMax, dfYMax, RasterLite2Callback, &cbk_data,
2120
            bPyramidize) != RL2_OK)
2121
    {
2122
        CPLError(CE_Failure, CPLE_AppDefined,
2123
                 "rl2_load_raw_tiles_into_dbms() failed");
2124
        delete poDS;
2125
        rl2_destroy_coverage(cvg);
2126
        if (pPalette)
2127
            rl2_destroy_palette(pPalette);
2128
        return nullptr;
2129
    }
2130

2131
    rl2_destroy_coverage(cvg);
2132
    if (pPalette)
2133
        rl2_destroy_palette(pPalette);
2134

2135
    poDS->CommitTransaction();
2136

2137
    delete poDS;
2138

2139
    poDS = new OGRSQLiteDataSource();
2140
    GDALOpenInfo oOpenInfo(
2141
        CPLSPrintf("RASTERLITE2:%s:%s",
2142
                   EscapeNameAndQuoteIfNeeded(pszName).c_str(),
2143
                   EscapeNameAndQuoteIfNeeded(osCoverageName.c_str()).c_str()),
2144
        GDAL_OF_RASTER | GDAL_OF_UPDATE);
2145
    poDS->Open(&oOpenInfo);
2146
    return poDS;
2147
}
2148

2149
/************************************************************************/
2150
/*                          IBuildOverviews()                           */
2151
/************************************************************************/
2152

2153
CPLErr OGRSQLiteDataSource::IBuildOverviews(
2154
    const char *pszResampling, int nOverviews, const int *panOverviewList,
2155
    int nBandsIn, const int * /*panBandList */,
2156
    GDALProgressFunc /*pfnProgress*/, void * /*pProgressData*/,
2157
    CSLConstList /* papszOptions */)
2158

2159
{
2160
    if (nBandsIn != nBands)
2161
    {
2162
        CPLError(CE_Failure, CPLE_AppDefined,
2163
                 "Only build of all bands is supported");
2164
    }
2165

2166
    if (nOverviews == 0)
2167
    {
2168
        int ret;
2169
        if (m_bRL2MixedResolutions && m_nSectionId >= 0)
2170
        {
2171
            ret =
2172
                rl2_delete_section_pyramid(hDB, m_osCoverageName, m_nSectionId);
2173
        }
2174
        else
2175
        {
2176
            ret = rl2_delete_all_pyramids(hDB, m_osCoverageName);
2177
        }
2178
        if (ret != RL2_OK)
2179
        {
2180
            CPLError(CE_Failure, CPLE_AppDefined,
2181
                     "Deletion of pyramids failed");
2182
            return CE_Failure;
2183
        }
2184
    }
2185
    else
2186
    {
2187
        if (!STARTS_WITH_CI(pszResampling, "NEAR"))
2188
        {
2189
            CPLError(CE_Warning, CPLE_AppDefined,
2190
                     "Resampling method is ignored. Using librasterlite2 own "
2191
                     "method");
2192
        }
2193
        for (int i = 0; i < nOverviews; ++i)
2194
        {
2195
            if (!CPLIsPowerOfTwo(panOverviewList[i]))
2196
            {
2197
                CPLError(CE_Failure, CPLE_NotSupported,
2198
                         "Only power-of-two overview factors are supported");
2199
                return CE_Failure;
2200
            }
2201
        }
2202

2203
        const int bForcedRebuild = 1;
2204
        const int bVerbose = 0;
2205
        const int bVirtualLevels = 1;
2206
        int ret;
2207
        if (m_bRL2MixedResolutions)
2208
        {
2209
            if (m_nSectionId >= 0)
2210
            {
2211
                ret = rl2_build_section_pyramid(hDB, GetRL2Context(),
2212
                                                m_osCoverageName, m_nSectionId,
2213
                                                bForcedRebuild, bVerbose);
2214
            }
2215
            else
2216
            {
2217
                ret = rl2_build_monolithic_pyramid(hDB, GetRL2Context(),
2218
                                                   m_osCoverageName,
2219
                                                   bVirtualLevels, bVerbose);
2220
            }
2221
        }
2222
        else
2223
        {
2224
            ret = rl2_build_monolithic_pyramid(hDB, GetRL2Context(),
2225
                                               m_osCoverageName, bVirtualLevels,
2226
                                               bVerbose);
2227
        }
2228
        if (ret != RL2_OK)
2229
        {
2230
            CPLError(CE_Failure, CPLE_AppDefined, "Build of pyramids failed");
2231
            return CE_Failure;
2232
        }
2233
    }
2234

2235
    for (size_t i = 0; i < m_apoOverviewDS.size(); ++i)
2236
        delete m_apoOverviewDS[i];
2237
    m_apoOverviewDS.clear();
2238
    ListOverviews();
2239

2240
    return CE_None;
2241
}
2242

2243
#endif  // HAVE_RASTERLITE2
2244

2245
/************************************************************************/
2246
/*                             GetMetadata()                            */
2247
/************************************************************************/
2248

2249
char **OGRSQLiteDataSource::GetMetadata(const char *pszDomain)
5✔
2250
{
2251
    if (pszDomain != nullptr && EQUAL(pszDomain, "SUBDATASETS") &&
5✔
2252
        m_aosSubDatasets.size() > 2)
×
2253
    {
2254
        return m_aosSubDatasets.List();
×
2255
    }
2256
    return GDALPamDataset::GetMetadata(pszDomain);
5✔
2257
}
2258

2259
/************************************************************************/
2260
/*                           GetGeoTransform()                          */
2261
/************************************************************************/
2262

2263
CPLErr OGRSQLiteDataSource::GetGeoTransform(GDALGeoTransform &gt) const
×
2264
{
2265
    if (m_bGeoTransformValid)
×
2266
    {
2267
        gt = m_gt;
×
2268
        return CE_None;
×
2269
    }
2270
    return GDALPamDataset::GetGeoTransform(gt);
×
2271
}
2272

2273
/************************************************************************/
2274
/*                            GetSpatialRef()                           */
2275
/************************************************************************/
2276

2277
const OGRSpatialReference *OGRSQLiteDataSource::GetSpatialRef() const
×
2278
{
2279
    if (!m_oSRS.IsEmpty())
×
2280
        return &m_oSRS;
×
2281
    return GDALPamDataset::GetSpatialRef();
×
2282
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc