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