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