LCOV - code coverage report
Current view: directory - frmts/rasterlite - rasterlitedataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 579 463 80.0 %
Date: 2012-04-28 Functions: 25 18 72.0 %

       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                 : }

Generated by: LCOV version 1.7