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