LCOV - code coverage report
Current view: directory - frmts/wktraster - wktrasterrasterband.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 305 0 0.0 %
Date: 2010-01-09 Functions: 11 0 0.0 %

       1                 : 
       2                 : #include <string>
       3                 : 
       4                 : 
       5                 : #include "cpl_string.h"
       6                 : 
       7                 : /******************************************************************************
       8                 :  * File :    wktrasterrasterband.cpp
       9                 :  * Project:  WKT Raster driver
      10                 :  * Purpose:  GDAL Dataset code for WKTRaster driver 
      11                 :  * Author:   Jorge Arevalo, jorgearevalo@gis4free.org
      12                 :  * 
      13                 :  * Last changes:
      14                 :  * $Id: wktrasterrasterband.cpp 18029 2009-11-15 01:54:19Z jorgearevalo $
      15                 :  *
      16                 :  * TODO:
      17                 :  *  - Block caching, to avoid fetching the whole raster from database each time
      18                 :  *    IReadBlock is called.
      19                 :  *  - Read outdb rasters. Take into account that the outdb raster may don't have
      20                 :  *    the same block structure...
      21                 :  *  - Update raster_columns table if values read from IReadBlock are different
      22                 :  *
      23                 :  ******************************************************************************
      24                 :  * Copyright (c) 2009, Jorge Arevalo, jorgearevalo@gis4free.org
      25                 :  *
      26                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      27                 :  * copy of this software and associated documentation files (the "Software"),
      28                 :  * to deal in the Software without restriction, including without limitation
      29                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      30                 :  * and/or sell copies of the Software, and to permit persons to whom the
      31                 :  * Software is furnished to do so, subject to the following conditions:
      32                 :  *
      33                 :  * The above copyright notice and this permission notice shall be included
      34                 :  * in all copies or substantial portions of the Software.
      35                 :  *
      36                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      37                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      38                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      39                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      40                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      41                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      42                 :  * DEALINGS IN THE SOFTWARE.
      43                 :  ******************************************************************************/
      44                 : #include "wktraster.h"
      45                 : #include "ogr_api.h"
      46                 : #include "ogr_geometry.h"
      47                 : #include <gdal_priv.h>
      48                 : 
      49                 : CPL_CVSID("$Id: wktrasterrasterband.cpp 18029 2009-11-15 01:54:19Z jorgearevalo $");
      50                 : 
      51                 : /**
      52                 :  * Constructor.
      53                 :  * Parameters:
      54                 :  *  - WKTRasterDataset *: The Dataset this band belongs to
      55                 :  *  - int: the band number
      56                 :  *  - GDALDataType: The data type for this band
      57                 :  *  - double: The nodata value.  Could be any kind of data (GByte, GUInt16,
      58                 :  *          GInt32...) but the variable has the bigger type.
      59                 :  *  - GBool: if the data type is signed byte or not. If yes, the SIGNEDBYTE
      60                 :  *          metadata value is added to IMAGE_STRUCTURE domain
      61                 :  *  - int: The bit depth, to add NBITS as metadata value in IMAGE_STRUCTURE
      62                 :  *          domain.
      63                 :  */
      64               0 : WKTRasterRasterBand::WKTRasterRasterBand(WKTRasterDataset *poDS,
      65                 :         int nBand, GDALDataType hDataType, double dfNodata, GBool bSignedByte,
      66               0 :         int nBitD) {
      67                 :     
      68               0 :     VALIDATE_POINTER0(poDS, "WKTRasterRasterBand");
      69                 : 
      70               0 :     poDS = poDS;
      71               0 :     nBand = nBand;
      72                 : 
      73               0 :     nRasterXSize = poDS->GetRasterXSize();
      74               0 :     nRasterYSize = poDS->GetRasterYSize();
      75                 : 
      76               0 :     nBlockXSize = ((WKTRasterDataset *) poDS)->nBlockSizeX;
      77               0 :     nBlockYSize = ((WKTRasterDataset *) poDS)->nBlockSizeY;
      78                 : 
      79                 :      // Check Irregular blocking
      80               0 :     if (nBlockXSize == 0 || nBlockYSize == 0) {
      81                 :         CPLError(CE_Warning, CPLE_NotSupported,
      82               0 :                 "This band has irregular blocking, but is not supported yet");
      83                 :     }
      84                 : 
      85                 : 
      86               0 :     eAccess = ((WKTRasterDataset *) poDS)->GetAccess();
      87                 : 
      88                 :     // Get no data value and pixel type from dataset too
      89               0 :     eDataType = hDataType;
      90               0 :     dfNoDataValue = dfNodata;
      91                 : 
      92               0 :     nBitDepth = nBitD;
      93                 : 
      94                 :     // Add pixeltype to image structure domain
      95               0 :     if (bSignedByte == TRUE) {
      96               0 :         SetMetadataItem("PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" );
      97               0 :         bIsSignedByte = bSignedByte;
      98                 :     }
      99                 : 
     100                 :     // Add NBITS to metadata only for sub-byte types
     101               0 :     if (nBitDepth < 8)
     102                 :         SetMetadataItem("NBITS", CPLString().Printf( "%d", nBitDepth ),
     103               0 :             "IMAGE_STRUCTURE" );
     104               0 : }
     105                 : 
     106                 : /**
     107                 :  * Says if the datatype for this band is signedbyte.
     108                 :  * Parameters: none
     109                 :  * Returns:
     110                 :  *  - TRUE if the datatype for this band is signedbyte, FALSE otherwise
     111                 :  */
     112               0 :  GBool WKTRasterRasterBand::IsSignedByteDataType()
     113                 :  {
     114               0 :      return bIsSignedByte;
     115                 : }
     116                 : 
     117                 : /**
     118                 :  * Get the bit depth for this raster band
     119                 :  * Parameters: none.
     120                 :  * Returns: the bit depth
     121                 :  */
     122               0 :  int WKTRasterRasterBand::GetNBitDepth()
     123                 :  {
     124               0 :      return nBitDepth;
     125                 :  }
     126                 : 
     127                 : /**
     128                 :  * Write a block of data to the raster band. First establish if a corresponding
     129                 :  * row to the block already exists with a SELECT. If so, update the raster 
     130                 :  * column contents. If it does not exist create a new row for the block.
     131                 :  * Inputs:
     132                 :  *  int: horizontal block offset
     133                 :  *  int: vertical block offset
     134                 :  *  void *: The buffer wit the data to be write
     135                 :  * Output:
     136                 :  *  CE_None on success, CE_Failure on error
     137                 :  */
     138               0 : CPLErr WKTRasterRasterBand::IWriteBlock(int nBlockXOff,
     139                 :         int nBlockYOff, void * pImage) {
     140                 : 
     141                 :     // Check parameters
     142               0 :     if (pImage == NULL || nBlockXOff < 0 || nBlockYOff < 0) {
     143                 :         CPLError(CE_Failure, CPLE_NotSupported,
     144               0 :                 "Unsupported block size or NULL buffer");
     145               0 :         return CE_Failure;
     146                 :     }
     147                 : 
     148               0 :     WKTRasterDataset * poWKTRasterDS = (WKTRasterDataset *) poDS;
     149               0 :     CPLString osCommand;
     150                 :     PGresult * hPGresult;
     151                 :     int nPixelSize;
     152                 :     int nPixelXInitPosition;
     153                 :     int nPixelYInitPosition;
     154                 :     int nPixelXEndPosition;
     155                 :     int nPixelYEndPosition;
     156                 :     double adfTransform[6];
     157               0 :     double fProjXInit = 0.0;
     158               0 :     double fProjYInit = 0.0;
     159               0 :     double fProjXEnd = 0.0;
     160               0 :     double fProjYEnd = 0.0;
     161               0 :     double fProjLowerLeftX = 0.0;
     162               0 :     double fProjLowerLeftY = 0.0;
     163               0 :     double fProjUpperRightX = 0.0;
     164               0 :     double fProjUpperRightY = 0.0;
     165               0 :     GByte byMachineEndianess = NDR;
     166               0 :     int nTuples = 0;
     167               0 :     char * pszHexWkb = NULL;
     168               0 :     WKTRasterWrapper * poWKTRasterWrapper = NULL;
     169               0 :     WKTRasterBandWrapper * poWKTRasterBandWrapper = NULL;
     170               0 :     int nRid = 0;
     171               0 :     int nCurrentBandPixelSize = 0;
     172                 : 
     173                 : 
     174                 :     // Check machine endianess
     175                 : #ifdef CPL_LSB
     176               0 :     byMachineEndianess = NDR;
     177                 : #else
     178                 :     byMachineEndianess = XDR;
     179                 : #endif
     180                 : 
     181                 :     /***********************************************************************
     182                 :      * Get pixel size (divide by 8 because GDALGetDataTypeSize returns the
     183                 :      * size in bits)
     184                 :      ***********************************************************************/
     185               0 :     nPixelSize = GDALGetDataTypeSize(eDataType) / 8;
     186                 : 
     187                 :     /***********************************************************************
     188                 :      * nBlockXOff and nBlockYOff are block offsets. So, we first have to
     189                 :      * transform them in pixel/line coordinates, taking into account the
     190                 :      * size of a block.
     191                 :      ***********************************************************************/
     192               0 :     nPixelXInitPosition = nBlockXSize * nBlockXOff;
     193               0 :     nPixelYInitPosition = nBlockYSize * nBlockYOff;
     194                 : 
     195                 :     // Now, get the end of the block
     196               0 :     nPixelXEndPosition = nPixelXInitPosition + nBlockXSize;
     197               0 :     nPixelYEndPosition = nPixelYInitPosition + nBlockYSize;
     198                 : 
     199                 : 
     200                 :     /**************************************************************************
     201                 :      * Transform pixel/line coordinates into coordinates of the raster
     202                 :      * reference system.
     203                 :      * NOTE: I take the georeference information from dataset. The SQL function
     204                 :      * ST_GdalGeoTransform takes the same information from the raster row, in
     205                 :      * array format.
     206                 :      **************************************************************************/
     207               0 :     poWKTRasterDS->GetGeoTransform(adfTransform);
     208               0 :     fProjXInit = adfTransform[0] +
     209               0 :             nPixelXInitPosition * adfTransform[1] +
     210               0 :             nPixelYInitPosition * adfTransform[2];
     211                 : 
     212               0 :     fProjYInit = adfTransform[3] +
     213               0 :             nPixelXInitPosition * adfTransform[4] +
     214               0 :             nPixelYInitPosition * adfTransform[5];
     215                 : 
     216               0 :     fProjXEnd = adfTransform[0] +
     217               0 :             nPixelXEndPosition * adfTransform[1] +
     218               0 :             nPixelYEndPosition * adfTransform[2];
     219                 : 
     220               0 :     fProjYEnd = adfTransform[3] +
     221               0 :             nPixelXEndPosition * adfTransform[4] +
     222               0 :             nPixelYEndPosition * adfTransform[5];
     223                 : 
     224                 : 
     225                 :     /*************************************************************************
     226                 :      * Now we have the block coordinates transformed into coordinates of the
     227                 :      * raster reference system. This coordinates are from:
     228                 :      *  - Upper left corner
     229                 :      *  - Lower right corner
     230                 :      * But for ST_MakeBox2D, we'll need block's coordinates of:
     231                 :      *  - Lower left corner
     232                 :      *  - Upper righ corner
     233                 :      *************************************************************************/
     234               0 :     fProjLowerLeftX = fProjXInit;
     235               0 :     fProjLowerLeftY = fProjYEnd;
     236                 : 
     237               0 :     fProjUpperRightX = fProjXEnd;
     238               0 :     fProjUpperRightY = fProjYInit;
     239                 : 
     240                 : 
     241                 :     /*************************************************************************
     242                 :      * Perform a spatial query that gives the tile/block (row of raster table)
     243                 :      * or tiles/blocks (in case of non-regular blocking) that should contain
     244                 :      * this block
     245                 :      *************************************************************************/
     246                 : 
     247               0 :     if (poWKTRasterDS->pszWhereClause != NULL) {
     248                 : 
     249                 :         /**
     250                 :          * Table has GIST index-
     251                 :          * We could disable sequential scanning, but for versions of PostGIS
     252                 :          * up to 0.8, this is no necessary. PostGIS >=0.8 is correctly
     253                 :          * integrated with query planner, thus PostgreSQL will use indexes
     254                 :          * whenever appropriate.
     255                 :          * NOTE: We should add version checking here, and disable sequential
     256                 :          * scanning when needed. See OGRDataSource::Open method.
     257                 :          */
     258               0 :         if (poWKTRasterDS->bTableHasGISTIndex) {
     259                 : 
     260                 :             /**
     261                 :              * This queries for the tiles that contains the given block. When
     262                 :              * regular_blocking rasters, the blocks will have the same size of
     263                 :              * a tile, so, we can use "contain" function and "~" operator.
     264                 :              * But when non-regular_blocking, the only way this will work is
     265                 :              * setting the block size to the smallest tile size. The problem is
     266                 :              * how do we know all the tiles size?
     267                 :              */
     268                 :             osCommand.Printf(
     269                 :                     "SELECT rid, %s FROM %s.%s WHERE %s ~ ST_SetSRID(ST_MakeBox2D\
     270                 :                     (ST_Point(%f, %f),ST_Point(%f, %f)), %d) AND %s",
     271                 :                     poWKTRasterDS->pszRasterColumnName,
     272                 :                     poWKTRasterDS->pszSchemaName,
     273                 :                     poWKTRasterDS->pszTableName,
     274                 :                     poWKTRasterDS->pszRasterColumnName, fProjLowerLeftX,
     275                 :                     fProjLowerLeftY, fProjUpperRightX, fProjUpperRightY,
     276               0 :                     poWKTRasterDS->nSrid, poWKTRasterDS->pszWhereClause);
     277                 : 
     278                 :         }            /**
     279                 :              * Table hasn't a GIST index. Normal searching
     280                 :              */
     281                 :         else {
     282                 :             osCommand.Printf(
     283                 :                     "SELECT rid, %s FROM %s.%s WHERE _ST_Contains(%s, ST_SetSRID(\
     284                 :                     ST_MakeBox2D(ST_Point(%f, %f), ST_Point(%f, %f)), %d)) AND \
     285                 :                     %s",
     286                 :                     poWKTRasterDS->pszRasterColumnName,
     287                 :                     poWKTRasterDS->pszSchemaName,
     288                 :                     poWKTRasterDS->pszTableName,
     289                 :                     poWKTRasterDS->pszRasterColumnName, fProjLowerLeftX,
     290                 :                     fProjLowerLeftY, fProjUpperRightX, fProjUpperRightY,
     291               0 :                     poWKTRasterDS->nSrid, poWKTRasterDS->pszWhereClause);
     292                 :         }
     293                 : 
     294                 : 
     295                 :     }        // No where clause
     296                 :     else {
     297                 : 
     298                 : 
     299                 :         /**
     300                 :          * Table has a GIST index.
     301                 :          */
     302               0 :         if (poWKTRasterDS->bTableHasGISTIndex) {
     303                 : 
     304                 :             osCommand.Printf(
     305                 :                     "SELECT rid, %s FROM %s.%s WHERE %s ~ ST_SetSRID(ST_MakeBox2D\
     306                 :                     (ST_Point(%f, %f), ST_Point(%f, %f)), %d)",
     307                 :                     poWKTRasterDS->pszRasterColumnName,
     308                 :                     poWKTRasterDS->pszSchemaName,
     309                 :                     poWKTRasterDS->pszTableName,
     310                 :                     poWKTRasterDS->pszRasterColumnName, fProjLowerLeftX,
     311                 :                     fProjLowerLeftY, fProjUpperRightX, fProjUpperRightY,
     312               0 :                     poWKTRasterDS->nSrid);
     313                 : 
     314                 :         }            /**
     315                 :              * Table hasn't a GIST index. Normal searching
     316                 :              */
     317                 :         else {
     318                 :             osCommand.Printf(
     319                 :                     "SELECT rid, %s FROM %s.%s WHERE _ST_Contains(%s, ST_SetSRID(\
     320                 :                     ST_MakeBox2D(ST_Point(%f, %f), ST_Point(%f, %f)), %d))",
     321                 :                     poWKTRasterDS->pszRasterColumnName,
     322                 :                     poWKTRasterDS->pszSchemaName,
     323                 :                     poWKTRasterDS->pszTableName,
     324                 :                     poWKTRasterDS->pszRasterColumnName, fProjLowerLeftX, 
     325                 :                     fProjLowerLeftY, fProjUpperRightX, fProjUpperRightY,
     326               0 :                     poWKTRasterDS->nSrid);
     327                 :         }
     328                 :     }
     329                 : 
     330                 : 
     331                 :     //printf("query: %s\n", osCommand.c_str());
     332                 : 
     333               0 :     hPGresult = PQexec(poWKTRasterDS->hPGconn, osCommand.c_str());
     334               0 :     if (hPGresult == NULL || PQresultStatus(hPGresult) != PGRES_TUPLES_OK) {
     335               0 :         if (hPGresult)
     336               0 :             PQclear(hPGresult);
     337                 : 
     338                 :         CPLError(CE_Failure, CPLE_AppDefined,
     339                 :                 "Sorry, couldn't fetch block information from database: %s",
     340               0 :                 PQerrorMessage(poWKTRasterDS->hPGconn));
     341               0 :         return CE_Failure;
     342                 :     }
     343                 : 
     344                 : 
     345               0 :     nTuples = PQntuples(hPGresult);
     346                 : 
     347                 : 
     348                 :     /*******************************************************
     349                 :      * Block not found. We have to create a new one
     350                 :      *******************************************************/
     351               0 :     if (nTuples <= 0) {
     352                 : 
     353                 :         /**
     354                 :          * There is no block. We need to create a new one. We can use the
     355                 :          * first block of the table and modify it.
     356                 :          */
     357               0 :         PQclear(hPGresult);
     358                 :         osCommand.Printf(
     359                 :                 "SELECT %s FROM %s.%s LIMIT 1 OFFSET 0",
     360                 :                 poWKTRasterDS->pszRasterColumnName,
     361                 :                 poWKTRasterDS->pszSchemaName,
     362               0 :                 poWKTRasterDS->pszTableName);
     363                 : 
     364               0 :         hPGresult = PQexec(poWKTRasterDS->hPGconn, osCommand.c_str());
     365                 : 
     366                 :         /**
     367                 :          * Empty table, What should we do? Is it an error?
     368                 :          */
     369               0 :         if (hPGresult == NULL || PQresultStatus(hPGresult) != PGRES_TUPLES_OK) {
     370               0 :             if (hPGresult)
     371               0 :                 PQclear(hPGresult);
     372                 : 
     373                 :             CPLError(CE_Failure, CPLE_AppDefined,
     374                 :                     "Sorry, couldn't fetch block information from database: %s",
     375               0 :                     PQerrorMessage(poWKTRasterDS->hPGconn));
     376                 : 
     377               0 :             return CE_Failure;
     378                 :         }
     379                 :         
     380                 :         // Get HEXWKB representation of the block
     381               0 :         pszHexWkb = CPLStrdup(PQgetvalue(hPGresult, 0, 0));
     382               0 :         PQclear(hPGresult);
     383                 : 
     384                 :         // Create a wrapper object with this data
     385               0 :         poWKTRasterWrapper = new WKTRasterWrapper();
     386                 : 
     387                 :         // Should we try creating the raster block in other way?
     388               0 :         if (poWKTRasterWrapper->Initialize(pszHexWkb) == FALSE) {
     389               0 :             CPLFree(pszHexWkb);
     390               0 :             delete poWKTRasterWrapper; 
     391               0 :             return CE_Failure;
     392                 :         }
     393                 : 
     394                 :         // We won't need this
     395               0 :         CPLFree(pszHexWkb);
     396                 : 
     397                 :         // Get raster band
     398               0 :         poWKTRasterBandWrapper = poWKTRasterWrapper->GetBand((GUInt16)nBand);
     399                 : 
     400                 :         // Should we try creating the raster block in other way?
     401               0 :         if (poWKTRasterBandWrapper == NULL) {
     402               0 :             delete poWKTRasterWrapper;
     403               0 :             return CE_Failure;
     404                 :         }
     405                 : 
     406                 :         // Set raster data
     407                 :         poWKTRasterBandWrapper->SetData((GByte *)pImage,
     408               0 :                 (nBlockXSize * nBlockYSize) * nPixelSize * sizeof (GByte));
     409                 : 
     410                 :         // Insert new block into table. First, we need a new rid
     411                 :         osCommand.Printf(
     412                 :                 "SELECT rid FROM %s.%s ORDER BY rid DESC LIMIT 1 OFFSET 0",
     413               0 :                 poWKTRasterDS->pszSchemaName, poWKTRasterDS->pszTableName);
     414                 : 
     415               0 :         hPGresult = PQexec(poWKTRasterDS->hPGconn, osCommand.c_str());
     416               0 :         if (
     417                 :                 hPGresult == NULL ||
     418                 :                 PQresultStatus(hPGresult) != PGRES_TUPLES_OK ||
     419                 :                 PQntuples(hPGresult) <= 0) {
     420                 :             // What should we do?
     421               0 :             if (hPGresult)
     422               0 :                 PQclear(hPGresult);
     423               0 :             delete poWKTRasterWrapper;
     424               0 :             delete poWKTRasterBandWrapper;
     425                 : 
     426               0 :             return CE_Failure;
     427                 :         }
     428                 : 
     429               0 :         int nRid = atoi(PQgetvalue(hPGresult, 0, 0)) + 1;
     430               0 :         pszHexWkb = poWKTRasterWrapper->GetHexWkbRepresentation();
     431                 : 
     432                 :         // Insert the block        
     433                 :         osCommand.Printf(
     434                 :                 "INSERT INTO %s.%s (rid, %s) VALUES (%d, %s)",
     435                 :                 poWKTRasterDS->pszSchemaName,poWKTRasterDS->pszTableName,
     436               0 :                 poWKTRasterDS->pszRasterColumnName,nRid, pszHexWkb);
     437                 : 
     438               0 :         hPGresult = PQexec(poWKTRasterDS->hPGconn, osCommand.c_str());
     439               0 :         if (hPGresult == NULL || 
     440                 :                 PQresultStatus(hPGresult) != PGRES_COMMAND_OK) {
     441                 :             CPLError(CE_Failure, CPLE_NoWriteAccess,
     442                 :                     "Couldn't add new block to database: %s",
     443               0 :                     PQerrorMessage(poWKTRasterDS->hPGconn));
     444               0 :             if (hPGresult)
     445               0 :                 PQclear(hPGresult);
     446               0 :             delete poWKTRasterWrapper;
     447               0 :             delete poWKTRasterBandWrapper;
     448               0 :             CPLFree(pszHexWkb);
     449                 : 
     450               0 :             return CE_Failure;
     451                 :         }
     452                 : 
     453                 :         // block added
     454               0 :         CPLFree(pszHexWkb);
     455               0 :         PQclear(hPGresult);
     456                 :     }
     457                 : 
     458                 :    /****************************************************************
     459                 :     * One block found: We have to update the block data
     460                 :     ****************************************************************/
     461               0 :     else if (nTuples == 1) {
     462                 : 
     463                 :         // get data
     464               0 :         nRid = atoi(PQgetvalue(hPGresult, 0, 0));
     465               0 :         pszHexWkb = CPLStrdup(PQgetvalue(hPGresult, 0, 1));
     466               0 :         PQclear(hPGresult);
     467                 : 
     468                 :         // Create wrapper
     469                 :          // Should we try creating the raster block in other way?
     470               0 :         poWKTRasterWrapper = new WKTRasterWrapper();
     471               0 :   if (poWKTRasterWrapper->Initialize(pszHexWkb) == FALSE) {
     472               0 :             CPLFree(pszHexWkb);
     473               0 :             delete poWKTRasterWrapper; 
     474               0 :             return CE_Failure;
     475                 :         }
     476                 : 
     477                 :         // We won't need this
     478               0 :         CPLFree(pszHexWkb);
     479                 : 
     480                 :         // Get raster band
     481               0 :         poWKTRasterBandWrapper = poWKTRasterWrapper->GetBand((GUInt16)nBand);
     482                 : 
     483                 :         // Should we try creating the raster block in other way?
     484                 : 
     485               0 :         if (poWKTRasterBandWrapper == NULL) {
     486               0 :             delete poWKTRasterWrapper;
     487               0 :             return CE_Failure;
     488                 :         }
     489                 : 
     490                 :         /**
     491                 :          * Swap words if needed
     492                 :          */
     493               0 :         if (poWKTRasterWrapper->byEndianess != byMachineEndianess) {
     494                 : 
     495                 :             // Get pixel size of this band
     496               0 :             switch (poWKTRasterBandWrapper->byPixelType) {
     497                 :                 case 0: case 1: case 2: case 3: case 4:
     498               0 :                     nCurrentBandPixelSize = 1;
     499               0 :                     break;
     500                 :                 case 5: case 6: case 9:
     501               0 :                     nCurrentBandPixelSize = 2;
     502               0 :                     break;
     503                 :                 case 7: case 8: case 10:
     504               0 :                     nCurrentBandPixelSize = 4;
     505               0 :                     break;
     506                 :                 case 11:
     507               0 :                     nCurrentBandPixelSize = 8;
     508               0 :                     break;
     509                 :                 default:
     510               0 :                     nCurrentBandPixelSize = 1;
     511                 :             }
     512                 : 
     513                 :             GDALSwapWords((GByte *)pImage, nCurrentBandPixelSize,
     514                 :                     poWKTRasterBandWrapper->nDataSize / nCurrentBandPixelSize,
     515               0 :                     nCurrentBandPixelSize);
     516                 :         }
     517                 : 
     518                 :         // Set raster data
     519                 :         poWKTRasterBandWrapper->SetData((GByte *)pImage,
     520               0 :                 (nBlockXSize * nBlockYSize) * nPixelSize * sizeof (GByte));
     521                 :         
     522                 :         // Get hexwkb again, with new data
     523               0 :         pszHexWkb = poWKTRasterWrapper->GetHexWkbRepresentation();
     524                 : 
     525                 : 
     526                 :         // update register
     527                 :         osCommand.Printf(
     528                 :                 "UPDATE %s.%s SET %s = %s WHERE rid = %d",
     529                 :                 poWKTRasterDS->pszSchemaName, poWKTRasterDS->pszTableName,
     530               0 :                 poWKTRasterDS->pszRasterColumnName, pszHexWkb, nRid);
     531               0 :         hPGresult = PQexec(poWKTRasterDS->hPGconn, osCommand.c_str());
     532               0 :         if (hPGresult == NULL ||
     533                 :                 PQresultStatus(hPGresult) != PGRES_COMMAND_OK) {
     534               0 :             if (hPGresult)
     535               0 :                 PQclear(hPGresult);
     536               0 :             CPLFree(pszHexWkb);
     537                 :             CPLError(CE_Failure, CPLE_NoWriteAccess,
     538               0 :                     "Couldn't update the raster data");
     539               0 :             return CE_Failure;
     540                 :         }
     541                 : 
     542                 :         // ok, updated
     543               0 :         CPLFree(pszHexWkb);
     544               0 :         PQclear(hPGresult);
     545                 : 
     546                 :     }
     547                 :    
     548                 :     /*****************************************************************
     549                 :      * More than one block found. What should we do?
     550                 :      *****************************************************************/
     551                 :     else {
     552                 :         // Only regular_block supported, just now
     553               0 :         PQclear(hPGresult);
     554                 :         CPLError(CE_Failure, CPLE_NotSupported,
     555                 :                 "Sorry, but the raster presents block overlapping. This feature\
     556               0 :                 is under development");
     557                 : 
     558               0 :         return CE_Failure;
     559                 :     }
     560                 : 
     561                 : 
     562               0 :     return CE_None;
     563                 : }
     564                 : 
     565                 : 
     566                 : /**
     567                 :  * Read a block of image data
     568                 :  * Inputs:
     569                 :  *  int: horizontal block offset
     570                 :  *  int: vertical block offset
     571                 :  *  void *: The buffer into the data will be read
     572                 :  * Output:
     573                 :  *  CE_None on success, CE_Failure on error
     574                 :  */
     575               0 : CPLErr WKTRasterRasterBand::IReadBlock(int nBlockXOff,
     576                 :         int nBlockYOff, void * pImage) {
     577                 : 
     578               0 :     WKTRasterDataset * poWKTRasterDS = (WKTRasterDataset *) poDS;
     579               0 :     CPLString osCommand;
     580                 :     PGresult * hPGresult;
     581                 :     int nPixelSize;
     582                 :     int nPixelXInitPosition;
     583                 :     int nPixelYInitPosition;
     584                 :     int nPixelXEndPosition;
     585                 :     int nPixelYEndPosition;
     586                 :     double adfTransform[6];
     587               0 :     double dfProjXInit = 0.0;
     588               0 :     double dfProjYInit = 0.0;
     589               0 :     double dfProjXEnd = 0.0;
     590               0 :     double dfProjYEnd = 0.0;
     591               0 :     double dfProjLowerLeftX = 0.0;
     592               0 :     double dfProjLowerLeftY = 0.0;
     593               0 :     double dfProjUpperRightX = 0.0;
     594               0 :     double dfProjUpperRightY = 0.0;
     595               0 :     char * pszHexWkb = NULL;
     596               0 :     GByte byMachineEndianess = NDR; // by default
     597               0 :     int nTuples = 0;
     598               0 :     GByte * pbyRasterData = NULL;
     599               0 :     WKTRasterWrapper * poWKTRasterWrapper = NULL;
     600               0 :     WKTRasterBandWrapper * poWKTRasterBandWrapper = NULL;
     601               0 :     int nNaturalXBlockSize = 0;
     602               0 :     int nNaturalYBlockSize = 0;
     603                 : 
     604                 : 
     605                 :     // Check parameters
     606               0 :     if (pImage == NULL || nBlockXOff < 0 || nBlockYOff < 0) {
     607                 :         CPLError(CE_Failure, CPLE_NotSupported,
     608               0 :                 "Unsupported block size or NULL buffer");
     609               0 :         return CE_Failure;
     610                 :     }
     611                 : 
     612                 :    
     613                 :     // Check machine endianess
     614                 : #ifdef CPL_LSB
     615               0 :     byMachineEndianess = NDR;
     616                 : #else
     617                 :     byMachineEndianess = XDR;
     618                 : #endif
     619                 : 
     620                 :     /*************************************************************************
     621                 :      * Get pixel size (divide by 8 because GDALGetDataTypeSize returns the
     622                 :      * size in bits)
     623                 :      *************************************************************************/
     624               0 :     nPixelSize = MAX(1,GDALGetDataTypeSize(eDataType)/8);
     625                 : 
     626                 :     /*************************************************************************
     627                 :      * nBlockXOff and nBlockYOff are block offsets. So, we first have to
     628                 :      * transform them in pixel/line coordinates, taking into account the
     629                 :      * size of a block.
     630                 :      *************************************************************************/
     631               0 :     GetBlockSize(&nNaturalXBlockSize, &nNaturalYBlockSize);
     632                 : 
     633                 : 
     634               0 :     nPixelXInitPosition = nNaturalXBlockSize * nBlockXOff;
     635               0 :     nPixelYInitPosition = nNaturalYBlockSize * nBlockYOff;
     636                 : 
     637                 :     // Now, get the end of the block
     638               0 :     nPixelXEndPosition = nPixelXInitPosition + nNaturalXBlockSize;
     639               0 :     nPixelYEndPosition = nPixelYInitPosition + nNaturalYBlockSize;
     640                 : 
     641                 : 
     642                 :     /**************************************************************************
     643                 :      * Transform pixel/line coordinates into coordinates of the raster
     644                 :      * reference system.
     645                 :      * NOTE: I take the georeference information from dataset. The SQL function
     646                 :      * ST_GdalGeoTransform takes the same information from the raster row, in
     647                 :      * array format.
     648                 :      **************************************************************************/
     649               0 :     poWKTRasterDS->GetGeoTransform(adfTransform);
     650               0 :     dfProjXInit = adfTransform[0] +
     651               0 :             nPixelXInitPosition * adfTransform[1] +
     652               0 :             nPixelYInitPosition * adfTransform[2];
     653                 : 
     654               0 :     dfProjYInit = adfTransform[3] +
     655               0 :             nPixelXInitPosition * adfTransform[4] +
     656               0 :             nPixelYInitPosition * adfTransform[5];
     657                 : 
     658               0 :     dfProjXEnd = adfTransform[0] +
     659               0 :             nPixelXEndPosition * adfTransform[1] +
     660               0 :             nPixelYEndPosition * adfTransform[2];
     661                 : 
     662               0 :     dfProjYEnd = adfTransform[3] +
     663               0 :             nPixelXEndPosition * adfTransform[4] +
     664               0 :             nPixelYEndPosition * adfTransform[5];
     665                 : 
     666                 : 
     667                 :     /*************************************************************************
     668                 :      * Now we have the block coordinates transformed into coordinates of the
     669                 :      * raster reference system. This coordinates are from:
     670                 :      *  - Upper left corner
     671                 :      *  - Lower right corner
     672                 :      * But for ST_MakeBox2D, we'll need block's coordinates of:
     673                 :      *  - Lower left corner
     674                 :      *  - Upper right corner
     675                 :      *************************************************************************/
     676               0 :     dfProjLowerLeftX = dfProjXInit;
     677               0 :     dfProjLowerLeftY = dfProjYEnd;
     678                 : 
     679               0 :     dfProjUpperRightX = dfProjXEnd;
     680               0 :     dfProjUpperRightY = dfProjYInit;
     681                 : 
     682                 : 
     683                 :     /**************************************************************************
     684                 :      * Perform a spatial query that gives the tile/block (row of raster table)
     685                 :      * or tiles/blocks (in case of non-regular blocking) that contain this block
     686                 :      **************************************************************************/
     687                 : 
     688               0 :     if (poWKTRasterDS->pszWhereClause != NULL) {
     689                 : 
     690                 :         /**
     691                 :          * Table has GIST index-
     692                 :          * We could disable sequential scanning, but for versions of PostGIS
     693                 :          * up to 0.8, this is no necessary. PostGIS >=0.8 is correctly
     694                 :          * integrated with query planner, thus PostgreSQL will use indexes
     695                 :          * whenever appropriate.
     696                 :          * NOTE: We should add version checking here, and disable sequential
     697                 :          * scanning when needed. See OGRDataSource::Open method.
     698                 :          */
     699               0 :         if (poWKTRasterDS->bTableHasGISTIndex) {
     700                 : 
     701                 :             /**
     702                 :              * This queries for the tiles that contains the given block. When
     703                 :              * regular_blocking rasters, the blocks will have the same size of
     704                 :              * a tile, so, we can use "contain" function and "~" operator. 
     705                 :              * But when non-regular_blocking, the only way this will work is
     706                 :              * setting the block size to the smallest tile size. The problem is
     707                 :              * how do we know all the tiles size?
     708                 :              */
     709                 :             osCommand.Printf(
     710                 :                     "SELECT rid, %s FROM %s.%s WHERE %s ~ ST_SetSRID(ST_MakeBox2D\
     711                 :                     (ST_Point(%f, %f),ST_Point(%f, %f)), %d) AND %s",
     712                 :                     poWKTRasterDS->pszRasterColumnName,
     713                 :                     poWKTRasterDS->pszSchemaName,
     714                 :                     poWKTRasterDS->pszTableName,
     715                 :                     poWKTRasterDS->pszRasterColumnName, dfProjLowerLeftX,
     716                 :                     dfProjLowerLeftY, dfProjUpperRightX, dfProjUpperRightY,
     717               0 :                     poWKTRasterDS->nSrid, poWKTRasterDS->pszWhereClause);
     718                 : 
     719                 :         }            /**
     720                 :              * Table hasn't a GIST index. Normal searching
     721                 :              */
     722                 :         else {
     723                 :             osCommand.Printf(
     724                 :                     "SELECT rid, %s FROM %s.%s WHERE _ST_Contains(%s, ST_SetSRID(\
     725                 :                     ST_MakeBox2D(ST_Point(%f, %f), ST_Point(%f, %f)), %d)) AND\
     726                 :                     %s",
     727                 :                     poWKTRasterDS->pszRasterColumnName,
     728                 :                     poWKTRasterDS->pszSchemaName,
     729                 :                     poWKTRasterDS->pszTableName,
     730                 :                     poWKTRasterDS->pszRasterColumnName, dfProjLowerLeftX,
     731                 :                     dfProjLowerLeftY, dfProjUpperRightX, dfProjUpperRightY,
     732               0 :                     poWKTRasterDS->nSrid, poWKTRasterDS->pszWhereClause);
     733                 :         }
     734                 : 
     735                 : 
     736                 :     }        // No where clause
     737                 :     else {
     738                 : 
     739                 : 
     740                 : 
     741                 :         //printf("raster band: srid from dataset: %d\n", poWKTRasterDS->nSrid);
     742                 : 
     743                 :         /**
     744                 :          * Table has a GIST index.
     745                 :          */
     746               0 :         if (poWKTRasterDS->bTableHasGISTIndex) {
     747                 : 
     748                 :             osCommand.Printf(
     749                 :                     "SELECT rid, %s FROM %s.%s WHERE %s ~ ST_SetSRID(ST_MakeBox2D(\
     750                 :                     ST_Point(%f, %f),ST_Point(%f, %f)), %d)",
     751                 :                     poWKTRasterDS->pszRasterColumnName,
     752                 :                     poWKTRasterDS->pszSchemaName,
     753                 :                     poWKTRasterDS->pszTableName,
     754                 :                     poWKTRasterDS->pszRasterColumnName, dfProjLowerLeftX,
     755                 :                     dfProjLowerLeftY,dfProjUpperRightX, dfProjUpperRightY,
     756               0 :                     poWKTRasterDS->nSrid);
     757                 : 
     758                 :         }            /**
     759                 :              * Table hasn't a GIST index. Normal searching
     760                 :              */
     761                 :         else {
     762                 :             osCommand.Printf(
     763                 :                     "SELECT rid, %s FROM %s.%s WHERE _ST_Contains(%s, ST_SetSRID(\
     764                 :                     ST_MakeBox2D(ST_Point(%f, %f), ST_Point(%f, %f)), %d))",
     765                 :                     poWKTRasterDS->pszRasterColumnName,
     766                 :                     poWKTRasterDS->pszSchemaName,
     767                 :                     poWKTRasterDS->pszTableName,
     768                 :                     poWKTRasterDS->pszRasterColumnName, dfProjLowerLeftX,
     769                 :                     dfProjLowerLeftY, dfProjUpperRightX, dfProjUpperRightY,
     770               0 :                     poWKTRasterDS->nSrid);
     771                 :         }
     772                 :     }
     773                 : 
     774                 : 
     775                 :     //printf("query: %s\n", szCommand);
     776                 : 
     777               0 :     hPGresult = PQexec(poWKTRasterDS->hPGconn, osCommand.c_str());
     778                 : 
     779               0 :     if (hPGresult == NULL ||
     780                 :             PQresultStatus(hPGresult) != PGRES_TUPLES_OK ||
     781                 :             PQntuples(hPGresult) < 0)
     782                 :     {
     783               0 :         if (hPGresult)
     784               0 :             PQclear(hPGresult);
     785                 :         CPLError(CE_Failure, CPLE_AppDefined,
     786                 :                 "Sorry, couldn't fetch block information from database: %s",
     787               0 :                 PQerrorMessage(poWKTRasterDS->hPGconn));
     788               0 :         return CE_Failure;
     789                 :     }
     790                 : 
     791                 : 
     792               0 :     nTuples = PQntuples(hPGresult);
     793                 : 
     794                 :     /*****************************************************************
     795                 :      * No blocks found. Fill the buffer with nodata value
     796                 :      *****************************************************************/
     797               0 :     if (nTuples == 0) {
     798               0 :         NullBlock(pImage);
     799               0 :         return CE_None;
     800                 :     }
     801                 : 
     802                 :     
     803                 :     /******************************************************************
     804                 :      * One block found. Regular blocking arrangements, no overlaps
     805                 :      ******************************************************************/
     806               0 :     else if (nTuples == 1) {
     807               0 :         int nRid = atoi(PQgetvalue(hPGresult, 0, 0));      
     808                 : 
     809                 :         // Get HEXWKB representation of the block
     810               0 :         pszHexWkb = CPLStrdup(PQgetvalue(hPGresult, 0, 1));
     811                 : 
     812               0 :         PQclear(hPGresult);
     813                 : 
     814                 :         // Raster hex must have an even number of characters
     815               0 :         if (pszHexWkb == NULL || strlen(pszHexWkb) % 2) {
     816                 :             CPLError(CE_Failure, CPLE_AppDefined,
     817                 :                     "The HEXWKB data fetch from database must have an even number \
     818               0 :                   of characters");
     819               0 :             return CE_Failure;
     820                 :         }
     821                 : 
     822                 : 
     823                 :         // Create a wrapper object
     824               0 :         poWKTRasterWrapper = new WKTRasterWrapper();
     825               0 :         if (poWKTRasterWrapper->Initialize(pszHexWkb) == FALSE) {
     826               0 :             CPLFree(pszHexWkb);
     827               0 :             delete poWKTRasterWrapper;
     828               0 :             return CE_Failure;
     829                 :         }
     830                 :         
     831                 : 
     832                 :         // We won't need this
     833               0 :         CPLFree(pszHexWkb);
     834                 : 
     835                 :         // Create raster band wrapper
     836               0 :         poWKTRasterBandWrapper = poWKTRasterWrapper->GetBand((GUInt16)nBand);
     837               0 :         if (poWKTRasterBandWrapper == NULL) {
     838               0 :             CPLError(CE_Failure, CPLE_ObjectNull,"Couldn't fetch band data");
     839               0 :             delete poWKTRasterWrapper;
     840               0 :             return CE_Failure;
     841                 :         }
     842                 : 
     843                 :         // Get raster data
     844               0 :         pbyRasterData = poWKTRasterBandWrapper->GetData();
     845                 : 
     846                 :        
     847                 :         
     848                 :         //printf("IReadBlock with offset: %d, %d\n", nBlockXOff, nBlockYOff);
     849                 : 
     850                 :         /**********************************************************
     851                 :          * Check if the raster is offline
     852                 :          **********************************************************/
     853               0 :         if (poWKTRasterBandWrapper->bIsOffline == TRUE) {
     854                 :             // The raster data in this case is a path to the raster file
     855               0 :             int nBandToRead = poWKTRasterBandWrapper->nOutDbBandNumber;
     856                 : 
     857                 : 
     858                 :             // Open dataset, if needed
     859               0 :             if  (poWKTRasterDS->poOutdbRasterDS == NULL) {
     860                 :                 poWKTRasterDS->poOutdbRasterDS = (GDALDataset *)
     861               0 :                         GDALOpen((char *)pbyRasterData, GA_ReadOnly);
     862                 :             }
     863                 : 
     864               0 :             if (poWKTRasterDS->poOutdbRasterDS != NULL)
     865                 : 
     866                 :                 // Read data from band
     867                 :                 /**
     868                 :                  * NOT SO SIMPLE!!!!
     869                 :                  * The outdb file may don't have the same block structure...
     870                 :                  */
     871                 : 
     872                 :                 /*
     873                 :                 poWKTRasterDS->poOutdbRasterDS->GetRasterBand(nBandToRead)->ReadBlock(
     874                 :                     nBlockXOff, nBlockYOff, pImage);
     875                 :                  */
     876                 :                 ;
     877                 :             else {
     878                 :                 CPLError(CE_Failure, CPLE_ObjectNull,
     879               0 :                     "Couldn't read band data from out-db raster");
     880               0 :                 delete poWKTRasterWrapper;
     881               0 :                 return CE_Failure;
     882                 :             }
     883                 :             
     884                 :         }
     885                 : 
     886                 : 
     887                 :         else {
     888                 :             /**
     889                 :              * Copy the data buffer into pImage.
     890                 :              * nBlockXSize * nBlockYSize should be equal to nDataSize/2
     891                 :              */
     892                 :             memcpy(pImage, pbyRasterData,
     893                 :                     (nNaturalXBlockSize * nNaturalYBlockSize) *
     894               0 :                     nPixelSize * sizeof (GByte));
     895                 :         }
     896                 :        
     897                 : 
     898                 : 
     899                 :         // Free resources and exit
     900               0 :         delete poWKTRasterWrapper;
     901                 : 
     902               0 :         return CE_None;
     903                 : 
     904                 :     }// end if ntuples == 1
     905                 : 
     906                 :         /*********************************************************************
     907                 :          * More than one block found. Non regular blocking arrangements
     908                 :          *********************************************************************/
     909                 :     else {
     910                 :         // Only regular_block supported, just now
     911               0 :         PQclear(hPGresult);
     912                 :         CPLError(CE_Failure, CPLE_NotSupported,
     913                 :                 "Sorry, but the raster presents block overlapping. This feature \
     914               0 :                 is under development");
     915                 : 
     916               0 :         return CE_Failure;
     917               0 :     }
     918                 : }
     919                 : 
     920                 : /**
     921                 :  * Set the block data to the null value if it is set, or zero if there is
     922                 :  * no null data value.
     923                 :  * Parameters:
     924                 :  *  - void *: the block data
     925                 :  * Returns: nothing
     926                 :  */
     927               0 : void WKTRasterRasterBand::NullBlock(void *pData) {
     928               0 :     VALIDATE_POINTER0(pData, "NullBlock");
     929                 : 
     930               0 :     int nNaturalBlockXSize = 0;
     931               0 :     int nNaturalBlockYSize = 0;
     932               0 :     GetBlockSize(&nNaturalBlockXSize, &nNaturalBlockYSize);
     933                 : 
     934               0 :     int nWords = nNaturalBlockXSize * nNaturalBlockYSize;
     935               0 :     int nChunkSize = MAX(1, GDALGetDataTypeSize(eDataType) / 8);
     936                 : 
     937                 :     int bNoDataSet;
     938               0 :     double dfNoData = GetNoDataValue(&bNoDataSet);
     939               0 :     if (!bNoDataSet) {
     940               0 :         memset(pData, 0, nWords * nChunkSize);
     941                 :     } else {
     942               0 :         int i = 0;
     943               0 :         for (i = 0; i < nWords; i += nChunkSize)
     944               0 :             memcpy((GByte *) pData + i, &dfNoData, nChunkSize);
     945                 :     }
     946                 : }
     947                 : 
     948                 : /**
     949                 :  * Set the no data value for this band.
     950                 :  * Parameters:
     951                 :  *  - double: The nodata value
     952                 :  * Returns:
     953                 :  *  - CE_None.
     954                 :  */
     955               0 : CPLErr WKTRasterRasterBand::SetNoDataValue(double dfNewValue) {
     956               0 :     dfNoDataValue = dfNewValue;
     957                 : 
     958               0 :     return CE_None;
     959                 : }
     960                 : 
     961                 : /**
     962                 :  * Fetch the no data value for this band.
     963                 :  * Parameters:
     964                 :  *  - int *: pointer to a boolean to use to indicate if a value is actually
     965                 :  *          associated with this layer. May be NULL (default).
     966                 :  *  Returns:
     967                 :  *  - double: the nodata value for this band.
     968                 :  */
     969               0 : double WKTRasterRasterBand::GetNoDataValue(int *pbSuccess) {
     970               0 :     if (pbSuccess != NULL)
     971               0 :         *pbSuccess = TRUE;
     972                 : 
     973               0 :     return dfNoDataValue;
     974                 : }
     975                 : 
     976                 : /**
     977                 :  * Returns the number of overview layers available.
     978                 :  * Parameters: none
     979                 :  * Returns:
     980                 :  *  int: the number of overviews layers available
     981                 :  */
     982               0 : int WKTRasterRasterBand::GetOverviewCount() {
     983               0 :     WKTRasterDataset * poWKTRasterDS = (WKTRasterDataset *) poDS;
     984                 : 
     985                 :     return (poWKTRasterDS->nOverviews > 0) ?
     986                 :             poWKTRasterDS->nOverviews :
     987               0 :             GDALRasterBand::GetOverviewCount();
     988                 : }
     989                 : 
     990                 : /**
     991                 :  * Fetch overview raster band object.
     992                 :  * Parameters:
     993                 :  *  - int: overview index between 0 and GetOverviewCount()-1
     994                 :  * Returns:
     995                 :  *  - GDALRasterBand *: overview GDALRasterBand.
     996                 :  */
     997               0 : GDALRasterBand * WKTRasterRasterBand::GetOverview(int nOverview) {
     998               0 :     WKTRasterDataset * poWKTRasterDS = (WKTRasterDataset *) poDS;
     999                 : 
    1000               0 :     if (poWKTRasterDS->nOverviews > 0) {
    1001               0 :         if (nOverview < 0 || nOverview >= poWKTRasterDS->nOverviews)
    1002               0 :             return NULL;
    1003                 :         else
    1004                 :             return
    1005               0 :             poWKTRasterDS->papoWKTRasterOv[nOverview]->GetRasterBand(nBand);
    1006                 :     } else
    1007               0 :         return GDALRasterBand::GetOverview(nOverview);
    1008                 : }
    1009                 : 
    1010                 : /**
    1011                 :  * Get the natural block size for this band.
    1012                 :  * Parameters:
    1013                 :  *  - int *: pointer to int to store the natural X block size
    1014                 :  *  - int *: pointer to int to store the natural Y block size
    1015                 :  * Returns: nothing
    1016                 :  */
    1017               0 : void WKTRasterRasterBand::GetBlockSize(int * pnXSize, int *pnYSize)
    1018                 :  {
    1019               0 :     if (nBlockXSize == 0 || nBlockYSize == 0) {
    1020                 :         CPLError(CE_Failure, CPLE_AppDefined,
    1021                 :                 "This WKT Raster band has non regular blocking arrangement. \
    1022               0 :                 This feature is under development");
    1023                 : 
    1024               0 :         if (pnXSize != NULL)
    1025               0 :             *pnXSize = 0;
    1026               0 :         if (pnYSize != NULL)
    1027               0 :             *pnYSize = 0;
    1028                 : 
    1029                 :     }
    1030                 :     else {
    1031               0 :         GDALRasterBand::GetBlockSize(pnXSize, pnYSize);
    1032                 :     }
    1033               0 : }
    1034                 : 
    1035                 : 
    1036                 : 
    1037                 : 
    1038                 : 

Generated by: LCOV version 1.7