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