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