1 : /******************************************************************************
2 : * $Id: rasterlitecreatecopy.cpp 24801 2012-08-18 14:29:41Z 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: rasterlitecreatecopy.cpp 24801 2012-08-18 14:29:41Z rouault $");
37 :
38 : /************************************************************************/
39 : /* RasterliteGetTileDriverOptions () */
40 : /************************************************************************/
41 :
42 88 : static char** RasterliteAddTileDriverOptionsForDriver(char** papszOptions,
43 : char** papszTileDriverOptions,
44 : const char* pszOptionName,
45 : const char* pszExpectedDriverName)
46 : {
47 88 : const char* pszVal = CSLFetchNameValue(papszOptions, pszOptionName);
48 88 : if (pszVal)
49 : {
50 : const char* pszDriverName =
51 0 : CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff");
52 0 : if (EQUAL(pszDriverName, pszExpectedDriverName))
53 : {
54 : papszTileDriverOptions =
55 0 : CSLSetNameValue(papszTileDriverOptions, pszOptionName, pszVal);
56 : }
57 : else
58 : {
59 : CPLError(CE_Warning, CPLE_NotSupported,
60 : "Unexpected option '%s' for driver '%s'",
61 0 : pszOptionName, pszDriverName);
62 : }
63 : }
64 88 : return papszTileDriverOptions;
65 : }
66 :
67 22 : char** RasterliteGetTileDriverOptions(char** papszOptions)
68 : {
69 22 : char** papszTileDriverOptions = NULL;
70 :
71 : const char* pszDriverName =
72 22 : CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff");
73 :
74 22 : if (EQUAL(pszDriverName, "EPSILON"))
75 : {
76 : papszTileDriverOptions = CSLSetNameValue(papszTileDriverOptions,
77 2 : "RASTERLITE_OUTPUT", "YES");
78 : }
79 :
80 22 : const char* pszQuality = CSLFetchNameValue(papszOptions, "QUALITY");
81 22 : if (pszQuality)
82 : {
83 0 : if (EQUAL(pszDriverName, "GTiff"))
84 : {
85 : papszTileDriverOptions =
86 0 : CSLSetNameValue(papszTileDriverOptions, "JPEG_QUALITY", pszQuality);
87 : }
88 0 : else if (EQUAL(pszDriverName, "JPEG") || EQUAL(pszDriverName, "WEBP"))
89 : {
90 : papszTileDriverOptions =
91 0 : CSLSetNameValue(papszTileDriverOptions, "QUALITY", pszQuality);
92 : }
93 : else
94 : {
95 : CPLError(CE_Warning, CPLE_NotSupported,
96 : "Unexpected option '%s' for driver '%s'",
97 0 : "QUALITY", pszDriverName);
98 : }
99 : }
100 :
101 : papszTileDriverOptions = RasterliteAddTileDriverOptionsForDriver(
102 22 : papszOptions, papszTileDriverOptions, "COMPRESS", "GTiff");
103 : papszTileDriverOptions = RasterliteAddTileDriverOptionsForDriver(
104 22 : papszOptions, papszTileDriverOptions, "PHOTOMETRIC", "GTiff");
105 : papszTileDriverOptions = RasterliteAddTileDriverOptionsForDriver(
106 22 : papszOptions, papszTileDriverOptions, "TARGET", "EPSILON");
107 : papszTileDriverOptions = RasterliteAddTileDriverOptionsForDriver(
108 22 : papszOptions, papszTileDriverOptions, "FILTER", "EPSILON");
109 :
110 22 : return papszTileDriverOptions;
111 : }
112 :
113 : /************************************************************************/
114 : /* RasterliteInsertSRID () */
115 : /************************************************************************/
116 :
117 18 : static int RasterliteInsertSRID(OGRDataSourceH hDS, const char* pszWKT)
118 : {
119 18 : CPLString osSQL;
120 :
121 18 : int nAuthorityCode = 0;
122 18 : CPLString osAuthorityName, osProjCS, osProj4;
123 18 : if (pszWKT != NULL && strlen(pszWKT) != 0)
124 : {
125 18 : OGRSpatialReferenceH hSRS = OSRNewSpatialReference(pszWKT);
126 18 : if (hSRS)
127 : {
128 18 : const char* pszAuthorityName = OSRGetAuthorityName(hSRS, NULL);
129 18 : if (pszAuthorityName) osAuthorityName = pszAuthorityName;
130 :
131 18 : const char* pszProjCS = OSRGetAttrValue(hSRS, "PROJCS", 0);
132 18 : if (pszProjCS) osProjCS = pszProjCS;
133 :
134 18 : const char* pszAuthorityCode = OSRGetAuthorityCode(hSRS, NULL);
135 18 : if (pszAuthorityCode) nAuthorityCode = atoi(pszAuthorityCode);
136 :
137 18 : char *pszProj4 = NULL;
138 18 : if( OSRExportToProj4( hSRS, &pszProj4 ) != OGRERR_NONE )
139 0 : pszProj4 = CPLStrdup("");
140 18 : osProj4 = pszProj4;
141 18 : CPLFree(pszProj4);
142 : }
143 18 : OSRDestroySpatialReference(hSRS);
144 : }
145 :
146 18 : int nSRSId = -1;
147 18 : if (nAuthorityCode != 0 && osAuthorityName.size() != 0)
148 : {
149 18 : osSQL.Printf ("SELECT srid FROM spatial_ref_sys WHERE auth_srid = %d", nAuthorityCode);
150 18 : OGRLayerH hLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
151 18 : if (hLyr == NULL)
152 : {
153 0 : nSRSId = nAuthorityCode;
154 :
155 0 : if ( osProjCS.size() != 0 )
156 : osSQL.Printf(
157 : "INSERT INTO spatial_ref_sys "
158 : "(srid, auth_name, auth_srid, ref_sys_name, proj4text) "
159 : "VALUES (%d, '%s', '%d', '%s', '%s')",
160 : nSRSId, osAuthorityName.c_str(),
161 0 : nAuthorityCode, osProjCS.c_str(), osProj4.c_str() );
162 : else
163 : osSQL.Printf(
164 : "INSERT INTO spatial_ref_sys "
165 : "(srid, auth_name, auth_srid, proj4text) "
166 : "VALUES (%d, '%s', '%d', '%s')",
167 : nSRSId, osAuthorityName.c_str(),
168 0 : nAuthorityCode, osProj4.c_str() );
169 :
170 :
171 0 : OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
172 : }
173 : else
174 : {
175 18 : OGRFeatureH hFeat = OGR_L_GetNextFeature(hLyr);
176 18 : if (hFeat)
177 : {
178 18 : nSRSId = OGR_F_GetFieldAsInteger(hFeat, 0);
179 18 : OGR_F_Destroy(hFeat);
180 : }
181 18 : OGR_DS_ReleaseResultSet(hDS, hLyr);
182 : }
183 : }
184 :
185 18 : return nSRSId;
186 : }
187 :
188 : /************************************************************************/
189 : /* RasterliteCreateTables () */
190 : /************************************************************************/
191 :
192 18 : OGRDataSourceH RasterliteCreateTables(OGRDataSourceH hDS, const char* pszTableName,
193 : int nSRSId, int bWipeExistingData)
194 : {
195 18 : CPLString osSQL;
196 :
197 18 : CPLString osOldVal = CPLGetConfigOption("SQLITE_LIST_ALL_TABLES", "FALSE");
198 18 : CPLString osDBName = OGR_DS_GetName(hDS);
199 :
200 18 : CPLString osRasterLayer;
201 18 : osRasterLayer.Printf("%s_rasters", pszTableName);
202 :
203 18 : CPLString osMetatadataLayer;
204 18 : osMetatadataLayer.Printf("%s_metadata", pszTableName);
205 :
206 : OGRLayerH hLyr;
207 :
208 18 : if (OGR_DS_GetLayerByName(hDS, osRasterLayer.c_str()) == NULL)
209 : {
210 : /* -------------------------------------------------------------------- */
211 : /* The table don't exist. Create them */
212 : /* -------------------------------------------------------------------- */
213 :
214 : /* Create _rasters table */
215 : osSQL.Printf ("CREATE TABLE \"%s\" ("
216 : "id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,"
217 18 : "raster BLOB NOT NULL)", osRasterLayer.c_str());
218 18 : OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
219 :
220 : /* Create _metadata table */
221 : osSQL.Printf ("CREATE TABLE \"%s\" ("
222 : "id INTEGER NOT NULL PRIMARY KEY,"
223 : "source_name TEXT NOT NULL,"
224 : "tile_id INTEGER NOT NULL,"
225 : "width INTEGER NOT NULL,"
226 : "height INTEGER NOT NULL,"
227 : "pixel_x_size DOUBLE NOT NULL,"
228 : "pixel_y_size DOUBLE NOT NULL)",
229 18 : osMetatadataLayer.c_str());
230 18 : OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
231 :
232 : /* Add geometry column to _metadata table */
233 : osSQL.Printf("SELECT AddGeometryColumn('%s', 'geometry', %d, 'POLYGON', 2)",
234 18 : osMetatadataLayer.c_str(), nSRSId);
235 18 : if ((hLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL)) == NULL)
236 : {
237 : CPLError(CE_Failure, CPLE_AppDefined,
238 0 : "Check that the OGR SQLite driver has Spatialite support");
239 0 : OGRReleaseDataSource(hDS);
240 0 : return NULL;
241 : }
242 18 : OGR_DS_ReleaseResultSet(hDS, hLyr);
243 :
244 : /* Create spatial index on _metadata table */
245 : osSQL.Printf("SELECT CreateSpatialIndex('%s', 'geometry')",
246 18 : osMetatadataLayer.c_str());
247 18 : if ((hLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL)) == NULL)
248 : {
249 0 : OGRReleaseDataSource(hDS);
250 0 : return NULL;
251 : }
252 18 : OGR_DS_ReleaseResultSet(hDS, hLyr);
253 :
254 : /* Create statistics tables */
255 18 : osSQL.Printf("SELECT UpdateLayerStatistics()");
256 18 : CPLPushErrorHandler(CPLQuietErrorHandler);
257 18 : hLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
258 18 : CPLPopErrorHandler();
259 18 : OGR_DS_ReleaseResultSet(hDS, hLyr);
260 :
261 : /* Re-open the DB to take into account the new tables*/
262 18 : OGRReleaseDataSource(hDS);
263 :
264 18 : CPLSetThreadLocalConfigOption("SQLITE_LIST_ALL_TABLES", "TRUE");
265 18 : hDS = OGROpen(osDBName.c_str(), TRUE, NULL);
266 18 : CPLSetThreadLocalConfigOption("SQLITE_LIST_ALL_TABLES", osOldVal.c_str());
267 : }
268 : else
269 : {
270 : /* Check that the existing SRS is consistent with the one of the new */
271 : /* data to be inserted */
272 : osSQL.Printf("SELECT srid FROM geometry_columns WHERE f_table_name = '%s'",
273 0 : osMetatadataLayer.c_str());
274 0 : hLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
275 0 : if (hLyr)
276 : {
277 0 : int nExistingSRID = -1;
278 0 : OGRFeatureH hFeat = OGR_L_GetNextFeature(hLyr);
279 0 : if (hFeat)
280 : {
281 0 : nExistingSRID = OGR_F_GetFieldAsInteger(hFeat, 0);
282 0 : OGR_F_Destroy(hFeat);
283 : }
284 0 : OGR_DS_ReleaseResultSet(hDS, hLyr);
285 :
286 0 : if (nExistingSRID != nSRSId)
287 : {
288 0 : if (bWipeExistingData)
289 : {
290 : osSQL.Printf("UPDATE geometry_columns SET srid = %d "
291 : "WHERE f_table_name = \"%s\"",
292 0 : nSRSId, osMetatadataLayer.c_str());
293 0 : OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
294 :
295 : /* Re-open the DB to take into account the change of SRS */
296 0 : OGRReleaseDataSource(hDS);
297 :
298 0 : CPLSetThreadLocalConfigOption("SQLITE_LIST_ALL_TABLES", "TRUE");
299 0 : hDS = OGROpen(osDBName.c_str(), TRUE, NULL);
300 0 : CPLSetThreadLocalConfigOption("SQLITE_LIST_ALL_TABLES", osOldVal.c_str());
301 : }
302 : else
303 : {
304 : CPLError(CE_Failure, CPLE_NotSupported,
305 0 : "New data has not the same SRS as existing data");
306 0 : OGRReleaseDataSource(hDS);
307 0 : return NULL;
308 : }
309 : }
310 : }
311 :
312 0 : if (bWipeExistingData)
313 : {
314 0 : osSQL.Printf("DELETE FROM \"%s\"", osRasterLayer.c_str());
315 0 : OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
316 :
317 0 : osSQL.Printf("DELETE FROM \"%s\"", osMetatadataLayer.c_str());
318 0 : OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
319 : }
320 : }
321 :
322 18 : return hDS;
323 : }
324 :
325 : /************************************************************************/
326 : /* RasterliteCreateCopy () */
327 : /************************************************************************/
328 :
329 : GDALDataset *
330 36 : RasterliteCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
331 : int bStrict, char ** papszOptions,
332 : GDALProgressFunc pfnProgress, void * pProgressData )
333 : {
334 36 : int nBands = poSrcDS->GetRasterCount();
335 36 : if (nBands == 0)
336 : {
337 1 : CPLError(CE_Failure, CPLE_NotSupported, "nBands == 0");
338 1 : return NULL;
339 : }
340 :
341 35 : const char* pszDriverName = CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff");
342 35 : if (EQUAL(pszDriverName, "MEM") || EQUAL(pszDriverName, "VRT"))
343 : {
344 : CPLError(CE_Failure, CPLE_AppDefined, "GDAL %s driver cannot be used as underlying driver",
345 0 : pszDriverName);
346 0 : return NULL;
347 : }
348 :
349 35 : GDALDriverH hTileDriver = GDALGetDriverByName(pszDriverName);
350 35 : if ( hTileDriver == NULL)
351 : {
352 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL %s driver", pszDriverName);
353 0 : return NULL;
354 : }
355 :
356 35 : GDALDriverH hMemDriver = GDALGetDriverByName("MEM");
357 35 : if (hMemDriver == NULL)
358 : {
359 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL MEM driver");
360 0 : return NULL;
361 : }
362 :
363 35 : int nXSize = GDALGetRasterXSize(poSrcDS);
364 35 : int nYSize = GDALGetRasterYSize(poSrcDS);
365 :
366 : double adfGeoTransform[6];
367 35 : if (poSrcDS->GetGeoTransform(adfGeoTransform) != CE_None)
368 : {
369 0 : adfGeoTransform[0] = 0;
370 0 : adfGeoTransform[1] = 1;
371 0 : adfGeoTransform[2] = 0;
372 0 : adfGeoTransform[3] = 0;
373 0 : adfGeoTransform[4] = 0;
374 0 : adfGeoTransform[5] = -1;
375 : }
376 35 : else if (adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0)
377 : {
378 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot use geotransform with rotational terms");
379 0 : return NULL;
380 : }
381 :
382 35 : int bTiled = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "TILED", "YES"));
383 : int nBlockXSize, nBlockYSize;
384 35 : if (bTiled)
385 : {
386 35 : nBlockXSize = atoi(CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", "256"));
387 35 : nBlockYSize = atoi(CSLFetchNameValueDef(papszOptions, "BLOCKYSIZE", "256"));
388 35 : if (nBlockXSize < 64) nBlockXSize = 64;
389 35 : else if (nBlockXSize > 4096) nBlockXSize = 4096;
390 35 : if (nBlockYSize < 64) nBlockYSize = 64;
391 35 : else if (nBlockYSize > 4096) nBlockYSize = 4096;
392 : }
393 : else
394 : {
395 0 : nBlockXSize = nXSize;
396 0 : nBlockYSize = nYSize;
397 : }
398 :
399 : /* -------------------------------------------------------------------- */
400 : /* Analyze arguments */
401 : /* -------------------------------------------------------------------- */
402 :
403 35 : CPLString osDBName;
404 35 : CPLString osTableName;
405 : VSIStatBuf sBuf;
406 : int bExists;
407 :
408 : /* Skip optionnal RASTERLITE: prefix */
409 35 : const char* pszFilenameWithoutPrefix = pszFilename;
410 35 : if (EQUALN(pszFilename, "RASTERLITE:", 11))
411 1 : pszFilenameWithoutPrefix += 11;
412 :
413 : char** papszTokens = CSLTokenizeStringComplex(
414 35 : pszFilenameWithoutPrefix, ", ", FALSE, FALSE );
415 35 : int nTokens = CSLCount(papszTokens);
416 35 : if (nTokens == 0)
417 : {
418 0 : osDBName = pszFilenameWithoutPrefix;
419 0 : osTableName = CPLGetBasename(pszFilenameWithoutPrefix);
420 : }
421 : else
422 : {
423 35 : osDBName = papszTokens[0];
424 :
425 : int i;
426 36 : for(i=1;i<nTokens;i++)
427 : {
428 1 : if (EQUALN(papszTokens[i], "table=", 6))
429 1 : osTableName = papszTokens[i] + 6;
430 : else
431 : {
432 : CPLError(CE_Warning, CPLE_AppDefined,
433 0 : "Invalid option : %s", papszTokens[i]);
434 : }
435 : }
436 : }
437 :
438 35 : CSLDestroy(papszTokens);
439 35 : papszTokens = NULL;
440 :
441 35 : bExists = (VSIStat(osDBName.c_str(), &sBuf) == 0);
442 :
443 35 : if (osTableName.size() == 0)
444 : {
445 34 : if (bExists)
446 : {
447 : CPLError(CE_Failure, CPLE_AppDefined,
448 0 : "Database already exists. Explicit table name must be specified");
449 0 : return NULL;
450 : }
451 34 : osTableName = CPLGetBasename(osDBName.c_str());
452 : }
453 :
454 35 : CPLString osRasterLayer;
455 35 : osRasterLayer.Printf("%s_rasters", osTableName.c_str());
456 :
457 35 : CPLString osMetatadataLayer;
458 35 : osMetatadataLayer.Printf("%s_metadata", osTableName.c_str());
459 :
460 : /* -------------------------------------------------------------------- */
461 : /* Create or open the SQLite DB */
462 : /* -------------------------------------------------------------------- */
463 :
464 35 : if (OGRGetDriverCount() == 0)
465 1 : OGRRegisterAll();
466 :
467 35 : OGRSFDriverH hSQLiteDriver = OGRGetDriverByName("SQLite");
468 35 : if (hSQLiteDriver == NULL)
469 : {
470 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot load OGR SQLite driver");
471 0 : return NULL;
472 : }
473 :
474 : OGRDataSourceH hDS;
475 :
476 : CPLString osOldVal =
477 35 : CPLGetConfigOption("SQLITE_LIST_ALL_TABLES", "FALSE");
478 35 : CPLSetThreadLocalConfigOption("SQLITE_LIST_ALL_TABLES", "TRUE");
479 35 : if (!bExists)
480 : {
481 35 : char** papszOGROptions = CSLAddString(NULL, "SPATIALITE=YES");
482 : hDS = OGR_Dr_CreateDataSource(hSQLiteDriver,
483 35 : osDBName.c_str(), papszOGROptions);
484 35 : CSLDestroy(papszOGROptions);
485 : }
486 : else
487 : {
488 0 : hDS = OGROpen(osDBName.c_str(), TRUE, NULL);
489 : }
490 35 : CPLSetThreadLocalConfigOption("SQLITE_LIST_ALL_TABLES", osOldVal.c_str());
491 :
492 35 : if (hDS == NULL)
493 : {
494 : CPLError(CE_Failure, CPLE_AppDefined,
495 17 : "Cannot load or create SQLite database");
496 17 : return NULL;
497 : }
498 :
499 18 : CPLString osSQL;
500 :
501 : /* -------------------------------------------------------------------- */
502 : /* Get the SRID for the SRS */
503 : /* -------------------------------------------------------------------- */
504 18 : int nSRSId = RasterliteInsertSRID(hDS, poSrcDS->GetProjectionRef());
505 :
506 : /* -------------------------------------------------------------------- */
507 : /* Create or wipe existing tables */
508 : /* -------------------------------------------------------------------- */
509 : int bWipeExistingData =
510 18 : CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "WIPE", "NO"));
511 :
512 : hDS = RasterliteCreateTables(hDS, osTableName.c_str(),
513 18 : nSRSId, bWipeExistingData);
514 18 : if (hDS == NULL)
515 0 : return NULL;
516 :
517 18 : OGRLayerH hRasterLayer = OGR_DS_GetLayerByName(hDS, osRasterLayer.c_str());
518 18 : OGRLayerH hMetadataLayer = OGR_DS_GetLayerByName(hDS, osMetatadataLayer.c_str());
519 18 : if (hRasterLayer == NULL || hMetadataLayer == NULL)
520 : {
521 : CPLError(CE_Failure, CPLE_AppDefined,
522 0 : "Cannot find metadata and/or raster tables");
523 0 : OGRReleaseDataSource(hDS);
524 0 : return NULL;
525 : }
526 :
527 : /* -------------------------------------------------------------------- */
528 : /* Check if there is overlapping data and warn the user */
529 : /* -------------------------------------------------------------------- */
530 18 : double minx = adfGeoTransform[0];
531 18 : double maxx = adfGeoTransform[0] + nXSize * adfGeoTransform[1];
532 18 : double maxy = adfGeoTransform[3];
533 18 : double miny = adfGeoTransform[3] + nYSize * adfGeoTransform[5];
534 :
535 : osSQL.Printf("SELECT COUNT(geometry) FROM \"%s\" "
536 : "WHERE rowid IN "
537 : "(SELECT pkid FROM \"idx_%s_metadata_geometry\" "
538 : "WHERE xmin < %.15f AND xmax > %.15f "
539 : "AND ymin < %.15f AND ymax > %.15f) "
540 : "AND pixel_x_size >= %.15f AND pixel_x_size <= %.15f AND "
541 : "pixel_y_size >= %.15f AND pixel_y_size <= %.15f",
542 : osMetatadataLayer.c_str(),
543 : osTableName.c_str(),
544 : maxx, minx, maxy, miny,
545 36 : adfGeoTransform[1] - 1e-15, adfGeoTransform[1] + 1e-15,
546 54 : - adfGeoTransform[5] - 1e-15, - adfGeoTransform[5] + 1e-15);
547 :
548 18 : int nOverlappingGeoms = 0;
549 18 : OGRLayerH hCountLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
550 18 : if (hCountLyr)
551 : {
552 18 : OGRFeatureH hFeat = OGR_L_GetNextFeature(hCountLyr);
553 18 : if (hFeat)
554 : {
555 18 : nOverlappingGeoms = OGR_F_GetFieldAsInteger(hFeat, 0);
556 18 : OGR_F_Destroy(hFeat);
557 : }
558 18 : OGR_DS_ReleaseResultSet(hDS, hCountLyr);
559 : }
560 :
561 18 : if (nOverlappingGeoms != 0)
562 : {
563 : CPLError(CE_Warning, CPLE_AppDefined,
564 : "Raster tiles already exist in the %s table within "
565 : "the extent of the data to be inserted in",
566 0 : osTableName.c_str());
567 : }
568 :
569 : /* -------------------------------------------------------------------- */
570 : /* Iterate over blocks to add data into raster and metadata tables */
571 : /* -------------------------------------------------------------------- */
572 18 : int nXBlocks = (nXSize + nBlockXSize - 1) / nBlockXSize;
573 18 : int nYBlocks = (nYSize + nBlockYSize - 1) / nBlockYSize;
574 :
575 18 : GDALDataType eDataType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
576 18 : int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8;
577 : GByte* pabyMEMDSBuffer =
578 18 : (GByte*)VSIMalloc3(nBlockXSize, nBlockYSize, nBands * nDataTypeSize);
579 18 : if (pabyMEMDSBuffer == NULL)
580 : {
581 0 : OGRReleaseDataSource(hDS);
582 0 : return NULL;
583 : }
584 :
585 18 : CPLString osTempFileName;
586 18 : osTempFileName.Printf("/vsimem/%p", hDS);
587 :
588 18 : int nTileId = 0;
589 18 : int nBlocks = 0;
590 18 : int nTotalBlocks = nXBlocks * nYBlocks;
591 :
592 18 : char** papszTileDriverOptions = RasterliteGetTileDriverOptions(papszOptions);
593 :
594 18 : OGR_DS_ExecuteSQL(hDS, "BEGIN", NULL, NULL);
595 :
596 18 : CPLErr eErr = CE_None;
597 : int nBlockXOff, nBlockYOff;
598 36 : for(nBlockYOff=0;eErr == CE_None && nBlockYOff<nYBlocks;nBlockYOff++)
599 : {
600 36 : for(nBlockXOff=0;eErr == CE_None && nBlockXOff<nXBlocks;nBlockXOff++)
601 : {
602 : /* -------------------------------------------------------------------- */
603 : /* Create in-memory tile */
604 : /* -------------------------------------------------------------------- */
605 18 : int nReqXSize = nBlockXSize, nReqYSize = nBlockYSize;
606 18 : if ((nBlockXOff+1) * nBlockXSize > nXSize)
607 18 : nReqXSize = nXSize - nBlockXOff * nBlockXSize;
608 18 : if ((nBlockYOff+1) * nBlockYSize > nYSize)
609 18 : nReqYSize = nYSize - nBlockYOff * nBlockYSize;
610 :
611 : eErr = poSrcDS->RasterIO(GF_Read,
612 : nBlockXOff * nBlockXSize,
613 : nBlockYOff * nBlockYSize,
614 : nReqXSize, nReqYSize,
615 : pabyMEMDSBuffer, nReqXSize, nReqYSize,
616 : eDataType, nBands, NULL,
617 18 : 0, 0, 0);
618 18 : if (eErr != CE_None)
619 : {
620 0 : break;
621 : }
622 :
623 : GDALDatasetH hMemDS = GDALCreate(hMemDriver, "MEM:::",
624 : nReqXSize, nReqYSize, 0,
625 18 : eDataType, NULL);
626 18 : if (hMemDS == NULL)
627 : {
628 0 : eErr = CE_Failure;
629 0 : break;
630 : }
631 :
632 : int iBand;
633 48 : for(iBand = 0; iBand < nBands; iBand ++)
634 : {
635 30 : char** papszMEMDSOptions = NULL;
636 : char szTmp[64];
637 30 : memset(szTmp, 0, sizeof(szTmp));
638 : CPLPrintPointer(szTmp,
639 : pabyMEMDSBuffer + iBand * nDataTypeSize *
640 30 : nReqXSize * nReqYSize, sizeof(szTmp));
641 30 : papszMEMDSOptions = CSLSetNameValue(papszMEMDSOptions, "DATAPOINTER", szTmp);
642 30 : GDALAddBand(hMemDS, eDataType, papszMEMDSOptions);
643 30 : CSLDestroy(papszMEMDSOptions);
644 : }
645 :
646 : GDALDatasetH hOutDS = GDALCreateCopy(hTileDriver,
647 : osTempFileName.c_str(), hMemDS, FALSE,
648 18 : papszTileDriverOptions, NULL, NULL);
649 :
650 18 : GDALClose(hMemDS);
651 18 : if (hOutDS)
652 18 : GDALClose(hOutDS);
653 : else
654 : {
655 0 : eErr = CE_Failure;
656 0 : break;
657 : }
658 :
659 : /* -------------------------------------------------------------------- */
660 : /* Insert new entry into raster table */
661 : /* -------------------------------------------------------------------- */
662 :
663 18 : vsi_l_offset nDataLength = 0;
664 : GByte *pabyData = VSIGetMemFileBuffer( osTempFileName.c_str(),
665 36 : &nDataLength, FALSE);
666 :
667 18 : OGRFeatureH hFeat = OGR_F_Create( OGR_L_GetLayerDefn(hRasterLayer) );
668 18 : OGR_F_SetFieldBinary(hFeat, 0, (int)nDataLength, pabyData);
669 :
670 18 : OGR_L_CreateFeature(hRasterLayer, hFeat);
671 : /* Query raster ID to set it as the ID of the associated metadata */
672 18 : int nRasterID = (int)OGR_F_GetFID(hFeat);
673 :
674 18 : OGR_F_Destroy(hFeat);
675 :
676 18 : VSIUnlink(osTempFileName.c_str());
677 :
678 : /* -------------------------------------------------------------------- */
679 : /* Insert new entry into metadata table */
680 : /* -------------------------------------------------------------------- */
681 :
682 18 : hFeat = OGR_F_Create( OGR_L_GetLayerDefn(hMetadataLayer) );
683 18 : OGR_F_SetFID(hFeat, nRasterID);
684 18 : OGR_F_SetFieldString(hFeat, 0, GDALGetDescription(poSrcDS));
685 18 : OGR_F_SetFieldInteger(hFeat, 1, nTileId ++);
686 18 : OGR_F_SetFieldInteger(hFeat, 2, nReqXSize);
687 18 : OGR_F_SetFieldInteger(hFeat, 3, nReqYSize);
688 18 : OGR_F_SetFieldDouble(hFeat, 4, adfGeoTransform[1]);
689 18 : OGR_F_SetFieldDouble(hFeat, 5, -adfGeoTransform[5]);
690 :
691 18 : minx = adfGeoTransform[0] +
692 18 : (nBlockXSize * nBlockXOff) * adfGeoTransform[1];
693 18 : maxx = adfGeoTransform[0] +
694 18 : (nBlockXSize * nBlockXOff + nReqXSize) * adfGeoTransform[1];
695 18 : maxy = adfGeoTransform[3] +
696 18 : (nBlockYSize * nBlockYOff) * adfGeoTransform[5];
697 18 : miny = adfGeoTransform[3] +
698 18 : (nBlockYSize * nBlockYOff + nReqYSize) * adfGeoTransform[5];
699 :
700 18 : OGRGeometryH hRectangle = OGR_G_CreateGeometry(wkbPolygon);
701 18 : OGRGeometryH hLinearRing = OGR_G_CreateGeometry(wkbLinearRing);
702 18 : OGR_G_AddPoint_2D(hLinearRing, minx, miny);
703 18 : OGR_G_AddPoint_2D(hLinearRing, minx, maxy);
704 18 : OGR_G_AddPoint_2D(hLinearRing, maxx, maxy);
705 18 : OGR_G_AddPoint_2D(hLinearRing, maxx, miny);
706 18 : OGR_G_AddPoint_2D(hLinearRing, minx, miny);
707 18 : OGR_G_AddGeometryDirectly(hRectangle, hLinearRing);
708 :
709 18 : OGR_F_SetGeometryDirectly(hFeat, hRectangle);
710 :
711 18 : OGR_L_CreateFeature(hMetadataLayer, hFeat);
712 18 : OGR_F_Destroy(hFeat);
713 :
714 18 : nBlocks++;
715 18 : if (pfnProgress && !pfnProgress(1.0 * nBlocks / nTotalBlocks,
716 : NULL, pProgressData))
717 0 : eErr = CE_Failure;
718 : }
719 : }
720 :
721 18 : if (eErr == CE_None)
722 18 : OGR_DS_ExecuteSQL(hDS, "COMMIT", NULL, NULL);
723 : else
724 0 : OGR_DS_ExecuteSQL(hDS, "ROLLBACK", NULL, NULL);
725 :
726 18 : CSLDestroy(papszTileDriverOptions);
727 :
728 18 : VSIFree(pabyMEMDSBuffer);
729 :
730 18 : OGRReleaseDataSource(hDS);
731 :
732 18 : return (GDALDataset*) GDALOpen(pszFilename, GA_Update);
733 : }
734 :
735 : /************************************************************************/
736 : /* RasterliteDelete () */
737 : /************************************************************************/
738 :
739 3 : CPLErr RasterliteDelete(const char* pszFilename)
740 : {
741 3 : return CE_None;
742 : }
|