1 : /******************************************************************************
2 : * $Id: rasterlitedataset.cpp 23712 2012-01-06 22:27:40Z 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 "gdal_frmts.h"
31 : #include "cpl_string.h"
32 : #include "ogr_api.h"
33 : #include "ogr_srs_api.h"
34 :
35 : #include "rasterlitedataset.h"
36 :
37 : CPL_CVSID("$Id: rasterlitedataset.cpp 23712 2012-01-06 22:27:40Z rouault $");
38 :
39 : /************************************************************************/
40 : /* RasterliteBand() */
41 : /************************************************************************/
42 :
43 114 : RasterliteBand::RasterliteBand(RasterliteDataset* poDS, int nBand,
44 : GDALDataType eDataType,
45 114 : int nBlockXSize, int nBlockYSize)
46 : {
47 114 : this->poDS = poDS;
48 114 : this->nBand = nBand;
49 114 : this->eDataType = eDataType;
50 114 : this->nBlockXSize = nBlockXSize;
51 114 : this->nBlockYSize = nBlockYSize;
52 114 : }
53 :
54 : /************************************************************************/
55 : /* IReadBlock() */
56 : /************************************************************************/
57 :
58 : //#define RASTERLITE_DEBUG
59 :
60 32 : CPLErr RasterliteBand::IReadBlock( int nBlockXOff, int nBlockYOff, void * pImage)
61 : {
62 32 : RasterliteDataset* poGDS = (RasterliteDataset*) poDS;
63 :
64 32 : double minx = poGDS->adfGeoTransform[0] +
65 32 : nBlockXOff * nBlockXSize * poGDS->adfGeoTransform[1];
66 32 : double maxx = poGDS->adfGeoTransform[0] +
67 32 : (nBlockXOff + 1) * nBlockXSize * poGDS->adfGeoTransform[1];
68 32 : double maxy = poGDS->adfGeoTransform[3] +
69 32 : nBlockYOff * nBlockYSize * poGDS->adfGeoTransform[5];
70 32 : double miny = poGDS->adfGeoTransform[3] +
71 32 : (nBlockYOff + 1) * nBlockYSize * poGDS->adfGeoTransform[5];
72 32 : int nDataTypeSize = GDALGetDataTypeSize(eDataType) / 8;
73 :
74 : #ifdef RASTERLITE_DEBUG
75 : if (nBand == 1)
76 : {
77 : printf("nBlockXOff = %d, nBlockYOff = %d, nBlockXSize = %d, nBlockYSize = %d\n"
78 : "minx=%.15f miny=%.15f maxx=%.15f maxy=%.15f\n",
79 : nBlockXOff, nBlockYOff, nBlockXSize, nBlockYSize, minx, miny, maxx, maxy);
80 : }
81 : #endif
82 :
83 32 : CPLString osSQL;
84 : osSQL.Printf("SELECT m.geometry, r.raster, m.id, m.width, m.height FROM \"%s_metadata\" AS m, "
85 : "\"%s_rasters\" AS r WHERE m.rowid IN "
86 : "(SELECT pkid FROM \"idx_%s_metadata_geometry\" "
87 : "WHERE xmin < %.15f AND xmax > %.15f "
88 : "AND ymin < %.15f AND ymax > %.15f) "
89 : "AND m.pixel_x_size >= %.15f AND m.pixel_x_size <= %.15f AND "
90 : "m.pixel_y_size >= %.15f AND m.pixel_y_size <= %.15f AND r.id = m.id",
91 : poGDS->osTableName.c_str(),
92 : poGDS->osTableName.c_str(),
93 : poGDS->osTableName.c_str(),
94 : maxx, minx, maxy, miny,
95 64 : poGDS->adfGeoTransform[1] - 1e-15, poGDS->adfGeoTransform[1] + 1e-15,
96 96 : - poGDS->adfGeoTransform[5] - 1e-15, - poGDS->adfGeoTransform[5] + 1e-15);
97 :
98 32 : OGRLayerH hSQLLyr = OGR_DS_ExecuteSQL(poGDS->hDS, osSQL.c_str(), NULL, NULL);
99 32 : if (hSQLLyr == NULL)
100 : {
101 0 : memset(pImage, 0, nBlockXSize * nBlockYSize * nDataTypeSize);
102 0 : return CE_None;
103 : }
104 :
105 32 : CPLString osMemFileName;
106 32 : osMemFileName.Printf("/vsimem/%p", this);
107 :
108 32 : int bHasFoundTile = FALSE;
109 32 : int bHasMemsetTile = FALSE;
110 :
111 : #ifdef RASTERLITE_DEBUG
112 : if (nBand == 1)
113 : {
114 : printf("nTiles = %d\n", OGR_L_GetFeatureCount(hSQLLyr, TRUE));
115 : }
116 : #endif
117 :
118 : OGRFeatureH hFeat;
119 96 : while( (hFeat = OGR_L_GetNextFeature(hSQLLyr)) != NULL )
120 : {
121 32 : OGRGeometryH hGeom = OGR_F_GetGeometryRef(hFeat);
122 32 : if (hGeom == NULL)
123 : {
124 0 : CPLError(CE_Failure, CPLE_AppDefined, "null geometry found");
125 0 : OGR_F_Destroy(hFeat);
126 0 : OGR_DS_ReleaseResultSet(poGDS->hDS, hSQLLyr);
127 0 : return CE_Failure;
128 : }
129 :
130 32 : OGREnvelope oEnvelope;
131 32 : OGR_G_GetEnvelope(hGeom, &oEnvelope);
132 :
133 32 : int nTileId = OGR_F_GetFieldAsInteger(hFeat, 1);
134 32 : int nTileXSize = OGR_F_GetFieldAsInteger(hFeat, 2);
135 32 : int nTileYSize = OGR_F_GetFieldAsInteger(hFeat, 3);
136 :
137 : int nDstXOff =
138 32 : (int)((oEnvelope.MinX - minx) / poGDS->adfGeoTransform[1] + 0.5);
139 : int nDstYOff =
140 32 : (int)((maxy - oEnvelope.MaxY) / (-poGDS->adfGeoTransform[5]) + 0.5);
141 :
142 32 : int nReqXSize = nTileXSize;
143 32 : int nReqYSize = nTileYSize;
144 :
145 : int nSrcXOff, nSrcYOff;
146 :
147 32 : if (nDstXOff >= 0)
148 : {
149 30 : nSrcXOff = 0;
150 : }
151 : else
152 : {
153 2 : nSrcXOff = -nDstXOff;
154 2 : nReqXSize += nDstXOff;
155 2 : nDstXOff = 0;
156 : }
157 :
158 :
159 32 : if (nDstYOff >= 0)
160 : {
161 30 : nSrcYOff = 0;
162 : }
163 : else
164 : {
165 2 : nSrcYOff = -nDstYOff;
166 2 : nReqYSize += nDstYOff;
167 2 : nDstYOff = 0;
168 : }
169 :
170 32 : if (nDstXOff + nReqXSize > nBlockXSize)
171 0 : nReqXSize = nBlockXSize - nDstXOff;
172 :
173 32 : if (nDstYOff + nReqYSize > nBlockYSize)
174 0 : nReqYSize = nBlockYSize - nDstYOff;
175 :
176 : #ifdef RASTERLITE_DEBUG
177 : if (nBand == 1)
178 : {
179 : printf("id = %d, minx=%.15f miny=%.15f maxx=%.15f maxy=%.15f\n"
180 : "nDstXOff = %d, nDstYOff = %d, nSrcXOff = %d, nSrcYOff = %d, "
181 : "nReqXSize=%d, nReqYSize=%d\n",
182 : nTileId,
183 : oEnvelope.MinX, oEnvelope.MinY, oEnvelope.MaxX, oEnvelope.MaxY,
184 : nDstXOff, nDstYOff,
185 : nSrcXOff, nSrcYOff, nReqXSize, nReqYSize);
186 : }
187 : #endif
188 :
189 32 : if (nReqXSize > 0 && nReqYSize > 0 &&
190 : nSrcXOff < nTileXSize && nSrcYOff < nTileYSize)
191 : {
192 :
193 : #ifdef RASTERLITE_DEBUG
194 : if (nBand == 1)
195 : {
196 : printf("id = %d, selected !\n", nTileId);
197 : }
198 : #endif
199 32 : int nDataSize = 0;
200 32 : GByte* pabyData = OGR_F_GetFieldAsBinary(hFeat, 0, &nDataSize);
201 :
202 : VSILFILE * fp = VSIFileFromMemBuffer( osMemFileName.c_str(), pabyData,
203 32 : nDataSize, FALSE);
204 32 : VSIFCloseL(fp);
205 :
206 32 : GDALDatasetH hDSTile = GDALOpen(osMemFileName.c_str(), GA_ReadOnly);
207 32 : int nTileBands = 0;
208 32 : if (hDSTile && (nTileBands = GDALGetRasterCount(hDSTile)) == 0)
209 : {
210 0 : GDALClose(hDSTile);
211 0 : hDSTile = NULL;
212 : }
213 32 : if (hDSTile == NULL)
214 : {
215 : CPLError(CE_Failure, CPLE_AppDefined, "Can't open tile %d",
216 0 : nTileId);
217 : }
218 :
219 32 : int nReqBand = 1;
220 32 : if (nTileBands == poGDS->nBands)
221 30 : nReqBand = nBand;
222 4 : else if (eDataType == GDT_Byte && nTileBands == 1 && poGDS->nBands == 3)
223 2 : nReqBand = 1;
224 : else
225 : {
226 0 : GDALClose(hDSTile);
227 0 : hDSTile = NULL;
228 : }
229 :
230 32 : if (hDSTile)
231 : {
232 32 : CPLAssert(GDALGetRasterXSize(hDSTile) == nTileXSize);
233 32 : CPLAssert(GDALGetRasterYSize(hDSTile) == nTileYSize);
234 :
235 32 : bHasFoundTile = TRUE;
236 :
237 32 : int bHasJustMemsetTileBand1 = FALSE;
238 :
239 : /* If the source tile doesn't fit the entire block size, then */
240 : /* we memset 0 before */
241 32 : if (!(nDstXOff == 0 && nDstYOff == 0 &&
242 : nReqXSize == nBlockXSize && nReqYSize == nBlockYSize) &&
243 : !bHasMemsetTile)
244 : {
245 10 : memset(pImage, 0, nBlockXSize * nBlockYSize * nDataTypeSize);
246 10 : bHasMemsetTile = TRUE;
247 10 : bHasJustMemsetTileBand1 = TRUE;
248 : }
249 :
250 : GDALColorTable* poTileCT =
251 32 : (GDALColorTable* )GDALGetRasterColorTable(GDALGetRasterBand(hDSTile, 1));
252 32 : unsigned char* pabyTranslationTable = NULL;
253 32 : if (poGDS->nBands == 1 && poGDS->poCT != NULL && poTileCT != NULL)
254 : {
255 : pabyTranslationTable =
256 : ((GDALRasterBand*)GDALGetRasterBand(hDSTile, 1))->
257 2 : GetIndexColorTranslationTo(this, NULL, NULL);
258 : }
259 :
260 : /* -------------------------------------------------------------------- */
261 : /* Read tile data */
262 : /* -------------------------------------------------------------------- */
263 : GDALRasterIO(GDALGetRasterBand(hDSTile, nReqBand), GF_Read,
264 : nSrcXOff, nSrcYOff, nReqXSize, nReqYSize,
265 : ((char*) pImage) + (nDstXOff + nDstYOff * nBlockXSize) * nDataTypeSize,
266 : nReqXSize, nReqYSize,
267 32 : eDataType, nDataTypeSize, nBlockXSize * nDataTypeSize);
268 :
269 32 : if (eDataType == GDT_Byte && pabyTranslationTable)
270 : {
271 : /* -------------------------------------------------------------------- */
272 : /* Convert from tile CT to band CT */
273 : /* -------------------------------------------------------------------- */
274 : int i, j;
275 0 : for(j=nDstYOff;j<nDstYOff + nReqYSize;j++)
276 : {
277 0 : for(i=nDstXOff;i<nDstXOff + nReqXSize;i++)
278 : {
279 0 : GByte* pPixel = ((GByte*) pImage) + i + j * nBlockXSize;
280 0 : *pPixel = pabyTranslationTable[*pPixel];
281 : }
282 : }
283 0 : CPLFree(pabyTranslationTable);
284 0 : pabyTranslationTable = NULL;
285 : }
286 32 : else if (eDataType == GDT_Byte && nTileBands == 1 &&
287 : poGDS->nBands == 3 && poTileCT != NULL)
288 : {
289 : /* -------------------------------------------------------------------- */
290 : /* Expand from PCT to RGB */
291 : /* -------------------------------------------------------------------- */
292 : int i, j;
293 : GByte abyCT[256];
294 2 : int nEntries = MIN(256, poTileCT->GetColorEntryCount());
295 514 : for(i=0;i<nEntries;i++)
296 : {
297 512 : const GDALColorEntry* psEntry = poTileCT->GetColorEntry(i);
298 512 : if (nBand == 1)
299 512 : abyCT[i] = (GByte)psEntry->c1;
300 0 : else if (nBand == 2)
301 0 : abyCT[i] = (GByte)psEntry->c2;
302 : else
303 0 : abyCT[i] = (GByte)psEntry->c3;
304 : }
305 2 : for(;i<256;i++)
306 0 : abyCT[i] = 0;
307 :
308 340 : for(j=nDstYOff;j<nDstYOff + nReqYSize;j++)
309 : {
310 114582 : for(i=nDstXOff;i<nDstXOff + nReqXSize;i++)
311 : {
312 114244 : GByte* pPixel = ((GByte*) pImage) + i + j * nBlockXSize;
313 114244 : *pPixel = abyCT[*pPixel];
314 : }
315 : }
316 : }
317 :
318 : /* -------------------------------------------------------------------- */
319 : /* Put in the block cache the data for this block into other bands */
320 : /* while the underlying dataset is opened */
321 : /* -------------------------------------------------------------------- */
322 32 : if (nBand == 1 && poGDS->nBands > 1)
323 : {
324 : int iOtherBand;
325 36 : for(iOtherBand=2;iOtherBand<=poGDS->nBands;iOtherBand++)
326 : {
327 : GDALRasterBlock *poBlock;
328 :
329 : poBlock = poGDS->GetRasterBand(iOtherBand)->
330 24 : GetLockedBlockRef(nBlockXOff,nBlockYOff, TRUE);
331 24 : if (poBlock == NULL)
332 0 : break;
333 :
334 24 : GByte* pabySrcBlock = (GByte *) poBlock->GetDataRef();
335 24 : if( pabySrcBlock == NULL )
336 : {
337 0 : poBlock->DropLock();
338 0 : break;
339 : }
340 :
341 24 : if (nTileBands == 1)
342 4 : nReqBand = 1;
343 : else
344 20 : nReqBand = iOtherBand;
345 :
346 24 : if (bHasJustMemsetTileBand1)
347 : memset(pabySrcBlock, 0,
348 4 : nBlockXSize * nBlockYSize * nDataTypeSize);
349 :
350 : /* -------------------------------------------------------------------- */
351 : /* Read tile data */
352 : /* -------------------------------------------------------------------- */
353 : GDALRasterIO(GDALGetRasterBand(hDSTile, nReqBand), GF_Read,
354 : nSrcXOff, nSrcYOff, nReqXSize, nReqYSize,
355 : ((char*) pabySrcBlock) +
356 : (nDstXOff + nDstYOff * nBlockXSize) * nDataTypeSize,
357 : nReqXSize, nReqYSize,
358 24 : eDataType, nDataTypeSize, nBlockXSize * nDataTypeSize);
359 :
360 24 : if (eDataType == GDT_Byte && nTileBands == 1 &&
361 : poGDS->nBands == 3 && poTileCT != NULL)
362 : {
363 : /* -------------------------------------------------------------------- */
364 : /* Expand from PCT to RGB */
365 : /* -------------------------------------------------------------------- */
366 :
367 : int i, j;
368 : GByte abyCT[256];
369 4 : int nEntries = MIN(256, poTileCT->GetColorEntryCount());
370 1028 : for(i=0;i<nEntries;i++)
371 : {
372 1024 : const GDALColorEntry* psEntry = poTileCT->GetColorEntry(i);
373 1024 : if (iOtherBand == 1)
374 0 : abyCT[i] = (GByte)psEntry->c1;
375 1024 : else if (iOtherBand == 2)
376 512 : abyCT[i] = (GByte)psEntry->c2;
377 : else
378 512 : abyCT[i] = (GByte)psEntry->c3;
379 : }
380 4 : for(;i<256;i++)
381 0 : abyCT[i] = 0;
382 :
383 680 : for(j=nDstYOff;j<nDstYOff + nReqYSize;j++)
384 : {
385 229164 : for(i=nDstXOff;i<nDstXOff + nReqXSize;i++)
386 : {
387 228488 : GByte* pPixel = ((GByte*) pabySrcBlock) + i + j * nBlockXSize;
388 228488 : *pPixel = abyCT[*pPixel];
389 : }
390 : }
391 : }
392 :
393 24 : poBlock->DropLock();
394 : }
395 :
396 : }
397 32 : GDALClose(hDSTile);
398 : }
399 :
400 32 : VSIUnlink(osMemFileName.c_str());
401 : }
402 : else
403 : {
404 : #ifdef RASTERLITE_DEBUG
405 : if (nBand == 1)
406 : {
407 : printf("id = %d, NOT selected !\n", nTileId);
408 : }
409 : #endif
410 : }
411 :
412 32 : OGR_F_Destroy(hFeat);
413 : }
414 :
415 32 : if (!bHasFoundTile)
416 : {
417 0 : memset(pImage, 0, nBlockXSize * nBlockYSize * nDataTypeSize);
418 : }
419 :
420 32 : OGR_DS_ReleaseResultSet(poGDS->hDS, hSQLLyr);
421 :
422 : #ifdef RASTERLITE_DEBUG
423 : if (nBand == 1)
424 : printf("\n");
425 : #endif
426 :
427 32 : return CE_None;
428 : }
429 :
430 : /************************************************************************/
431 : /* GetOverviewCount() */
432 : /************************************************************************/
433 :
434 14 : int RasterliteBand::GetOverviewCount()
435 : {
436 14 : RasterliteDataset* poGDS = (RasterliteDataset*) poDS;
437 :
438 14 : if (poGDS->nLimitOvrCount >= 0)
439 6 : return poGDS->nLimitOvrCount;
440 8 : else if (poGDS->nResolutions > 1)
441 2 : return poGDS->nResolutions - 1;
442 : else
443 6 : return GDALPamRasterBand::GetOverviewCount();
444 : }
445 :
446 : /************************************************************************/
447 : /* GetOverview() */
448 : /************************************************************************/
449 :
450 18 : GDALRasterBand* RasterliteBand::GetOverview(int nLevel)
451 : {
452 18 : RasterliteDataset* poGDS = (RasterliteDataset*) poDS;
453 :
454 18 : if (poGDS->nLimitOvrCount >= 0)
455 : {
456 4 : if (nLevel < 0 || nLevel >= poGDS->nLimitOvrCount)
457 0 : return NULL;
458 : }
459 :
460 18 : if (poGDS->nResolutions == 1)
461 0 : return GDALPamRasterBand::GetOverview(nLevel);
462 :
463 18 : if (nLevel < 0 || nLevel >= poGDS->nResolutions - 1)
464 0 : return NULL;
465 :
466 18 : GDALDataset* poOvrDS = poGDS->papoOverviews[nLevel];
467 18 : if (poOvrDS)
468 18 : return poOvrDS->GetRasterBand(nBand);
469 : else
470 0 : return NULL;
471 : }
472 :
473 : /************************************************************************/
474 : /* GetColorInterpretation() */
475 : /************************************************************************/
476 :
477 2 : GDALColorInterp RasterliteBand::GetColorInterpretation()
478 : {
479 2 : RasterliteDataset* poGDS = (RasterliteDataset*) poDS;
480 2 : if (poGDS->nBands == 1)
481 : {
482 2 : if (poGDS->poCT != NULL)
483 2 : return GCI_PaletteIndex;
484 : else
485 0 : return GCI_GrayIndex;
486 : }
487 0 : else if (poGDS->nBands == 3)
488 : {
489 0 : if (nBand == 1)
490 0 : return GCI_RedBand;
491 0 : else if (nBand == 2)
492 0 : return GCI_GreenBand;
493 0 : else if (nBand == 3)
494 0 : return GCI_BlueBand;
495 : }
496 :
497 0 : return GCI_Undefined;
498 : }
499 :
500 : /************************************************************************/
501 : /* GetColorTable() */
502 : /************************************************************************/
503 :
504 6 : GDALColorTable* RasterliteBand::GetColorTable()
505 : {
506 6 : RasterliteDataset* poGDS = (RasterliteDataset*) poDS;
507 6 : if (poGDS->nBands == 1)
508 4 : return poGDS->poCT;
509 : else
510 2 : return NULL;
511 : }
512 :
513 : /************************************************************************/
514 : /* RasterliteDataset() */
515 : /************************************************************************/
516 :
517 104 : RasterliteDataset::RasterliteDataset()
518 : {
519 104 : nLimitOvrCount = -1;
520 104 : bValidGeoTransform = FALSE;
521 104 : bMustFree = FALSE;
522 104 : nLevel = 0;
523 104 : poMainDS = NULL;
524 104 : nResolutions = 0;
525 104 : padfXResolutions = NULL;
526 104 : padfYResolutions = NULL;
527 104 : pszSRS = NULL;
528 104 : hDS = NULL;
529 104 : papoOverviews = NULL;
530 104 : papszMetadata = NULL;
531 104 : papszSubDatasets = NULL;
532 : papszImageStructure =
533 104 : CSLAddString(NULL, "INTERLEAVE=PIXEL");
534 104 : poCT = NULL;
535 104 : bCheckForExistingOverview = TRUE;
536 104 : }
537 :
538 : /************************************************************************/
539 : /* RasterliteDataset() */
540 : /************************************************************************/
541 :
542 16 : RasterliteDataset::RasterliteDataset(RasterliteDataset* poMainDS, int nLevel)
543 : {
544 16 : nLimitOvrCount = -1;
545 16 : bMustFree = FALSE;
546 16 : this->nLevel = nLevel;
547 16 : this->poMainDS = poMainDS;
548 16 : nResolutions = poMainDS->nResolutions - nLevel;
549 16 : padfXResolutions = poMainDS->padfXResolutions + nLevel;
550 16 : padfYResolutions = poMainDS->padfYResolutions + nLevel;
551 16 : pszSRS = poMainDS->pszSRS;
552 16 : hDS = poMainDS->hDS;
553 16 : papoOverviews = poMainDS->papoOverviews + nLevel;
554 16 : papszMetadata = poMainDS->papszMetadata;
555 16 : papszSubDatasets = poMainDS->papszSubDatasets;
556 16 : papszImageStructure = poMainDS->papszImageStructure;
557 16 : poCT = poMainDS->poCT;
558 16 : bCheckForExistingOverview = TRUE;
559 :
560 16 : osTableName = poMainDS->osTableName;
561 16 : osFileName = poMainDS->osFileName;
562 :
563 : nRasterXSize = (int)(poMainDS->nRasterXSize *
564 16 : (poMainDS->padfXResolutions[0] / padfXResolutions[0]) + 0.5);
565 : nRasterYSize = (int)(poMainDS->nRasterYSize *
566 16 : (poMainDS->padfYResolutions[0] / padfYResolutions[0]) + 0.5);
567 :
568 16 : bValidGeoTransform = TRUE;
569 16 : memcpy(adfGeoTransform, poMainDS->adfGeoTransform, 6 * sizeof(double));
570 16 : adfGeoTransform[1] = padfXResolutions[0];
571 16 : adfGeoTransform[5] = - padfYResolutions[0];
572 16 : }
573 :
574 : /************************************************************************/
575 : /* ~RasterliteDataset() */
576 : /************************************************************************/
577 :
578 120 : RasterliteDataset::~RasterliteDataset()
579 : {
580 120 : CloseDependentDatasets();
581 120 : }
582 :
583 : /************************************************************************/
584 : /* CloseDependentDatasets() */
585 : /************************************************************************/
586 :
587 120 : int RasterliteDataset::CloseDependentDatasets()
588 : {
589 120 : int bRet = GDALPamDataset::CloseDependentDatasets();
590 :
591 224 : if (poMainDS == NULL && !bMustFree)
592 : {
593 104 : CSLDestroy(papszMetadata);
594 104 : papszMetadata = NULL;
595 104 : CSLDestroy(papszSubDatasets);
596 104 : papszSubDatasets = NULL;
597 104 : CSLDestroy(papszImageStructure);
598 104 : papszImageStructure = NULL;
599 104 : CPLFree(pszSRS);
600 104 : pszSRS = NULL;
601 :
602 104 : if (papoOverviews)
603 : {
604 : int i;
605 16 : for(i=1;i<nResolutions;i++)
606 : {
607 20 : if (papoOverviews[i-1] != NULL &&
608 10 : papoOverviews[i-1]->bMustFree)
609 : {
610 0 : papoOverviews[i-1]->poMainDS = NULL;
611 : }
612 10 : delete papoOverviews[i-1];
613 : }
614 6 : CPLFree(papoOverviews);
615 6 : papoOverviews = NULL;
616 6 : nResolutions = 0;
617 6 : bRet = TRUE;
618 : }
619 :
620 104 : if (hDS != NULL)
621 54 : OGRReleaseDataSource(hDS);
622 104 : hDS = NULL;
623 :
624 104 : CPLFree(padfXResolutions);
625 104 : CPLFree(padfYResolutions);
626 104 : padfXResolutions = padfYResolutions = NULL;
627 :
628 104 : delete poCT;
629 104 : poCT = NULL;
630 : }
631 16 : else if (poMainDS != NULL && bMustFree)
632 : {
633 0 : poMainDS->papoOverviews[nLevel-1] = NULL;
634 0 : delete poMainDS;
635 0 : poMainDS = NULL;
636 0 : bRet = TRUE;
637 : }
638 :
639 120 : return bRet;
640 : }
641 :
642 : /************************************************************************/
643 : /* AddSubDataset() */
644 : /************************************************************************/
645 :
646 50 : void RasterliteDataset::AddSubDataset( const char* pszDSName)
647 : {
648 : char szName[80];
649 50 : int nCount = CSLCount(papszSubDatasets ) / 2;
650 :
651 50 : sprintf( szName, "SUBDATASET_%d_NAME", nCount+1 );
652 : papszSubDatasets =
653 50 : CSLSetNameValue( papszSubDatasets, szName, pszDSName);
654 :
655 50 : sprintf( szName, "SUBDATASET_%d_DESC", nCount+1 );
656 : papszSubDatasets =
657 50 : CSLSetNameValue( papszSubDatasets, szName, pszDSName);
658 50 : }
659 :
660 : /************************************************************************/
661 : /* GetMetadata() */
662 : /************************************************************************/
663 :
664 0 : char **RasterliteDataset::GetMetadata( const char *pszDomain )
665 :
666 : {
667 0 : if( pszDomain != NULL && EQUAL(pszDomain,"SUBDATASETS") )
668 0 : return papszSubDatasets;
669 :
670 0 : if( CSLCount(papszSubDatasets) < 2 &&
671 : pszDomain != NULL && EQUAL(pszDomain,"IMAGE_STRUCTURE") )
672 0 : return papszImageStructure;
673 :
674 0 : if ( pszDomain == NULL || EQUAL(pszDomain, "") )
675 0 : return papszMetadata;
676 :
677 0 : return GDALPamDataset::GetMetadata( pszDomain );
678 : }
679 :
680 : /************************************************************************/
681 : /* GetMetadataItem() */
682 : /************************************************************************/
683 :
684 4 : const char *RasterliteDataset::GetMetadataItem( const char *pszName,
685 : const char *pszDomain )
686 : {
687 4 : if (pszDomain != NULL &&EQUAL(pszDomain,"OVERVIEWS") )
688 : {
689 4 : if (nResolutions > 1 || CSLCount(papszSubDatasets) > 2)
690 0 : return NULL;
691 : else
692 : {
693 4 : osOvrFileName.Printf("%s_%s", osFileName.c_str(), osTableName.c_str());
694 4 : if (bCheckForExistingOverview == FALSE ||
695 : CPLCheckForFile((char*) osOvrFileName.c_str(), NULL))
696 0 : return osOvrFileName.c_str();
697 : else
698 4 : return NULL;
699 : }
700 : }
701 0 : return GDALPamDataset::GetMetadataItem(pszName, pszDomain);
702 : }
703 :
704 : /************************************************************************/
705 : /* GetGeoTransform() */
706 : /************************************************************************/
707 :
708 8 : CPLErr RasterliteDataset::GetGeoTransform( double* padfGeoTransform )
709 : {
710 8 : if (bValidGeoTransform)
711 : {
712 8 : memcpy(padfGeoTransform, adfGeoTransform, 6 * sizeof(double));
713 8 : return CE_None;
714 : }
715 : else
716 0 : return CE_Failure;
717 : }
718 :
719 : /************************************************************************/
720 : /* GetProjectionRef() */
721 : /************************************************************************/
722 :
723 8 : const char* RasterliteDataset::GetProjectionRef()
724 : {
725 8 : if (pszSRS)
726 8 : return pszSRS;
727 : else
728 0 : return "";
729 : }
730 :
731 : /************************************************************************/
732 : /* GetFileList() */
733 : /************************************************************************/
734 :
735 0 : char** RasterliteDataset::GetFileList()
736 : {
737 0 : char** papszFileList = NULL;
738 0 : papszFileList = CSLAddString(papszFileList, osFileName);
739 0 : return papszFileList;
740 : }
741 :
742 : /************************************************************************/
743 : /* GetBlockParams() */
744 : /************************************************************************/
745 :
746 70 : int RasterliteDataset::GetBlockParams(OGRLayerH hRasterLyr, int nLevel,
747 : int* pnBands, GDALDataType* peDataType,
748 : int* pnBlockXSize, int* pnBlockYSize)
749 : {
750 70 : CPLString osSQL;
751 :
752 : osSQL.Printf("SELECT m.geometry, r.raster, m.id "
753 : "FROM \"%s_metadata\" AS m, \"%s_rasters\" AS r "
754 : "WHERE m.pixel_x_size >= %.15f AND m.pixel_x_size <= %.15f AND "
755 : "m.pixel_y_size >= %.15f AND m.pixel_y_size <= %.15f AND r.id = m.id",
756 : osTableName.c_str(), osTableName.c_str(),
757 140 : padfXResolutions[nLevel] - 1e-15, padfXResolutions[nLevel] + 1e-15,
758 210 : padfYResolutions[nLevel] - 1e-15, padfYResolutions[nLevel] + 1e-15);
759 :
760 70 : OGRLayerH hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
761 70 : if (hSQLLyr == NULL)
762 : {
763 0 : return FALSE;
764 : }
765 :
766 70 : OGRFeatureH hFeat = OGR_L_GetNextFeature(hRasterLyr);
767 70 : if (hFeat == NULL)
768 : {
769 0 : OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
770 0 : return FALSE;
771 : }
772 :
773 : int nDataSize;
774 70 : GByte* pabyData = OGR_F_GetFieldAsBinary(hFeat, 0, &nDataSize);
775 :
776 70 : if (nDataSize > 32 &&
777 : EQUALN((const char*)pabyData, "StartWaveletsImage$$", strlen("StartWaveletsImage$$")))
778 : {
779 8 : if (GDALGetDriverByName("EPSILON") == NULL)
780 : {
781 : CPLError(CE_Failure, CPLE_NotSupported,
782 0 : "Rasterlite driver doesn't support WAVELET compressed images if EPSILON driver is not compiled");
783 0 : OGR_F_Destroy(hFeat);
784 0 : OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
785 0 : return FALSE;
786 : }
787 : }
788 :
789 70 : CPLString osMemFileName;
790 70 : osMemFileName.Printf("/vsimem/%p", this);
791 : VSILFILE * fp = VSIFileFromMemBuffer( osMemFileName.c_str(), pabyData,
792 70 : nDataSize, FALSE);
793 70 : VSIFCloseL(fp);
794 :
795 70 : GDALDatasetH hDSTile = GDALOpen(osMemFileName.c_str(), GA_ReadOnly);
796 70 : if (hDSTile)
797 : {
798 70 : *pnBands = GDALGetRasterCount(hDSTile);
799 70 : if (*pnBands == 0)
800 : {
801 0 : GDALClose(hDSTile);
802 0 : hDSTile = NULL;
803 : }
804 : }
805 : else
806 : {
807 : CPLError(CE_Failure, CPLE_AppDefined, "Can't open tile %d",
808 0 : OGR_F_GetFieldAsInteger(hFeat, 1));
809 : }
810 :
811 70 : if (hDSTile)
812 : {
813 : int iBand;
814 70 : *peDataType = GDALGetRasterDataType(GDALGetRasterBand(hDSTile, 1));
815 :
816 110 : for(iBand=2;iBand<=*pnBands;iBand++)
817 : {
818 40 : if (*peDataType != GDALGetRasterDataType(GDALGetRasterBand(hDSTile, 1)))
819 : {
820 0 : CPLError(CE_Failure, CPLE_NotSupported, "Band types must be identical");
821 0 : GDALClose(hDSTile);
822 0 : hDSTile = NULL;
823 0 : goto end;
824 : }
825 : }
826 :
827 70 : *pnBlockXSize = GDALGetRasterXSize(hDSTile);
828 70 : *pnBlockYSize = GDALGetRasterYSize(hDSTile);
829 70 : if (CSLFindName(papszImageStructure, "COMPRESSION") == -1)
830 : {
831 : const char* pszCompression =
832 68 : GDALGetMetadataItem(hDSTile, "COMPRESSION", "IMAGE_STRUCTURE");
833 68 : if (pszCompression != NULL && EQUAL(pszCompression, "JPEG"))
834 : papszImageStructure =
835 4 : CSLAddString(papszImageStructure, "COMPRESSION=JPEG");
836 : }
837 :
838 70 : if (CSLFindName(papszMetadata, "TILE_FORMAT") == -1)
839 : {
840 : papszMetadata =
841 : CSLSetNameValue(papszMetadata, "TILE_FORMAT",
842 54 : GDALGetDriverShortName(GDALGetDatasetDriver(hDSTile)));
843 : }
844 :
845 :
846 70 : if (*pnBands == 1 && this->poCT == NULL)
847 : {
848 : GDALColorTable* poCT =
849 52 : (GDALColorTable*)GDALGetRasterColorTable(GDALGetRasterBand(hDSTile, 1));
850 52 : if (poCT)
851 4 : this->poCT = poCT->Clone();
852 : }
853 :
854 70 : GDALClose(hDSTile);
855 : }
856 : end:
857 70 : VSIUnlink(osMemFileName.c_str());
858 :
859 70 : OGR_F_Destroy(hFeat);
860 :
861 70 : OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
862 :
863 70 : return hDSTile != NULL;
864 : }
865 :
866 : /************************************************************************/
867 : /* Identify() */
868 : /************************************************************************/
869 :
870 22186 : int RasterliteDataset::Identify(GDALOpenInfo* poOpenInfo)
871 : {
872 22186 : if (!EQUAL(CPLGetExtension(poOpenInfo->pszFilename), "MBTILES") &&
873 : poOpenInfo->nHeaderBytes >= 1024 &&
874 : EQUALN((const char*)poOpenInfo->pabyHeader, "SQLite Format 3", 15))
875 : {
876 46 : return TRUE;
877 : }
878 22140 : else if (EQUALN(poOpenInfo->pszFilename, "RASTERLITE:", 11))
879 : {
880 10 : return TRUE;
881 : }
882 :
883 22130 : return FALSE;
884 : }
885 :
886 : /************************************************************************/
887 : /* Open() */
888 : /************************************************************************/
889 :
890 3278 : GDALDataset* RasterliteDataset::Open(GDALOpenInfo* poOpenInfo)
891 : {
892 3278 : CPLString osFileName;
893 3278 : CPLString osTableName;
894 3278 : char **papszTokens = NULL;
895 3278 : int nLevel = 0;
896 3278 : double minx = 0, miny = 0, maxx = 0, maxy = 0;
897 3278 : int bMinXSet = FALSE, bMinYSet = FALSE, bMaxXSet = FALSE, bMaxYSet = FALSE;
898 3278 : int nReqBands = 0;
899 :
900 3278 : if (!Identify(poOpenInfo))
901 3224 : return NULL;
902 :
903 : /* -------------------------------------------------------------------- */
904 : /* Parse "file name" */
905 : /* -------------------------------------------------------------------- */
906 100 : if (poOpenInfo->nHeaderBytes >= 1024 &&
907 : EQUALN((const char*)poOpenInfo->pabyHeader, "SQLite Format 3", 15))
908 : {
909 46 : osFileName = poOpenInfo->pszFilename;
910 : }
911 : else
912 : {
913 : papszTokens = CSLTokenizeStringComplex(
914 8 : poOpenInfo->pszFilename + 11, ", ", FALSE, FALSE );
915 8 : int nTokens = CSLCount(papszTokens);
916 8 : if (nTokens == 0)
917 : {
918 0 : CSLDestroy(papszTokens);
919 0 : return NULL;
920 : }
921 :
922 8 : osFileName = papszTokens[0];
923 :
924 : int i;
925 22 : for(i=1;i<nTokens;i++)
926 : {
927 14 : if (EQUALN(papszTokens[i], "table=", 6))
928 4 : osTableName = papszTokens[i] + 6;
929 10 : else if (EQUALN(papszTokens[i], "level=", 6))
930 0 : nLevel = atoi(papszTokens[i] + 6);
931 10 : else if (EQUALN(papszTokens[i], "minx=", 5))
932 : {
933 2 : bMinXSet = TRUE;
934 2 : minx = atof(papszTokens[i] + 5);
935 : }
936 8 : else if (EQUALN(papszTokens[i], "miny=", 5))
937 : {
938 2 : bMinYSet = TRUE;
939 2 : miny = atof(papszTokens[i] + 5);
940 : }
941 6 : else if (EQUALN(papszTokens[i], "maxx=", 5))
942 : {
943 2 : bMaxXSet = TRUE;
944 2 : maxx = atof(papszTokens[i] + 5);
945 : }
946 4 : else if (EQUALN(papszTokens[i], "maxy=", 5))
947 : {
948 2 : bMaxYSet = TRUE;
949 2 : maxy = atof(papszTokens[i] + 5);
950 : }
951 2 : else if (EQUALN(papszTokens[i], "bands=", 6))
952 : {
953 2 : nReqBands = atoi(papszTokens[i] + 6);
954 : }
955 : else
956 : {
957 : CPLError(CE_Warning, CPLE_AppDefined,
958 0 : "Invalid option : %s", papszTokens[i]);
959 : }
960 : }
961 : }
962 :
963 54 : if (OGRGetDriverCount() == 0)
964 0 : OGRRegisterAll();
965 :
966 : /* -------------------------------------------------------------------- */
967 : /* Open underlying OGR DB */
968 : /* -------------------------------------------------------------------- */
969 :
970 : /* Set SQLITE_LIST_ALL_TABLES option as we wan't to be able to */
971 : /* fetch non spatial tables */
972 54 : CPLString osOldVal = CPLGetConfigOption("SQLITE_LIST_ALL_TABLES", "FALSE");
973 54 : CPLSetThreadLocalConfigOption("SQLITE_LIST_ALL_TABLES", "TRUE");
974 54 : OGRDataSourceH hDS = OGROpen(osFileName.c_str(), (poOpenInfo->eAccess == GA_Update) ? TRUE : FALSE, NULL);
975 54 : CPLSetThreadLocalConfigOption("SQLITE_LIST_ALL_TABLES", osOldVal.c_str());
976 54 : CPLDebug("RASTERLITE", "SQLite DB Open");
977 :
978 54 : RasterliteDataset* poDS = NULL;
979 :
980 54 : if (hDS == NULL)
981 0 : goto end;
982 :
983 54 : if (strlen(osTableName) == 0)
984 : {
985 50 : int nCountSubdataset = 0;
986 50 : int nLayers = OGR_DS_GetLayerCount(hDS);
987 : int i;
988 : /* -------------------------------------------------------------------- */
989 : /* Add raster layers as subdatasets */
990 : /* -------------------------------------------------------------------- */
991 774 : for(i=0;i<nLayers;i++)
992 : {
993 724 : OGRLayerH hLyr = OGR_DS_GetLayer(hDS, i);
994 724 : const char* pszLayerName = OGR_FD_GetName(OGR_L_GetLayerDefn(hLyr));
995 724 : if (strstr(pszLayerName, "_rasters"))
996 : {
997 50 : char* pszShortName = CPLStrdup(pszLayerName);
998 50 : *strstr(pszShortName, "_rasters") = '\0';
999 :
1000 50 : CPLString osMetadataTableName = pszShortName;
1001 50 : osMetadataTableName += "_metadata";
1002 :
1003 50 : if (OGR_DS_GetLayerByName(hDS, osMetadataTableName.c_str()) != NULL)
1004 : {
1005 50 : if (poDS == NULL)
1006 : {
1007 50 : poDS = new RasterliteDataset();
1008 100 : osTableName = pszShortName;
1009 : }
1010 :
1011 50 : CPLString osSubdatasetName;
1012 50 : if (!EQUALN(poOpenInfo->pszFilename, "RASTERLITE:", 11))
1013 46 : osSubdatasetName += "RASTERLITE:";
1014 50 : osSubdatasetName += poOpenInfo->pszFilename;
1015 50 : osSubdatasetName += ",table=";
1016 50 : osSubdatasetName += pszShortName;
1017 50 : poDS->AddSubDataset(osSubdatasetName.c_str());
1018 :
1019 50 : nCountSubdataset++;
1020 : }
1021 :
1022 50 : CPLFree(pszShortName);
1023 : }
1024 : }
1025 :
1026 50 : if (nCountSubdataset == 0)
1027 : {
1028 0 : goto end;
1029 : }
1030 50 : else if (nCountSubdataset != 1)
1031 : {
1032 0 : poDS->SetDescription( poOpenInfo->pszFilename );
1033 0 : goto end;
1034 : }
1035 :
1036 : /* -------------------------------------------------------------------- */
1037 : /* If just one subdataset, then open it */
1038 : /* -------------------------------------------------------------------- */
1039 50 : delete poDS;
1040 50 : poDS = NULL;
1041 : }
1042 :
1043 : /* -------------------------------------------------------------------- */
1044 : /* Build dataset */
1045 : /* -------------------------------------------------------------------- */
1046 : {
1047 54 : CPLString osMetadataTableName, osRasterTableName;
1048 54 : CPLString osSQL;
1049 : OGRLayerH hMetadataLyr, hRasterLyr, hRasterPyramidsLyr;
1050 : OGRLayerH hSQLLyr;
1051 : OGRFeatureH hFeat;
1052 : int i, nResolutions;
1053 : int iBand, nBands, nBlockXSize, nBlockYSize;
1054 : GDALDataType eDataType;
1055 :
1056 54 : osMetadataTableName = osTableName;
1057 54 : osMetadataTableName += "_metadata";
1058 :
1059 54 : hMetadataLyr = OGR_DS_GetLayerByName(hDS, osMetadataTableName.c_str());
1060 54 : if (hMetadataLyr == NULL)
1061 : goto end;
1062 :
1063 54 : osRasterTableName = osTableName;
1064 54 : osRasterTableName += "_rasters";
1065 :
1066 54 : hRasterLyr = OGR_DS_GetLayerByName(hDS, osRasterTableName.c_str());
1067 54 : if (hRasterLyr == NULL)
1068 : goto end;
1069 :
1070 : /* -------------------------------------------------------------------- */
1071 : /* Fetch resolutions */
1072 : /* -------------------------------------------------------------------- */
1073 :
1074 54 : hRasterPyramidsLyr = OGR_DS_GetLayerByName(hDS, "raster_pyramids");
1075 54 : if (hRasterPyramidsLyr)
1076 : {
1077 : osSQL.Printf("SELECT pixel_x_size, pixel_y_size "
1078 : "FROM raster_pyramids WHERE table_prefix = '%s' "
1079 : "ORDER BY pixel_x_size ASC",
1080 6 : osTableName.c_str());
1081 : }
1082 : else
1083 : {
1084 : osSQL.Printf("SELECT DISTINCT(pixel_x_size), pixel_y_size "
1085 : "FROM \"%s_metadata\" WHERE pixel_x_size != 0 "
1086 : "ORDER BY pixel_x_size ASC",
1087 48 : osTableName.c_str());
1088 : }
1089 :
1090 54 : hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
1091 54 : if (hSQLLyr == NULL)
1092 : {
1093 0 : if (hRasterPyramidsLyr == NULL)
1094 : goto end;
1095 :
1096 : osSQL.Printf("SELECT DISTINCT(pixel_x_size), pixel_y_size "
1097 : "FROM \"%s_metadata\" WHERE pixel_x_size != 0 "
1098 : "ORDER BY pixel_x_size ASC",
1099 0 : osTableName.c_str());
1100 :
1101 0 : hSQLLyr = OGR_DS_ExecuteSQL(hDS, osSQL.c_str(), NULL, NULL);
1102 0 : if (hSQLLyr == NULL)
1103 : goto end;
1104 : }
1105 :
1106 54 : nResolutions = OGR_L_GetFeatureCount(hSQLLyr, TRUE);
1107 :
1108 54 : if (nResolutions == 0)
1109 : {
1110 0 : OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
1111 : goto end;
1112 : }
1113 :
1114 : /* -------------------------------------------------------------------- */
1115 : /* Set dataset attributes */
1116 : /* -------------------------------------------------------------------- */
1117 :
1118 54 : poDS = new RasterliteDataset();
1119 54 : poDS->SetDescription( poOpenInfo->pszFilename );
1120 54 : poDS->eAccess = poOpenInfo->eAccess;
1121 54 : poDS->osTableName = osTableName;
1122 54 : poDS->osFileName = osFileName;
1123 54 : poDS->hDS = hDS;
1124 :
1125 : /* poDS will release it from now */
1126 54 : hDS = NULL;
1127 :
1128 : /* -------------------------------------------------------------------- */
1129 : /* Fetch spatial extent or use the one provided by the user */
1130 : /* -------------------------------------------------------------------- */
1131 54 : OGREnvelope oEnvelope;
1132 56 : if (bMinXSet && bMinYSet && bMaxXSet && bMaxYSet)
1133 : {
1134 2 : oEnvelope.MinX = minx;
1135 2 : oEnvelope.MinY = miny;
1136 2 : oEnvelope.MaxX = maxx;
1137 2 : oEnvelope.MaxY = maxy;
1138 : }
1139 : else
1140 : {
1141 52 : CPLString osOldVal = CPLGetConfigOption("OGR_SQLITE_EXACT_EXTENT", "NO");
1142 52 : CPLSetThreadLocalConfigOption("OGR_SQLITE_EXACT_EXTENT", "YES");
1143 52 : OGR_L_GetExtent(hMetadataLyr, &oEnvelope, TRUE);
1144 52 : CPLSetThreadLocalConfigOption("OGR_SQLITE_EXACT_EXTENT", osOldVal.c_str());
1145 : //printf("minx=%.15f miny=%.15f maxx=%.15f maxy=%.15f\n",
1146 : // oEnvelope.MinX, oEnvelope.MinY, oEnvelope.MaxX, oEnvelope.MaxY);
1147 : }
1148 :
1149 : /* -------------------------------------------------------------------- */
1150 : /* Store resolutions */
1151 : /* -------------------------------------------------------------------- */
1152 54 : poDS->nResolutions = nResolutions;
1153 : poDS->padfXResolutions =
1154 54 : (double*)CPLMalloc(sizeof(double) * poDS->nResolutions);
1155 : poDS->padfYResolutions =
1156 54 : (double*)CPLMalloc(sizeof(double) * poDS->nResolutions);
1157 :
1158 54 : i = 0;
1159 172 : while((hFeat = OGR_L_GetNextFeature(hSQLLyr)) != NULL)
1160 : {
1161 64 : poDS->padfXResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 0);
1162 64 : poDS->padfYResolutions[i] = OGR_F_GetFieldAsDouble(hFeat, 1);
1163 :
1164 64 : OGR_F_Destroy(hFeat);
1165 :
1166 : //printf("[%d] xres=%.15f yres=%.15f\n", i,
1167 : // poDS->padfXResolutions[i], poDS->padfYResolutions[i]);
1168 :
1169 64 : if (poDS->padfXResolutions[i] <= 0 || poDS->padfXResolutions[i] <= 0)
1170 : {
1171 : CPLError(CE_Failure, CPLE_NotSupported,
1172 : "res=%d, xres=%.15f, yres=%.15f",
1173 0 : i, poDS->padfXResolutions[i], poDS->padfYResolutions[i]);
1174 0 : OGR_DS_ReleaseResultSet(hDS, hSQLLyr);
1175 0 : delete poDS;
1176 0 : poDS = NULL;
1177 : goto end;
1178 : }
1179 64 : i ++;
1180 : }
1181 :
1182 54 : OGR_DS_ReleaseResultSet(poDS->hDS, hSQLLyr);
1183 54 : hSQLLyr = NULL;
1184 :
1185 : /* -------------------------------------------------------------------- */
1186 : /* Compute raster size, geotransform and projection */
1187 : /* -------------------------------------------------------------------- */
1188 : poDS->nRasterXSize =
1189 54 : (int)((oEnvelope.MaxX - oEnvelope.MinX) / poDS->padfXResolutions[0] + 0.5);
1190 : poDS->nRasterYSize =
1191 54 : (int)((oEnvelope.MaxY - oEnvelope.MinY) / poDS->padfYResolutions[0] + 0.5);
1192 :
1193 54 : poDS->bValidGeoTransform = TRUE;
1194 54 : poDS->adfGeoTransform[0] = oEnvelope.MinX;
1195 54 : poDS->adfGeoTransform[1] = poDS->padfXResolutions[0];
1196 54 : poDS->adfGeoTransform[2] = 0;
1197 54 : poDS->adfGeoTransform[3] = oEnvelope.MaxY;
1198 54 : poDS->adfGeoTransform[4] = 0;
1199 54 : poDS->adfGeoTransform[5] = - poDS->padfYResolutions[0];
1200 :
1201 54 : OGRSpatialReferenceH hSRS = OGR_L_GetSpatialRef(hMetadataLyr);
1202 54 : if (hSRS)
1203 : {
1204 54 : OSRExportToWkt(hSRS, &poDS->pszSRS);
1205 : }
1206 :
1207 : /* -------------------------------------------------------------------- */
1208 : /* Get number of bands and block size */
1209 : /* -------------------------------------------------------------------- */
1210 :
1211 54 : if (poDS->GetBlockParams(hRasterLyr, 0, &nBands, &eDataType,
1212 : &nBlockXSize, &nBlockYSize) == FALSE)
1213 : {
1214 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot find block characteristics");
1215 0 : delete poDS;
1216 0 : poDS = NULL;
1217 : goto end;
1218 : }
1219 :
1220 56 : if (eDataType == GDT_Byte && nBands == 1 && nReqBands == 3)
1221 2 : nBands = 3;
1222 52 : else if (nReqBands != 0)
1223 : {
1224 : CPLError(CE_Warning, CPLE_NotSupported,
1225 0 : "Parameters bands=%d ignored", nReqBands);
1226 : }
1227 :
1228 : /* -------------------------------------------------------------------- */
1229 : /* Add bands */
1230 : /* -------------------------------------------------------------------- */
1231 :
1232 148 : for(iBand=0;iBand<nBands;iBand++)
1233 : poDS->SetBand(iBand+1, new RasterliteBand(poDS, iBand+1, eDataType,
1234 94 : nBlockXSize, nBlockYSize));
1235 :
1236 : /* -------------------------------------------------------------------- */
1237 : /* Add overview levels as internal datasets */
1238 : /* -------------------------------------------------------------------- */
1239 54 : if (nResolutions > 1)
1240 : {
1241 : poDS->papoOverviews = (RasterliteDataset**)
1242 6 : CPLCalloc(nResolutions - 1, sizeof(RasterliteDataset*));
1243 : int nLev;
1244 16 : for(nLev=1;nLev<nResolutions;nLev++)
1245 : {
1246 : int nOvrBands;
1247 : GDALDataType eOvrDataType;
1248 10 : if (poDS->GetBlockParams(hRasterLyr, nLev, &nOvrBands, &eOvrDataType,
1249 : &nBlockXSize, &nBlockYSize) == FALSE)
1250 : {
1251 : CPLError(CE_Failure, CPLE_AppDefined,
1252 0 : "Cannot find block characteristics for overview %d", nLev);
1253 0 : delete poDS;
1254 0 : poDS = NULL;
1255 : goto end;
1256 : }
1257 :
1258 10 : if (eDataType == GDT_Byte && nOvrBands == 1 && nReqBands == 3)
1259 0 : nOvrBands = 3;
1260 :
1261 10 : if (nBands != nOvrBands || eDataType != eOvrDataType)
1262 : {
1263 : CPLError(CE_Failure, CPLE_AppDefined,
1264 0 : "Overview %d has not the same number characteristics as main band", nLev);
1265 0 : delete poDS;
1266 0 : poDS = NULL;
1267 : goto end;
1268 : }
1269 :
1270 10 : poDS->papoOverviews[nLev-1] = new RasterliteDataset(poDS, nLev);
1271 :
1272 24 : for(iBand=0;iBand<nBands;iBand++)
1273 : {
1274 14 : poDS->papoOverviews[nLev-1]->SetBand(iBand+1,
1275 : new RasterliteBand(poDS->papoOverviews[nLev-1], iBand+1, eDataType,
1276 28 : nBlockXSize, nBlockYSize));
1277 : }
1278 : }
1279 : }
1280 :
1281 : /* -------------------------------------------------------------------- */
1282 : /* Select an overview if the user has requested so */
1283 : /* -------------------------------------------------------------------- */
1284 54 : if (nLevel == 0)
1285 : {
1286 : }
1287 0 : else if (nLevel >= 1 && nLevel <= nResolutions - 1)
1288 : {
1289 0 : poDS->papoOverviews[nLevel-1]->bMustFree = TRUE;
1290 0 : poDS = poDS->papoOverviews[nLevel-1];
1291 : }
1292 : else
1293 : {
1294 : CPLError(CE_Failure, CPLE_AppDefined,
1295 : "Invalid requested level : %d. Must be >= 0 and <= %d",
1296 0 : nLevel, nResolutions - 1);
1297 0 : delete poDS;
1298 0 : poDS = NULL;
1299 0 : }
1300 :
1301 : }
1302 :
1303 54 : if (poDS)
1304 : {
1305 : /* -------------------------------------------------------------------- */
1306 : /* Setup PAM info for this subdatasets */
1307 : /* -------------------------------------------------------------------- */
1308 54 : poDS->SetPhysicalFilename( osFileName.c_str() );
1309 :
1310 54 : CPLString osSubdatasetName;
1311 : osSubdatasetName.Printf("RASTERLITE:%s:table=%s",
1312 54 : osFileName.c_str(), osTableName.c_str());
1313 54 : poDS->SetSubdatasetName( osSubdatasetName.c_str() );
1314 54 : poDS->TryLoadXML();
1315 54 : poDS->oOvManager.Initialize( poDS, ":::VIRTUAL:::" );
1316 : }
1317 :
1318 :
1319 : end:
1320 54 : if (hDS)
1321 0 : OGRReleaseDataSource(hDS);
1322 54 : CSLDestroy(papszTokens);
1323 :
1324 54 : return poDS;
1325 : }
1326 :
1327 : /************************************************************************/
1328 : /* GDALRegister_Rasterlite() */
1329 : /************************************************************************/
1330 :
1331 1135 : void GDALRegister_Rasterlite()
1332 :
1333 : {
1334 : GDALDriver *poDriver;
1335 :
1336 1135 : if (! GDAL_CHECK_VERSION("Rasterlite driver"))
1337 0 : return;
1338 :
1339 1135 : if( GDALGetDriverByName( "Rasterlite" ) == NULL )
1340 : {
1341 1093 : poDriver = new GDALDriver();
1342 :
1343 1093 : poDriver->SetDescription( "Rasterlite" );
1344 : poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
1345 1093 : "Rasterlite" );
1346 : poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
1347 1093 : "frmt_rasterlite.html" );
1348 1093 : poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "sqlite" );
1349 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES,
1350 : "Byte UInt16 Int16 UInt32 Int32 Float32 "
1351 1093 : "Float64 CInt16 CInt32 CFloat32 CFloat64" );
1352 : poDriver->SetMetadataItem( GDAL_DMD_CREATIONOPTIONLIST,
1353 : "<CreationOptionList>"
1354 : " <Option name='WIPE' type='boolean' default='NO' description='Erase all prexisting data in the specified table'/>"
1355 : " <Option name='TILED' type='boolean' default='YES' description='Use tiling'/>"
1356 : " <Option name='BLOCKXSIZE' type='int' default='256' description='Tile Width'/>"
1357 : " <Option name='BLOCKYSIZE' type='int' default='256' description='Tile Height'/>"
1358 : " <Option name='DRIVER' type='string' default='GTiff' description='GDAL driver to use for storing tiles' default='GTiff'/>"
1359 : " <Option name='COMPRESS' type='string' default='(GTiff driver) Compression method' default='NONE'/>"
1360 : " <Option name='QUALITY' type='int' description='(JPEG-compressed GTiff, JPEG and WEBP drivers) JPEG/WEBP Quality 1-100' default='75'/>"
1361 : " <Option name='PHOTOMETRIC' type='string-select' description='(GTiff driver) Photometric interpretation'>"
1362 : " <Value>MINISBLACK</Value>"
1363 : " <Value>MINISWHITE</Value>"
1364 : " <Value>PALETTE</Value>"
1365 : " <Value>RGB</Value>"
1366 : " <Value>CMYK</Value>"
1367 : " <Value>YCBCR</Value>"
1368 : " <Value>CIELAB</Value>"
1369 : " <Value>ICCLAB</Value>"
1370 : " <Value>ITULAB</Value>"
1371 : " </Option>"
1372 : " <Option name='TARGET' type='int' description='(EPSILON driver) target size reduction as a percentage of the original (0-100)' default='96'/>"
1373 : " <Option name='FILTER' type='string' description='(EPSILON driver) Filter ID' default='daub97lift'/>"
1374 1093 : "</CreationOptionList>" );
1375 :
1376 1093 : poDriver->pfnOpen = RasterliteDataset::Open;
1377 1093 : poDriver->pfnIdentify = RasterliteDataset::Identify;
1378 1093 : poDriver->pfnCreateCopy = RasterliteCreateCopy;
1379 1093 : poDriver->pfnDelete = RasterliteDelete;
1380 :
1381 1093 : GetGDALDriverManager()->RegisterDriver( poDriver );
1382 : }
1383 : }
|