Line data Source code
1 : /******************************************************************************
2 : *
3 : * Project: GDAL Rasterlite driver
4 : * Purpose: Implement GDAL Rasterlite support using OGR SQLite driver
5 : * Author: Even Rouault, <even dot rouault at spatialys.com>
6 : *
7 : **********************************************************************
8 : * Copyright (c) 2009-2012, Even Rouault <even dot rouault at spatialys.com>
9 : *
10 : * SPDX-License-Identifier: MIT
11 : ****************************************************************************/
12 :
13 : #include "cpl_string.h"
14 : #include "ogr_api.h"
15 : #include "ogr_srs_api.h"
16 : #include "memdataset.h"
17 :
18 : #include "rasterlitedataset.h"
19 :
20 : /************************************************************************/
21 : /* ReloadOverviews() */
22 : /************************************************************************/
23 :
24 4 : CPLErr RasterliteDataset::ReloadOverviews()
25 : {
26 4 : if (nLevel != 0)
27 0 : return CE_Failure;
28 :
29 : /* -------------------------------------------------------------------- */
30 : /* Fetch resolutions */
31 : /* -------------------------------------------------------------------- */
32 :
33 8 : CPLString osSQL;
34 : OGRLayerH hRasterPyramidsLyr =
35 4 : GDALDatasetGetLayerByName(hDS, "raster_pyramids");
36 4 : if (hRasterPyramidsLyr)
37 : {
38 : osSQL.Printf("SELECT pixel_x_size, pixel_y_size "
39 : "FROM raster_pyramids WHERE table_prefix = '%s' "
40 : "ORDER BY pixel_x_size ASC",
41 4 : osTableName.c_str());
42 : }
43 : else
44 : {
45 : osSQL.Printf("SELECT DISTINCT(pixel_x_size), pixel_y_size "
46 : "FROM \"%s_metadata\" WHERE pixel_x_size != 0 "
47 : "ORDER BY pixel_x_size ASC",
48 0 : osTableName.c_str());
49 : }
50 :
51 : OGRLayerH hSQLLyr =
52 4 : GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
53 4 : if (hSQLLyr == nullptr)
54 : {
55 0 : if (hRasterPyramidsLyr == nullptr)
56 0 : return CE_Failure;
57 :
58 : osSQL.Printf("SELECT DISTINCT(pixel_x_size), pixel_y_size "
59 : "FROM \"%s_metadata\" WHERE pixel_x_size != 0 "
60 : "ORDER BY pixel_x_size ASC",
61 0 : osTableName.c_str());
62 :
63 0 : hSQLLyr = GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
64 0 : if (hSQLLyr == nullptr)
65 0 : return CE_Failure;
66 : }
67 :
68 : /* -------------------------------------------------------------------- */
69 : /* Cleanup */
70 : /* -------------------------------------------------------------------- */
71 6 : for (int i = 1; i < nResolutions; i++)
72 2 : delete papoOverviews[i - 1];
73 4 : CPLFree(papoOverviews);
74 4 : papoOverviews = nullptr;
75 4 : CPLFree(padfXResolutions);
76 4 : padfXResolutions = nullptr;
77 4 : CPLFree(padfYResolutions);
78 4 : padfYResolutions = nullptr;
79 :
80 : /* -------------------------------------------------------------------- */
81 : /* Rebuild arrays */
82 : /* -------------------------------------------------------------------- */
83 :
84 4 : nResolutions = static_cast<int>(OGR_L_GetFeatureCount(hSQLLyr, TRUE));
85 :
86 4 : padfXResolutions =
87 4 : reinterpret_cast<double *>(CPLMalloc(sizeof(double) * nResolutions));
88 4 : padfYResolutions =
89 4 : reinterpret_cast<double *>(CPLMalloc(sizeof(double) * nResolutions));
90 :
91 : {
92 : // Exstra scope for i.
93 4 : int i = 0;
94 : OGRFeatureH hFeat;
95 14 : while ((hFeat = OGR_L_GetNextFeature(hSQLLyr)) != nullptr)
96 : {
97 10 : padfXResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 0);
98 10 : padfYResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 1);
99 :
100 10 : OGR_F_Destroy(hFeat);
101 :
102 10 : i++;
103 : }
104 : }
105 :
106 4 : GDALDatasetReleaseResultSet(hDS, hSQLLyr);
107 4 : hSQLLyr = nullptr;
108 :
109 : /* -------------------------------------------------------------------- */
110 : /* Add overview levels as internal datasets */
111 : /* -------------------------------------------------------------------- */
112 4 : if (nResolutions > 1)
113 : {
114 8 : CPLString osRasterTableName = osTableName;
115 4 : osRasterTableName += "_rasters";
116 :
117 : OGRLayerH hRasterLyr =
118 4 : GDALDatasetGetLayerByName(hDS, osRasterTableName.c_str());
119 :
120 4 : papoOverviews = reinterpret_cast<RasterliteDataset **>(
121 4 : CPLCalloc(nResolutions - 1, sizeof(RasterliteDataset *)));
122 10 : for (int nLev = 1; nLev < nResolutions; nLev++)
123 : {
124 : int nOvrBands;
125 : GDALDataType eOvrDataType;
126 : int nBlockXSize, nBlockYSize;
127 6 : if (GetBlockParams(hRasterLyr, nLev, &nOvrBands, &eOvrDataType,
128 6 : &nBlockXSize, &nBlockYSize))
129 : {
130 6 : if (eOvrDataType == GDT_Byte && nOvrBands == 1 && nBands == 3)
131 0 : nOvrBands = 3;
132 :
133 6 : papoOverviews[nLev - 1] = new RasterliteDataset(this, nLev);
134 :
135 12 : for (int iBand = 0; iBand < nBands; iBand++)
136 : {
137 6 : papoOverviews[nLev - 1]->SetBand(
138 : iBand + 1, new RasterliteBand(
139 6 : papoOverviews[nLev - 1], iBand + 1,
140 6 : eOvrDataType, nBlockXSize, nBlockYSize));
141 : }
142 : }
143 : else
144 : {
145 0 : CPLError(CE_Failure, CPLE_AppDefined,
146 : "Cannot find block characteristics for overview %d",
147 : nLev);
148 0 : papoOverviews[nLev - 1] = nullptr;
149 : }
150 : }
151 : }
152 :
153 4 : return CE_None;
154 : }
155 :
156 : /************************************************************************/
157 : /* CleanOverviews() */
158 : /************************************************************************/
159 :
160 1 : CPLErr RasterliteDataset::CleanOverviews()
161 : {
162 1 : if (nLevel != 0)
163 0 : return CE_Failure;
164 :
165 2 : CPLString osSQL("BEGIN");
166 1 : GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
167 :
168 : const CPLString osResolutionCond =
169 2 : "NOT " +
170 2 : RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0]);
171 :
172 : osSQL.Printf("DELETE FROM \"%s_rasters\" WHERE id "
173 : "IN(SELECT id FROM \"%s_metadata\" WHERE %s)",
174 : osTableName.c_str(), osTableName.c_str(),
175 1 : osResolutionCond.c_str());
176 1 : GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
177 :
178 : osSQL.Printf("DELETE FROM \"%s_metadata\" WHERE %s", osTableName.c_str(),
179 1 : osResolutionCond.c_str());
180 1 : GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
181 :
182 : OGRLayerH hRasterPyramidsLyr =
183 1 : GDALDatasetGetLayerByName(hDS, "raster_pyramids");
184 1 : if (hRasterPyramidsLyr)
185 : {
186 : osSQL.Printf(
187 : "DELETE FROM raster_pyramids WHERE table_prefix = '%s' AND %s",
188 1 : osTableName.c_str(), osResolutionCond.c_str());
189 1 : GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
190 : }
191 :
192 1 : osSQL = "COMMIT";
193 1 : GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
194 :
195 3 : for (int i = 1; i < nResolutions; i++)
196 2 : delete papoOverviews[i - 1];
197 1 : CPLFree(papoOverviews);
198 1 : papoOverviews = nullptr;
199 1 : nResolutions = 1;
200 :
201 1 : return CE_None;
202 : }
203 :
204 : /************************************************************************/
205 : /* CleanOverviewLevel() */
206 : /************************************************************************/
207 :
208 4 : CPLErr RasterliteDataset::CleanOverviewLevel(int nOvrFactor)
209 : {
210 4 : if (nLevel != 0)
211 0 : return CE_Failure;
212 :
213 : /* -------------------------------------------------------------------- */
214 : /* Find the index of the overview matching the overview factor */
215 : /* -------------------------------------------------------------------- */
216 4 : int iLev = 1;
217 6 : for (; iLev < nResolutions; iLev++)
218 : {
219 2 : if (fabs(padfXResolutions[0] * nOvrFactor - padfXResolutions[iLev]) <
220 0 : 1e-15 &&
221 0 : fabs(padfYResolutions[0] * nOvrFactor - padfYResolutions[iLev]) <
222 : 1e-15)
223 0 : break;
224 : }
225 :
226 4 : if (iLev == nResolutions)
227 4 : return CE_None;
228 :
229 : /* -------------------------------------------------------------------- */
230 : /* Now clean existing overviews at that resolution */
231 : /* -------------------------------------------------------------------- */
232 :
233 0 : CPLString osSQL("BEGIN");
234 0 : GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
235 :
236 : CPLString osResolutionCond = RasterliteGetPixelSizeCond(
237 0 : padfXResolutions[iLev], padfYResolutions[iLev]);
238 :
239 : osSQL.Printf("DELETE FROM \"%s_rasters\" WHERE id "
240 : "IN(SELECT id FROM \"%s_metadata\" WHERE %s)",
241 : osTableName.c_str(), osTableName.c_str(),
242 0 : osResolutionCond.c_str());
243 0 : GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
244 :
245 : osSQL.Printf("DELETE FROM \"%s_metadata\" WHERE %s", osTableName.c_str(),
246 0 : osResolutionCond.c_str());
247 0 : GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
248 :
249 : OGRLayerH hRasterPyramidsLyr =
250 0 : GDALDatasetGetLayerByName(hDS, "raster_pyramids");
251 0 : if (hRasterPyramidsLyr)
252 : {
253 : osSQL.Printf(
254 : "DELETE FROM raster_pyramids WHERE table_prefix = '%s' AND %s",
255 0 : osTableName.c_str(), osResolutionCond.c_str());
256 0 : GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
257 : }
258 :
259 0 : osSQL = "COMMIT";
260 0 : GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
261 :
262 0 : return CE_None;
263 : }
264 :
265 : /************************************************************************/
266 : /* CleanOverviewLevel() */
267 : /************************************************************************/
268 :
269 4 : CPLErr RasterliteDataset::CreateOverviewLevel(const char *pszResampling,
270 : int nOvrFactor,
271 : CSLConstList papszOptions,
272 : GDALProgressFunc pfnProgress,
273 : void *pProgressData)
274 : {
275 4 : const int nOvrXSize = nRasterXSize / nOvrFactor;
276 4 : const int nOvrYSize = nRasterYSize / nOvrFactor;
277 :
278 4 : if (nOvrXSize == 0 || nOvrYSize == 0)
279 0 : return CE_Failure;
280 :
281 : const bool bTiled =
282 4 : CPLTestBool(CSLFetchNameValueDef(papszOptions, "TILED", "YES"));
283 : int nBlockXSize, nBlockYSize;
284 4 : if (bTiled)
285 : {
286 : nBlockXSize =
287 4 : atoi(CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", "256"));
288 : nBlockYSize =
289 4 : atoi(CSLFetchNameValueDef(papszOptions, "BLOCKYSIZE", "256"));
290 4 : if (nBlockXSize < 64)
291 0 : nBlockXSize = 64;
292 4 : else if (nBlockXSize > 4096)
293 0 : nBlockXSize = 4096;
294 4 : if (nBlockYSize < 64)
295 0 : nBlockYSize = 64;
296 4 : else if (nBlockYSize > 4096)
297 0 : nBlockYSize = 4096;
298 : }
299 : else
300 : {
301 0 : nBlockXSize = nOvrXSize;
302 0 : nBlockYSize = nOvrYSize;
303 : }
304 :
305 : const char *pszDriverName =
306 4 : CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff");
307 4 : if (EQUAL(pszDriverName, "MEM") || EQUAL(pszDriverName, "VRT"))
308 : {
309 0 : CPLError(CE_Failure, CPLE_AppDefined,
310 : "GDAL %s driver cannot be used as underlying driver",
311 : pszDriverName);
312 0 : return CE_Failure;
313 : }
314 4 : GDALDriverH hTileDriver = GDALGetDriverByName(pszDriverName);
315 4 : if (hTileDriver == nullptr)
316 : {
317 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL %s driver",
318 : pszDriverName);
319 0 : return CE_Failure;
320 : }
321 :
322 4 : GDALDriverH hMemDriver = GDALGetDriverByName("MEM");
323 4 : if (hMemDriver == nullptr)
324 : {
325 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL MEM driver");
326 0 : return CE_Failure;
327 : }
328 :
329 4 : const GDALDataType eDataType = GetRasterBand(1)->GetRasterDataType();
330 4 : int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8;
331 4 : GByte *pabyMEMDSBuffer = reinterpret_cast<GByte *>(VSIMalloc3(
332 4 : nBlockXSize, nBlockYSize, cpl::fits_on<int>(nBands * nDataTypeSize)));
333 4 : if (pabyMEMDSBuffer == nullptr)
334 : {
335 0 : return CE_Failure;
336 : }
337 :
338 : const CPLString osTempFileName(
339 8 : VSIMemGenerateHiddenFilename("rasterlite_tile"));
340 :
341 4 : int nTileId = 0;
342 4 : int nBlocks = 0;
343 :
344 4 : const int nXBlocks = (nOvrXSize + nBlockXSize - 1) / nBlockXSize;
345 4 : const int nYBlocks = (nOvrYSize + nBlockYSize - 1) / nBlockYSize;
346 4 : int nTotalBlocks = nXBlocks * nYBlocks;
347 :
348 8 : CPLString osRasterLayer;
349 4 : osRasterLayer.Printf("%s_rasters", osTableName.c_str());
350 :
351 8 : CPLString osMetatadataLayer;
352 4 : osMetatadataLayer.Printf("%s_metadata", osTableName.c_str());
353 :
354 : OGRLayerH hRasterLayer =
355 4 : GDALDatasetGetLayerByName(hDS, osRasterLayer.c_str());
356 : OGRLayerH hMetadataLayer =
357 4 : GDALDatasetGetLayerByName(hDS, osMetatadataLayer.c_str());
358 :
359 8 : CPLString osSourceName = "unknown";
360 :
361 4 : const double dfXResolution = padfXResolutions[0] * nOvrFactor;
362 4 : const double dfYResolution = padfXResolutions[0] * nOvrFactor;
363 :
364 8 : CPLString osSQL;
365 : osSQL.Printf(
366 : "SELECT source_name FROM \"%s\" WHERE "
367 : "%s LIMIT 1",
368 : osMetatadataLayer.c_str(),
369 8 : RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0])
370 4 : .c_str());
371 : OGRLayerH hSQLLyr =
372 4 : GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
373 4 : if (hSQLLyr)
374 : {
375 4 : OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr);
376 4 : if (hFeat)
377 : {
378 4 : const char *pszVal = OGR_F_GetFieldAsString(hFeat, 0);
379 4 : if (pszVal)
380 4 : osSourceName = pszVal;
381 4 : OGR_F_Destroy(hFeat);
382 : }
383 4 : GDALDatasetReleaseResultSet(hDS, hSQLLyr);
384 : }
385 :
386 : /* -------------------------------------------------------------------- */
387 : /* Compute up to which existing overview level we can use for */
388 : /* computing the requested overview */
389 : /* -------------------------------------------------------------------- */
390 4 : nLimitOvrCount = 0;
391 4 : int iLev = 1;
392 6 : for (; iLev < nResolutions; iLev++)
393 : {
394 2 : if (!(padfXResolutions[iLev] < dfXResolution - 1e-10 &&
395 2 : padfYResolutions[iLev] < dfYResolution - 1e-10))
396 : {
397 : break;
398 : }
399 2 : nLimitOvrCount++;
400 : }
401 : /* -------------------------------------------------------------------- */
402 : /* Allocate buffer for tile of previous overview level */
403 : /* -------------------------------------------------------------------- */
404 :
405 4 : GDALDataset *poPrevOvrLevel =
406 2 : (papoOverviews != nullptr && iLev >= 2 && iLev <= nResolutions &&
407 2 : papoOverviews[iLev - 2])
408 6 : ? papoOverviews[iLev - 2]
409 : : this;
410 : const double dfRatioPrevOvr =
411 4 : static_cast<double>(poPrevOvrLevel->GetRasterBand(1)->GetXSize()) /
412 4 : nOvrXSize;
413 4 : const int nPrevOvrBlockXSize =
414 4 : static_cast<int>(nBlockXSize * dfRatioPrevOvr + 0.5);
415 4 : const int nPrevOvrBlockYSize =
416 4 : static_cast<int>(nBlockYSize * dfRatioPrevOvr + 0.5);
417 4 : GByte *pabyPrevOvrMEMDSBuffer = nullptr;
418 :
419 4 : if (!STARTS_WITH_CI(pszResampling, "NEAR"))
420 : {
421 : pabyPrevOvrMEMDSBuffer = reinterpret_cast<GByte *>(
422 2 : VSIMalloc3(nPrevOvrBlockXSize, nPrevOvrBlockYSize,
423 2 : cpl::fits_on<int>(nBands * nDataTypeSize)));
424 2 : if (pabyPrevOvrMEMDSBuffer == nullptr)
425 : {
426 0 : VSIFree(pabyMEMDSBuffer);
427 0 : return CE_Failure;
428 : }
429 : }
430 :
431 : /* -------------------------------------------------------------------- */
432 : /* Iterate over blocks to add data into raster and metadata tables */
433 : /* -------------------------------------------------------------------- */
434 :
435 : char **papszTileDriverOptions =
436 4 : RasterliteGetTileDriverOptions(papszOptions);
437 :
438 4 : GDALDatasetExecuteSQL(hDS, "BEGIN", nullptr, nullptr);
439 :
440 4 : CPLErr eErr = CE_None;
441 8 : for (int nBlockYOff = 0; eErr == CE_None && nBlockYOff < nYBlocks;
442 : nBlockYOff++)
443 : {
444 8 : for (int nBlockXOff = 0; eErr == CE_None && nBlockXOff < nXBlocks;
445 : nBlockXOff++)
446 : {
447 0 : std::unique_ptr<MEMDataset> poPrevOvrMemDS;
448 :
449 : /* --------------------------------------------------------------------
450 : */
451 : /* Create in-memory tile */
452 : /* --------------------------------------------------------------------
453 : */
454 4 : int nReqXSize = nBlockXSize;
455 4 : int nReqYSize = nBlockYSize;
456 4 : if ((nBlockXOff + 1) * nBlockXSize > nOvrXSize)
457 4 : nReqXSize = nOvrXSize - nBlockXOff * nBlockXSize;
458 4 : if ((nBlockYOff + 1) * nBlockYSize > nOvrYSize)
459 4 : nReqYSize = nOvrYSize - nBlockYOff * nBlockYSize;
460 :
461 4 : if (pabyPrevOvrMEMDSBuffer != nullptr)
462 : {
463 2 : int nPrevOvrReqXSize =
464 2 : static_cast<int>(nReqXSize * dfRatioPrevOvr + 0.5);
465 2 : int nPrevOvrReqYSize =
466 2 : static_cast<int>(nReqYSize * dfRatioPrevOvr + 0.5);
467 :
468 4 : eErr = RasterIO(GF_Read, nBlockXOff * nBlockXSize * nOvrFactor,
469 2 : nBlockYOff * nBlockYSize * nOvrFactor,
470 : nReqXSize * nOvrFactor, nReqYSize * nOvrFactor,
471 : pabyPrevOvrMEMDSBuffer, nPrevOvrReqXSize,
472 : nPrevOvrReqYSize, eDataType, nBands, nullptr, 0,
473 : 0, 0, nullptr);
474 :
475 2 : if (eErr != CE_None)
476 : {
477 0 : break;
478 : }
479 :
480 2 : poPrevOvrMemDS.reset(MEMDataset::Create("", nPrevOvrReqXSize,
481 : nPrevOvrReqYSize, 0,
482 : eDataType, nullptr));
483 :
484 4 : for (int iBand = 0; iBand < nBands; iBand++)
485 : {
486 2 : auto hBand = MEMCreateRasterBandEx(
487 2 : poPrevOvrMemDS.get(), iBand + 1,
488 2 : pabyPrevOvrMEMDSBuffer + iBand * nDataTypeSize *
489 2 : nPrevOvrReqXSize *
490 : nPrevOvrReqYSize,
491 : eDataType, 0, 0, false);
492 2 : poPrevOvrMemDS->AddMEMBand(hBand);
493 : }
494 : }
495 : else
496 : {
497 4 : eErr = RasterIO(GF_Read, nBlockXOff * nBlockXSize * nOvrFactor,
498 2 : nBlockYOff * nBlockYSize * nOvrFactor,
499 : nReqXSize * nOvrFactor, nReqYSize * nOvrFactor,
500 : pabyMEMDSBuffer, nReqXSize, nReqYSize,
501 : eDataType, nBands, nullptr, 0, 0, 0, nullptr);
502 2 : if (eErr != CE_None)
503 : {
504 0 : break;
505 : }
506 : }
507 :
508 : auto poMemDS = std::unique_ptr<MEMDataset>(MEMDataset::Create(
509 4 : "", nReqXSize, nReqYSize, 0, eDataType, nullptr));
510 8 : for (int iBand = 0; iBand < nBands; iBand++)
511 : {
512 4 : auto hBand = MEMCreateRasterBandEx(
513 4 : poMemDS.get(), iBand + 1,
514 : pabyMEMDSBuffer +
515 4 : iBand * nDataTypeSize * nReqXSize * nReqYSize,
516 : eDataType, 0, 0, false);
517 4 : poMemDS->AddMEMBand(hBand);
518 : }
519 :
520 4 : auto hMemDS = GDALDataset::ToHandle(poMemDS.get());
521 4 : if (poPrevOvrMemDS != nullptr)
522 : {
523 4 : for (int iBand = 0; iBand < nBands; iBand++)
524 : {
525 : GDALRasterBandH hDstOvrBand =
526 2 : GDALGetRasterBand(hMemDS, iBand + 1);
527 :
528 : auto hPrevOvrMEMDS =
529 2 : GDALDataset::ToHandle(poPrevOvrMemDS.get());
530 2 : eErr = GDALRegenerateOverviews(
531 : GDALGetRasterBand(hPrevOvrMEMDS, iBand + 1), 1,
532 : &hDstOvrBand, pszResampling, nullptr, nullptr);
533 2 : if (eErr != CE_None)
534 0 : break;
535 : }
536 :
537 2 : poPrevOvrMemDS.reset();
538 : }
539 :
540 : GDALDatasetH hOutDS =
541 4 : GDALCreateCopy(hTileDriver, osTempFileName.c_str(), hMemDS,
542 : FALSE, papszTileDriverOptions, nullptr, nullptr);
543 :
544 4 : poMemDS.reset();
545 4 : if (!hOutDS)
546 : {
547 0 : eErr = CE_Failure;
548 0 : break;
549 : }
550 :
551 4 : GDALClose(hOutDS);
552 :
553 : /* --------------------------------------------------------------------
554 : */
555 : /* Insert new entry into raster table */
556 : /* --------------------------------------------------------------------
557 : */
558 :
559 : vsi_l_offset nDataLength;
560 4 : GByte *pabyData = VSIGetMemFileBuffer(osTempFileName.c_str(),
561 : &nDataLength, FALSE);
562 :
563 4 : OGRFeatureH hFeat = OGR_F_Create(OGR_L_GetLayerDefn(hRasterLayer));
564 4 : OGR_F_SetFieldBinary(hFeat, 0, static_cast<int>(nDataLength),
565 : pabyData);
566 :
567 4 : if (OGR_L_CreateFeature(hRasterLayer, hFeat) != OGRERR_NONE)
568 0 : eErr = CE_Failure;
569 : /* Query raster ID to set it as the ID of the associated metadata */
570 4 : const int nRasterID = static_cast<int>(OGR_F_GetFID(hFeat));
571 :
572 4 : OGR_F_Destroy(hFeat);
573 :
574 4 : VSIUnlink(osTempFileName.c_str());
575 4 : if (eErr == CE_Failure)
576 0 : break;
577 :
578 : /* --------------------------------------------------------------------
579 : */
580 : /* Insert new entry into metadata table */
581 : /* --------------------------------------------------------------------
582 : */
583 :
584 4 : hFeat = OGR_F_Create(OGR_L_GetLayerDefn(hMetadataLayer));
585 4 : OGR_F_SetFID(hFeat, nRasterID);
586 4 : OGR_F_SetFieldString(hFeat, 0, osSourceName);
587 4 : OGR_F_SetFieldInteger(hFeat, 1, nTileId++);
588 4 : OGR_F_SetFieldInteger(hFeat, 2, nReqXSize);
589 4 : OGR_F_SetFieldInteger(hFeat, 3, nReqYSize);
590 4 : OGR_F_SetFieldDouble(hFeat, 4, dfXResolution);
591 4 : OGR_F_SetFieldDouble(hFeat, 5, dfYResolution);
592 :
593 4 : const double minx =
594 4 : adfGeoTransform[0] + (nBlockXSize * nBlockXOff) * dfXResolution;
595 4 : const double maxx =
596 4 : adfGeoTransform[0] +
597 4 : (nBlockXSize * nBlockXOff + nReqXSize) * dfXResolution;
598 4 : const double maxy = adfGeoTransform[3] +
599 4 : (nBlockYSize * nBlockYOff) * (-dfYResolution);
600 4 : const double miny =
601 4 : adfGeoTransform[3] +
602 4 : (nBlockYSize * nBlockYOff + nReqYSize) * (-dfYResolution);
603 :
604 4 : OGRGeometryH hRectangle = OGR_G_CreateGeometry(wkbPolygon);
605 4 : OGRGeometryH hLinearRing = OGR_G_CreateGeometry(wkbLinearRing);
606 4 : OGR_G_AddPoint_2D(hLinearRing, minx, miny);
607 4 : OGR_G_AddPoint_2D(hLinearRing, minx, maxy);
608 4 : OGR_G_AddPoint_2D(hLinearRing, maxx, maxy);
609 4 : OGR_G_AddPoint_2D(hLinearRing, maxx, miny);
610 4 : OGR_G_AddPoint_2D(hLinearRing, minx, miny);
611 4 : OGR_G_AddGeometryDirectly(hRectangle, hLinearRing);
612 :
613 4 : OGR_F_SetGeometryDirectly(hFeat, hRectangle);
614 :
615 4 : if (OGR_L_CreateFeature(hMetadataLayer, hFeat) != OGRERR_NONE)
616 0 : eErr = CE_Failure;
617 4 : OGR_F_Destroy(hFeat);
618 :
619 4 : nBlocks++;
620 4 : if (pfnProgress && !pfnProgress(1.0 * nBlocks / nTotalBlocks,
621 : nullptr, pProgressData))
622 0 : eErr = CE_Failure;
623 : }
624 : }
625 :
626 4 : nLimitOvrCount = -1;
627 :
628 4 : VSIUnlink(osTempFileName);
629 4 : VSIUnlink((osTempFileName + ".aux.xml").c_str());
630 :
631 4 : if (eErr == CE_None)
632 4 : GDALDatasetExecuteSQL(hDS, "COMMIT", nullptr, nullptr);
633 : else
634 0 : GDALDatasetExecuteSQL(hDS, "ROLLBACK", nullptr, nullptr);
635 :
636 4 : VSIFree(pabyMEMDSBuffer);
637 4 : VSIFree(pabyPrevOvrMEMDSBuffer);
638 :
639 4 : CSLDestroy(papszTileDriverOptions);
640 4 : papszTileDriverOptions = nullptr;
641 :
642 : /* -------------------------------------------------------------------- */
643 : /* Update raster_pyramids table */
644 : /* -------------------------------------------------------------------- */
645 4 : if (eErr != CE_None)
646 0 : return eErr;
647 :
648 : OGRLayerH hRasterPyramidsLyr =
649 4 : GDALDatasetGetLayerByName(hDS, "raster_pyramids");
650 4 : if (hRasterPyramidsLyr == nullptr)
651 : {
652 : osSQL.Printf("CREATE TABLE raster_pyramids ("
653 : "table_prefix TEXT NOT NULL,"
654 : "pixel_x_size DOUBLE NOT NULL,"
655 : "pixel_y_size DOUBLE NOT NULL,"
656 2 : "tile_count INTEGER NOT NULL)");
657 2 : GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
658 :
659 : /* Re-open the DB to take into account the new tables*/
660 2 : GDALClose(hDS);
661 :
662 2 : hDS = RasterliteOpenSQLiteDB(osFileName.c_str(), GA_Update);
663 :
664 2 : hRasterPyramidsLyr = GDALDatasetGetLayerByName(hDS, "raster_pyramids");
665 2 : if (hRasterPyramidsLyr == nullptr)
666 0 : return CE_Failure;
667 : }
668 4 : OGRFeatureDefnH hFDefn = OGR_L_GetLayerDefn(hRasterPyramidsLyr);
669 :
670 : /* Insert base resolution into raster_pyramids if not already done */
671 4 : bool bHasBaseResolution = false;
672 : osSQL.Printf(
673 : "SELECT * FROM raster_pyramids WHERE "
674 : "table_prefix = '%s' AND %s",
675 : osTableName.c_str(),
676 8 : RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0])
677 4 : .c_str());
678 4 : hSQLLyr = GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
679 4 : if (hSQLLyr)
680 : {
681 4 : OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr);
682 4 : if (hFeat)
683 : {
684 2 : bHasBaseResolution = true;
685 2 : OGR_F_Destroy(hFeat);
686 : }
687 4 : GDALDatasetReleaseResultSet(hDS, hSQLLyr);
688 : }
689 :
690 4 : if (!bHasBaseResolution)
691 : {
692 : osSQL.Printf(
693 : "SELECT COUNT(*) FROM \"%s\" WHERE %s", osMetatadataLayer.c_str(),
694 4 : RasterliteGetPixelSizeCond(padfXResolutions[0], padfYResolutions[0])
695 2 : .c_str());
696 :
697 2 : int nBlocksMainRes = 0;
698 :
699 2 : hSQLLyr = GDALDatasetExecuteSQL(hDS, osSQL.c_str(), nullptr, nullptr);
700 2 : if (hSQLLyr)
701 : {
702 2 : OGRFeatureH hFeat = OGR_L_GetNextFeature(hSQLLyr);
703 2 : if (hFeat)
704 : {
705 2 : nBlocksMainRes = OGR_F_GetFieldAsInteger(hFeat, 0);
706 2 : OGR_F_Destroy(hFeat);
707 : }
708 2 : GDALDatasetReleaseResultSet(hDS, hSQLLyr);
709 : }
710 :
711 2 : OGRFeatureH hFeat = OGR_F_Create(hFDefn);
712 2 : OGR_F_SetFieldString(hFeat,
713 : OGR_FD_GetFieldIndex(hFDefn, "table_prefix"),
714 : osTableName.c_str());
715 2 : OGR_F_SetFieldDouble(hFeat,
716 : OGR_FD_GetFieldIndex(hFDefn, "pixel_x_size"),
717 2 : padfXResolutions[0]);
718 2 : OGR_F_SetFieldDouble(hFeat,
719 : OGR_FD_GetFieldIndex(hFDefn, "pixel_y_size"),
720 2 : padfYResolutions[0]);
721 2 : OGR_F_SetFieldInteger(hFeat, OGR_FD_GetFieldIndex(hFDefn, "tile_count"),
722 : nBlocksMainRes);
723 2 : if (OGR_L_CreateFeature(hRasterPyramidsLyr, hFeat) != OGRERR_NONE)
724 0 : eErr = CE_Failure;
725 2 : OGR_F_Destroy(hFeat);
726 : }
727 :
728 4 : OGRFeatureH hFeat = OGR_F_Create(hFDefn);
729 4 : OGR_F_SetFieldString(hFeat, OGR_FD_GetFieldIndex(hFDefn, "table_prefix"),
730 : osTableName.c_str());
731 4 : OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_x_size"),
732 : dfXResolution);
733 4 : OGR_F_SetFieldDouble(hFeat, OGR_FD_GetFieldIndex(hFDefn, "pixel_y_size"),
734 : dfYResolution);
735 4 : OGR_F_SetFieldInteger(hFeat, OGR_FD_GetFieldIndex(hFDefn, "tile_count"),
736 : nTotalBlocks);
737 4 : if (OGR_L_CreateFeature(hRasterPyramidsLyr, hFeat) != OGRERR_NONE)
738 0 : eErr = CE_Failure;
739 4 : OGR_F_Destroy(hFeat);
740 :
741 4 : return eErr;
742 : }
743 :
744 : /************************************************************************/
745 : /* IBuildOverviews() */
746 : /************************************************************************/
747 :
748 3 : CPLErr RasterliteDataset::IBuildOverviews(
749 : const char *pszResampling, int nOverviews, const int *panOverviewList,
750 : int nBandsIn, const int *panBandList, GDALProgressFunc pfnProgress,
751 : void *pProgressData, CSLConstList papszOptions)
752 : {
753 3 : if (nLevel != 0)
754 : {
755 0 : CPLError(CE_Failure, CPLE_AppDefined,
756 : "Overviews can only be computed on the base dataset");
757 0 : return CE_Failure;
758 : }
759 :
760 3 : if (osTableName.empty())
761 0 : return CE_Failure;
762 :
763 : /* -------------------------------------------------------------------- */
764 : /* If we don't have read access, then create the overviews */
765 : /* externally. */
766 : /* -------------------------------------------------------------------- */
767 3 : if (GetAccess() != GA_Update)
768 : {
769 0 : CPLDebug("Rasterlite", "File open for read-only accessing, "
770 : "creating overviews externally.");
771 :
772 0 : if (nResolutions != 1)
773 : {
774 0 : CPLError(CE_Failure, CPLE_NotSupported,
775 : "Cannot add external overviews to a "
776 : "dataset with internal overviews");
777 0 : return CE_Failure;
778 : }
779 :
780 0 : bCheckForExistingOverview = FALSE;
781 0 : CPLErr eErr = GDALDataset::IBuildOverviews(
782 : pszResampling, nOverviews, panOverviewList, nBandsIn, panBandList,
783 : pfnProgress, pProgressData, papszOptions);
784 0 : bCheckForExistingOverview = TRUE;
785 0 : return eErr;
786 : }
787 :
788 : /* -------------------------------------------------------------------- */
789 : /* If zero overviews were requested, we need to clear all */
790 : /* existing overviews. */
791 : /* -------------------------------------------------------------------- */
792 3 : if (nOverviews == 0)
793 : {
794 1 : return CleanOverviews();
795 : }
796 :
797 2 : if (nBandsIn != GetRasterCount())
798 : {
799 0 : CPLError(CE_Failure, CPLE_NotSupported,
800 : "Generation of overviews in RASTERLITE only"
801 : " supported when operating on all bands.\n"
802 : "Operation failed.\n");
803 0 : return CE_Failure;
804 : }
805 :
806 : const char *pszOvrOptions =
807 2 : CPLGetConfigOption("RASTERLITE_OVR_OPTIONS", nullptr);
808 : const CPLStringList aosCreationOptions(
809 2 : pszOvrOptions ? CSLTokenizeString2(pszOvrOptions, ",", 0) : nullptr);
810 2 : GDALValidateCreationOptions(GetDriver(), aosCreationOptions.List());
811 :
812 2 : CPLErr eErr = CE_None;
813 6 : for (int i = 0; i < nOverviews && eErr == CE_None; i++)
814 : {
815 4 : if (panOverviewList[i] <= 1)
816 0 : continue;
817 :
818 4 : eErr = CleanOverviewLevel(panOverviewList[i]);
819 4 : if (eErr == CE_None)
820 4 : eErr = CreateOverviewLevel(pszResampling, panOverviewList[i],
821 : aosCreationOptions.List(), pfnProgress,
822 : pProgressData);
823 :
824 4 : ReloadOverviews();
825 : }
826 :
827 2 : return eErr;
828 : }
|