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