1 : /******************************************************************************
2 : * $Id: rasterlitecreatecopy.cpp 18603 2010-01-19 23:10:31Z 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 18603 2010-01-19 23:10:31Z rouault $");
37 :
38 : /************************************************************************/
39 : /* RasterliteGetTileDriverOptions () */
40 : /************************************************************************/
41 :
42 : static char** RasterliteAddTileDriverOptionsForDriver(char** papszOptions,
43 : char** papszTileDriverOptions,
44 : const char* pszOptionName,
45 72 : const char* pszExpectedDriverName)
46 : {
47 72 : const char* pszVal = CSLFetchNameValue(papszOptions, pszOptionName);
48 72 : 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 72 : return papszTileDriverOptions;
65 : }
66 :
67 18 : static char** RasterliteGetTileDriverOptions(char** papszOptions)
68 : {
69 18 : char** papszTileDriverOptions = NULL;
70 :
71 : const char* pszDriverName =
72 18 : CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff");
73 :
74 18 : if (EQUAL(pszDriverName, "EPSILON"))
75 : {
76 : papszTileDriverOptions = CSLSetNameValue(papszTileDriverOptions,
77 2 : "RASTERLITE_OUTPUT", "YES");
78 : }
79 :
80 18 : const char* pszQuality = CSLFetchNameValue(papszOptions, "QUALITY");
81 18 : 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"))
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 18 : papszOptions, papszTileDriverOptions, "COMPRESS", "GTiff");
103 : papszTileDriverOptions = RasterliteAddTileDriverOptionsForDriver(
104 18 : papszOptions, papszTileDriverOptions, "PHOTOMETRIC", "GTiff");
105 : papszTileDriverOptions = RasterliteAddTileDriverOptionsForDriver(
106 18 : papszOptions, papszTileDriverOptions, "TARGET", "EPSILON");
107 : papszTileDriverOptions = RasterliteAddTileDriverOptionsForDriver(
108 18 : papszOptions, papszTileDriverOptions, "FILTER", "EPSILON");
109 :
110 18 : 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 18 : nSRSId = nAuthorityCode;
154 :
155 18 : 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 2 : 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 16 : nAuthorityCode, osProj4.c_str() );
169 :
170 :
171 18 : OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
172 : }
173 : else
174 : {
175 0 : OGRFeatureH hFeat = OGR_L_GetNextFeature(hLyr);
176 0 : if (hFeat)
177 : {
178 0 : nSRSId = OGR_F_GetFieldAsInteger(hFeat, 0);
179 0 : OGR_F_Destroy(hFeat);
180 : }
181 0 : OGR_DS_ReleaseResultSet(hDS, hLyr);
182 : }
183 : }
184 :
185 18 : return nSRSId;
186 : }
187 :
188 : /************************************************************************/
189 : /* RasterliteCreateTables () */
190 : /************************************************************************/
191 :
192 : OGRDataSourceH RasterliteCreateTables(OGRDataSourceH hDS, const char* pszTableName,
193 18 : 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 : /* Re-open the DB to take into account the new tables*/
255 18 : OGRReleaseDataSource(hDS);
256 :
257 18 : CPLSetConfigOption("SQLITE_LIST_ALL_TABLES", "TRUE");
258 18 : hDS = OGROpen(osDBName.c_str(), TRUE, NULL);
259 18 : CPLSetConfigOption("SQLITE_LIST_ALL_TABLES", osOldVal.c_str());
260 : }
261 : else
262 : {
263 : /* Check that the existing SRS is consistent with the one of the new */
264 : /* data to be inserted */
265 : osSQL.Printf("SELECT srid FROM geometry_columns WHERE f_table_name = '%s'",
266 0 : osMetatadataLayer.c_str());
267 0 : hLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
268 0 : if (hLyr)
269 : {
270 0 : int nExistingSRID = -1;
271 0 : OGRFeatureH hFeat = OGR_L_GetNextFeature(hLyr);
272 0 : if (hFeat)
273 : {
274 0 : nExistingSRID = OGR_F_GetFieldAsInteger(hFeat, 0);
275 0 : OGR_F_Destroy(hFeat);
276 : }
277 0 : OGR_DS_ReleaseResultSet(hDS, hLyr);
278 :
279 0 : if (nExistingSRID != nSRSId)
280 : {
281 0 : if (bWipeExistingData)
282 : {
283 : osSQL.Printf("UPDATE geometry_columns SET srid = %d "
284 : "WHERE f_table_name = \"%s\"",
285 0 : nSRSId, osMetatadataLayer.c_str());
286 0 : OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
287 :
288 : /* Re-open the DB to take into account the change of SRS */
289 0 : OGRReleaseDataSource(hDS);
290 :
291 0 : CPLSetConfigOption("SQLITE_LIST_ALL_TABLES", "TRUE");
292 0 : hDS = OGROpen(osDBName.c_str(), TRUE, NULL);
293 0 : CPLSetConfigOption("SQLITE_LIST_ALL_TABLES", osOldVal.c_str());
294 : }
295 : else
296 : {
297 : CPLError(CE_Failure, CPLE_NotSupported,
298 0 : "New data has not the same SRS as existing data");
299 0 : OGRReleaseDataSource(hDS);
300 0 : return NULL;
301 : }
302 : }
303 : }
304 :
305 0 : if (bWipeExistingData)
306 : {
307 0 : osSQL.Printf("DELETE FROM \"%s\"", osRasterLayer.c_str());
308 0 : OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
309 :
310 0 : osSQL.Printf("DELETE FROM \"%s\"", osMetatadataLayer.c_str());
311 0 : OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
312 : }
313 : }
314 :
315 18 : return hDS;
316 : }
317 :
318 : /************************************************************************/
319 : /* RasterliteCreateCopy () */
320 : /************************************************************************/
321 :
322 : GDALDataset *
323 : RasterliteCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
324 : int bStrict, char ** papszOptions,
325 19 : GDALProgressFunc pfnProgress, void * pProgressData )
326 : {
327 19 : int nBands = poSrcDS->GetRasterCount();
328 19 : if (nBands == 0)
329 : {
330 1 : CPLError(CE_Failure, CPLE_NotSupported, "nBands == 0");
331 1 : return NULL;
332 : }
333 :
334 18 : const char* pszDriverName = CSLFetchNameValueDef(papszOptions, "DRIVER", "GTiff");
335 18 : GDALDriverH hTileDriver = GDALGetDriverByName(pszDriverName);
336 18 : if ( hTileDriver == NULL)
337 : {
338 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL %s driver", pszDriverName);
339 0 : return NULL;
340 : }
341 :
342 18 : GDALDriverH hMemDriver = GDALGetDriverByName("MEM");
343 18 : if (hMemDriver == NULL)
344 : {
345 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot load GDAL MEM driver");
346 0 : return NULL;
347 : }
348 :
349 18 : int nXSize = GDALGetRasterXSize(poSrcDS);
350 18 : int nYSize = GDALGetRasterYSize(poSrcDS);
351 :
352 : double adfGeoTransform[6];
353 18 : if (poSrcDS->GetGeoTransform(adfGeoTransform) != CE_None)
354 : {
355 0 : adfGeoTransform[0] = 0;
356 0 : adfGeoTransform[1] = 1;
357 0 : adfGeoTransform[2] = 0;
358 0 : adfGeoTransform[3] = 0;
359 0 : adfGeoTransform[4] = 0;
360 0 : adfGeoTransform[5] = -1;
361 : }
362 18 : else if (adfGeoTransform[2] != 0.0 || adfGeoTransform[4] != 0.0)
363 : {
364 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot use geotransform with rotational terms");
365 0 : return NULL;
366 : }
367 :
368 18 : int bTiled = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "TILED", "YES"));
369 : int nBlockXSize, nBlockYSize;
370 18 : if (bTiled)
371 : {
372 18 : nBlockXSize = atoi(CSLFetchNameValueDef(papszOptions, "BLOCKXSIZE", "256"));
373 18 : nBlockYSize = atoi(CSLFetchNameValueDef(papszOptions, "BLOCKYSIZE", "256"));
374 18 : if (nBlockXSize < 64) nBlockXSize = 64;
375 18 : else if (nBlockXSize > 4096) nBlockXSize = 4096;
376 18 : if (nBlockYSize < 64) nBlockYSize = 64;
377 18 : else if (nBlockYSize > 4096) nBlockYSize = 4096;
378 : }
379 : else
380 : {
381 0 : nBlockXSize = nXSize;
382 0 : nBlockYSize = nYSize;
383 : }
384 :
385 : /* -------------------------------------------------------------------- */
386 : /* Analyze arguments */
387 : /* -------------------------------------------------------------------- */
388 :
389 18 : CPLString osDBName;
390 18 : CPLString osTableName;
391 : VSIStatBuf sBuf;
392 : int bExists;
393 :
394 : /* Skip optionnal RASTERLITE: prefix */
395 18 : const char* pszFilenameWithoutPrefix = pszFilename;
396 18 : if (EQUALN(pszFilename, "RASTERLITE:", 11))
397 1 : pszFilenameWithoutPrefix += 11;
398 :
399 : char** papszTokens = CSLTokenizeStringComplex(
400 18 : pszFilenameWithoutPrefix, ", ", FALSE, FALSE );
401 18 : int nTokens = CSLCount(papszTokens);
402 18 : if (nTokens == 0)
403 : {
404 0 : osDBName = pszFilenameWithoutPrefix;
405 0 : osTableName = CPLGetBasename(pszFilenameWithoutPrefix);
406 : }
407 : else
408 : {
409 18 : osDBName = papszTokens[0];
410 :
411 : int i;
412 19 : for(i=1;i<nTokens;i++)
413 : {
414 1 : if (EQUALN(papszTokens[i], "table=", 6))
415 1 : osTableName = papszTokens[i] + 6;
416 : else
417 : {
418 : CPLError(CE_Warning, CPLE_AppDefined,
419 0 : "Invalid option : %s", papszTokens[i]);
420 : }
421 : }
422 : }
423 :
424 18 : CSLDestroy(papszTokens);
425 18 : papszTokens = NULL;
426 :
427 18 : bExists = (VSIStat(osDBName.c_str(), &sBuf) == 0);
428 :
429 18 : if (osTableName.size() == 0)
430 : {
431 17 : if (bExists)
432 : {
433 : CPLError(CE_Failure, CPLE_AppDefined,
434 0 : "Database already exists. Explicit table name must be specified");
435 18 : return NULL;
436 : }
437 17 : osTableName = CPLGetBasename(osDBName.c_str());
438 : }
439 :
440 18 : CPLString osRasterLayer;
441 18 : osRasterLayer.Printf("%s_rasters", osTableName.c_str());
442 :
443 18 : CPLString osMetatadataLayer;
444 18 : osMetatadataLayer.Printf("%s_metadata", osTableName.c_str());
445 :
446 : /* -------------------------------------------------------------------- */
447 : /* Create or open the SQLite DB */
448 : /* -------------------------------------------------------------------- */
449 :
450 18 : if (OGRGetDriverCount() == 0)
451 0 : OGRRegisterAll();
452 :
453 18 : OGRSFDriverH hSQLiteDriver = OGRGetDriverByName("SQLite");
454 18 : if (hSQLiteDriver == NULL)
455 : {
456 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot load OGR SQLite driver");
457 0 : return NULL;
458 : }
459 :
460 : OGRDataSourceH hDS;
461 :
462 : CPLString osOldVal =
463 18 : CPLGetConfigOption("SQLITE_LIST_ALL_TABLES", "FALSE");
464 18 : CPLSetConfigOption("SQLITE_LIST_ALL_TABLES", "TRUE");
465 18 : if (!bExists)
466 : {
467 18 : char** papszOGROptions = CSLAddString(NULL, "SPATIALITE=YES");
468 : hDS = OGR_Dr_CreateDataSource(hSQLiteDriver,
469 18 : osDBName.c_str(), papszOGROptions);
470 18 : CSLDestroy(papszOGROptions);
471 : }
472 : else
473 : {
474 0 : hDS = OGROpen(osDBName.c_str(), TRUE, NULL);
475 : }
476 18 : CPLSetConfigOption("SQLITE_LIST_ALL_TABLES", osOldVal.c_str());
477 :
478 18 : if (hDS == NULL)
479 : {
480 : CPLError(CE_Failure, CPLE_AppDefined,
481 0 : "Cannot load or create SQLite database");
482 0 : return NULL;
483 : }
484 :
485 18 : CPLString osSQL;
486 :
487 : /* -------------------------------------------------------------------- */
488 : /* Get the SRID for the SRS */
489 : /* -------------------------------------------------------------------- */
490 18 : int nSRSId = RasterliteInsertSRID(hDS, poSrcDS->GetProjectionRef());
491 :
492 : /* -------------------------------------------------------------------- */
493 : /* Create or wipe existing tables */
494 : /* -------------------------------------------------------------------- */
495 : int bWipeExistingData =
496 18 : CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "WIPE", "NO"));
497 :
498 : hDS = RasterliteCreateTables(hDS, osTableName.c_str(),
499 18 : nSRSId, bWipeExistingData);
500 18 : if (hDS == NULL)
501 0 : return NULL;
502 :
503 18 : OGRLayerH hRasterLayer = OGR_DS_GetLayerByName(hDS, osRasterLayer.c_str());
504 18 : OGRLayerH hMetadataLayer = OGR_DS_GetLayerByName(hDS, osMetatadataLayer.c_str());
505 18 : if (hRasterLayer == NULL || hMetadataLayer == NULL)
506 : {
507 : CPLError(CE_Failure, CPLE_AppDefined,
508 0 : "Cannot find metadata and/or raster tables");
509 0 : OGRReleaseDataSource(hDS);
510 0 : return NULL;
511 : }
512 :
513 : /* -------------------------------------------------------------------- */
514 : /* Check if there is overlapping data and warn the user */
515 : /* -------------------------------------------------------------------- */
516 18 : double minx = adfGeoTransform[0];
517 18 : double maxx = adfGeoTransform[0] + nXSize * adfGeoTransform[1];
518 18 : double maxy = adfGeoTransform[3];
519 18 : double miny = adfGeoTransform[3] + nYSize * adfGeoTransform[5];
520 :
521 : osSQL.Printf("SELECT COUNT(geometry) FROM \"%s\" "
522 : "WHERE rowid IN "
523 : "(SELECT pkid FROM \"idx_%s_metadata_geometry\" "
524 : "WHERE xmin < %.15f AND xmax > %.15f "
525 : "AND ymin < %.15f AND ymax > %.15f) "
526 : "AND pixel_x_size >= %.15f AND pixel_x_size <= %.15f AND "
527 : "pixel_y_size >= %.15f AND pixel_y_size <= %.15f",
528 : osMetatadataLayer.c_str(),
529 : osTableName.c_str(),
530 : maxx, minx, maxy, miny,
531 : adfGeoTransform[1] - 1e-15, adfGeoTransform[1] + 1e-15,
532 18 : - adfGeoTransform[5] - 1e-15, - adfGeoTransform[5] + 1e-15);
533 :
534 18 : int nOverlappingGeoms = 0;
535 18 : OGRLayerH hCountLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
536 18 : if (hCountLyr)
537 : {
538 18 : OGRFeatureH hFeat = OGR_L_GetNextFeature(hCountLyr);
539 18 : if (hFeat)
540 : {
541 18 : nOverlappingGeoms = OGR_F_GetFieldAsInteger(hFeat, 0);
542 18 : OGR_F_Destroy(hFeat);
543 : }
544 18 : OGR_DS_ReleaseResultSet(hDS, hCountLyr);
545 : }
546 :
547 18 : if (nOverlappingGeoms != 0)
548 : {
549 : CPLError(CE_Warning, CPLE_AppDefined,
550 : "Raster tiles already exist in the %s table within "
551 : "the extent of the data to be inserted in",
552 0 : osTableName.c_str());
553 : }
554 :
555 : /* -------------------------------------------------------------------- */
556 : /* Iterate over blocks to add data into raster and metadata tables */
557 : /* -------------------------------------------------------------------- */
558 18 : int nXBlocks = (nXSize + nBlockXSize - 1) / nBlockXSize;
559 18 : int nYBlocks = (nYSize + nBlockYSize - 1) / nBlockYSize;
560 :
561 18 : GDALDataType eDataType = poSrcDS->GetRasterBand(1)->GetRasterDataType();
562 18 : int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8;
563 : GByte* pabyMEMDSBuffer =
564 18 : (GByte*)VSIMalloc3(nBlockXSize, nBlockYSize, nBands * nDataTypeSize);
565 18 : if (pabyMEMDSBuffer == NULL)
566 : {
567 0 : OGRReleaseDataSource(hDS);
568 0 : return NULL;
569 : }
570 :
571 18 : CPLString osTempFileName;
572 18 : osTempFileName.Printf("/vsimem/%p", hDS);
573 :
574 18 : int nTileId = 0;
575 18 : int nBlocks = 0;
576 18 : int nTotalBlocks = nXBlocks * nYBlocks;
577 :
578 18 : char** papszTileDriverOptions = RasterliteGetTileDriverOptions(papszOptions);
579 :
580 18 : OGR_DS_ExecuteSQL(hDS, "BEGIN", NULL, NULL);
581 :
582 18 : CPLErr eErr = CE_None;
583 : int nBlockXOff, nBlockYOff;
584 36 : for(nBlockYOff=0;eErr == CE_None && nBlockYOff<nYBlocks;nBlockYOff++)
585 : {
586 36 : for(nBlockXOff=0;eErr == CE_None && nBlockXOff<nXBlocks;nBlockXOff++)
587 : {
588 : /* -------------------------------------------------------------------- */
589 : /* Create in-memory tile */
590 : /* -------------------------------------------------------------------- */
591 18 : int nReqXSize = nBlockXSize, nReqYSize = nBlockYSize;
592 18 : if ((nBlockXOff+1) * nBlockXSize > nXSize)
593 18 : nReqXSize = nXSize - nBlockXOff * nBlockXSize;
594 18 : if ((nBlockYOff+1) * nBlockYSize > nYSize)
595 18 : nReqYSize = nYSize - nBlockYOff * nBlockYSize;
596 :
597 : eErr = poSrcDS->RasterIO(GF_Read,
598 : nBlockXOff * nBlockXSize,
599 : nBlockYOff * nBlockYSize,
600 : nReqXSize, nReqYSize,
601 : pabyMEMDSBuffer, nReqXSize, nReqYSize,
602 : eDataType, nBands, NULL,
603 18 : 0, 0, 0);
604 18 : if (eErr != CE_None)
605 : {
606 0 : break;
607 : }
608 :
609 : GDALDatasetH hMemDS = GDALCreate(hMemDriver, "MEM:::",
610 : nReqXSize, nReqYSize, 0,
611 18 : eDataType, NULL);
612 18 : if (hMemDS == NULL)
613 : {
614 0 : eErr = CE_Failure;
615 0 : break;
616 : }
617 :
618 : int iBand;
619 48 : for(iBand = 0; iBand < nBands; iBand ++)
620 : {
621 30 : char** papszMEMDSOptions = NULL;
622 : char szTmp[64];
623 30 : memset(szTmp, 0, sizeof(szTmp));
624 : CPLPrintPointer(szTmp,
625 : pabyMEMDSBuffer + iBand * nDataTypeSize *
626 30 : nReqXSize * nReqYSize, sizeof(szTmp));
627 30 : papszMEMDSOptions = CSLSetNameValue(papszMEMDSOptions, "DATAPOINTER", szTmp);
628 30 : GDALAddBand(hMemDS, eDataType, papszMEMDSOptions);
629 30 : CSLDestroy(papszMEMDSOptions);
630 : }
631 :
632 : GDALDatasetH hOutDS = GDALCreateCopy(hTileDriver,
633 : osTempFileName.c_str(), hMemDS, FALSE,
634 18 : papszTileDriverOptions, NULL, NULL);
635 :
636 18 : GDALClose(hMemDS);
637 18 : if (hOutDS)
638 18 : GDALClose(hOutDS);
639 : else
640 : {
641 0 : eErr = CE_Failure;
642 0 : break;
643 : }
644 :
645 : /* -------------------------------------------------------------------- */
646 : /* Insert new entry into raster table */
647 : /* -------------------------------------------------------------------- */
648 :
649 : vsi_l_offset nDataLength;
650 : GByte *pabyData = VSIGetMemFileBuffer( osTempFileName.c_str(),
651 36 : &nDataLength, FALSE);
652 :
653 18 : OGRFeatureH hFeat = OGR_F_Create( OGR_L_GetLayerDefn(hRasterLayer) );
654 18 : OGR_F_SetFieldBinary(hFeat, 0, (int)nDataLength, pabyData);
655 :
656 18 : OGR_L_CreateFeature(hRasterLayer, hFeat);
657 : /* Query raster ID to set it as the ID of the associated metadata */
658 18 : int nRasterID = (int)OGR_F_GetFID(hFeat);
659 :
660 18 : OGR_F_Destroy(hFeat);
661 :
662 18 : VSIUnlink(osTempFileName.c_str());
663 :
664 : /* -------------------------------------------------------------------- */
665 : /* Insert new entry into metadata table */
666 : /* -------------------------------------------------------------------- */
667 :
668 18 : hFeat = OGR_F_Create( OGR_L_GetLayerDefn(hMetadataLayer) );
669 18 : OGR_F_SetFID(hFeat, nRasterID);
670 18 : OGR_F_SetFieldString(hFeat, 0, GDALGetDescription(poSrcDS));
671 18 : OGR_F_SetFieldInteger(hFeat, 1, nTileId ++);
672 18 : OGR_F_SetFieldInteger(hFeat, 2, nReqXSize);
673 18 : OGR_F_SetFieldInteger(hFeat, 3, nReqYSize);
674 18 : OGR_F_SetFieldDouble(hFeat, 4, adfGeoTransform[1]);
675 18 : OGR_F_SetFieldDouble(hFeat, 5, -adfGeoTransform[5]);
676 :
677 : minx = adfGeoTransform[0] +
678 18 : (nBlockXSize * nBlockXOff) * adfGeoTransform[1];
679 : maxx = adfGeoTransform[0] +
680 18 : (nBlockXSize * nBlockXOff + nReqXSize) * adfGeoTransform[1];
681 : maxy = adfGeoTransform[3] +
682 18 : (nBlockYSize * nBlockYOff) * adfGeoTransform[5];
683 : miny = adfGeoTransform[3] +
684 18 : (nBlockYSize * nBlockYOff + nReqYSize) * adfGeoTransform[5];
685 :
686 18 : OGRGeometryH hRectangle = OGR_G_CreateGeometry(wkbPolygon);
687 18 : OGRGeometryH hLinearRing = OGR_G_CreateGeometry(wkbLinearRing);
688 18 : OGR_G_AddPoint_2D(hLinearRing, minx, miny);
689 18 : OGR_G_AddPoint_2D(hLinearRing, minx, maxy);
690 18 : OGR_G_AddPoint_2D(hLinearRing, maxx, maxy);
691 18 : OGR_G_AddPoint_2D(hLinearRing, maxx, miny);
692 18 : OGR_G_AddPoint_2D(hLinearRing, minx, miny);
693 18 : OGR_G_AddGeometryDirectly(hRectangle, hLinearRing);
694 :
695 18 : OGR_F_SetGeometryDirectly(hFeat, hRectangle);
696 :
697 18 : OGR_L_CreateFeature(hMetadataLayer, hFeat);
698 18 : OGR_F_Destroy(hFeat);
699 :
700 18 : nBlocks++;
701 18 : if (pfnProgress && !pfnProgress(1.0 * nBlocks / nTotalBlocks,
702 : NULL, pProgressData))
703 0 : eErr = CE_Failure;
704 : }
705 : }
706 :
707 18 : if (eErr == CE_None)
708 18 : OGR_DS_ExecuteSQL(hDS, "COMMIT", NULL, NULL);
709 : else
710 0 : OGR_DS_ExecuteSQL(hDS, "ROLLBACK", NULL, NULL);
711 :
712 18 : CSLDestroy(papszTileDriverOptions);
713 :
714 18 : VSIFree(pabyMEMDSBuffer);
715 :
716 18 : OGRReleaseDataSource(hDS);
717 :
718 18 : return (GDALDataset*) GDALOpen(pszFilename, GA_Update);
719 : }
720 :
721 : /************************************************************************/
722 : /* RasterliteDelete () */
723 : /************************************************************************/
724 :
725 3 : CPLErr RasterliteDelete(const char* pszFilename)
726 : {
727 3 : return CE_None;
728 : }
|