LCOV - code coverage report
Current view: directory - frmts/wms - dataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 238 152 63.9 %
Date: 2010-01-09 Functions: 13 7 53.8 %

       1                 : /******************************************************************************
       2                 :  * $Id: dataset.cpp 18020 2009-11-14 14:33:20Z rouault $
       3                 :  *
       4                 :  * Project:  WMS Client Driver
       5                 :  * Purpose:  Implementation of Dataset and RasterBand classes for WMS
       6                 :  *           and other similar services.
       7                 :  * Author:   Adam Nowacki, nowak@xpam.de
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 2007, Adam Nowacki
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  ****************************************************************************/
      30                 : 
      31                 : #include "stdinc.h"
      32                 : 
      33               5 : GDALWMSDataset::GDALWMSDataset() {
      34               5 :     m_mini_driver = 0;
      35               5 :     m_cache = 0;
      36               5 :     m_hint.m_valid = false;
      37               5 :     m_data_type = GDT_Byte;
      38               5 :     m_clamp_requests = true;
      39               5 : }
      40                 : 
      41              10 : GDALWMSDataset::~GDALWMSDataset() {
      42               5 :     if (m_mini_driver) delete m_mini_driver;
      43               5 :     if (m_cache) delete m_cache;
      44              10 : }
      45               5 : CPLErr GDALWMSDataset::Initialize(CPLXMLNode *config) {
      46               5 :     CPLErr ret = CE_None;
      47                 : 
      48               5 :     if (ret == CE_None) {
      49               5 :         const char *max_conn = CPLGetXMLValue(config, "MaxConnections", "");
      50               5 :         if (max_conn[0] != '\0') {
      51               0 :             m_http_max_conn = atoi(max_conn);
      52                 :         } else {
      53               5 :             m_http_max_conn = 2;
      54                 :         }
      55                 :     }
      56               5 :     if (ret == CE_None) {
      57               5 :         const char *timeout = CPLGetXMLValue(config, "Timeout", "");
      58               5 :         if (timeout[0] != '\0') {
      59               0 :             m_http_timeout = atoi(timeout);
      60                 :         } else {
      61               5 :             m_http_timeout = 300;
      62                 :         }
      63                 :     }
      64               5 :     if (ret == CE_None) {
      65               5 :         const char *offline_mode = CPLGetXMLValue(config, "OfflineMode", "");
      66               5 :         if (offline_mode[0] != '\0') {
      67               0 :             const int offline_mode_bool = StrToBool(offline_mode);
      68               0 :             if (offline_mode_bool == -1) {
      69               0 :                 CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of OfflineMode, true / false expected.");
      70               0 :                 ret = CE_Failure;
      71                 :             } else {
      72               0 :                 m_offline_mode = offline_mode_bool;
      73                 :             }
      74                 :         } else {
      75               5 :             m_offline_mode = 0;
      76                 :         }
      77                 :     }
      78               5 :     if (ret == CE_None) {
      79               5 :         const char *advise_read = CPLGetXMLValue(config, "AdviseRead", "");
      80               5 :         if (advise_read[0] != '\0') {
      81               0 :             const int advise_read_bool = StrToBool(advise_read);
      82               0 :             if (advise_read_bool == -1) {
      83               0 :                 CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of AdviseRead, true / false expected.");
      84               0 :                 ret = CE_Failure;
      85                 :             } else {
      86               0 :                 m_use_advise_read = advise_read_bool;
      87                 :             }
      88                 :         } else {
      89               5 :             m_use_advise_read = 0;
      90                 :         }
      91                 :     }
      92               5 :     if (ret == CE_None) {
      93               5 :         const char *verify_advise_read = CPLGetXMLValue(config, "VerifyAdviseRead", "");
      94               5 :         if (m_use_advise_read) {
      95               0 :             if (verify_advise_read[0] != '\0') {
      96               0 :                 const int verify_advise_read_bool = StrToBool(verify_advise_read);
      97               0 :                 if (verify_advise_read_bool == -1) {
      98               0 :                     CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of VerifyAdviseRead, true / false expected.");
      99               0 :                     ret = CE_Failure;
     100                 :                 } else {
     101               0 :                     m_verify_advise_read = verify_advise_read_bool;
     102                 :                 }
     103                 :             } else {
     104               0 :                 m_verify_advise_read = 1;
     105                 :             }
     106                 :         }
     107                 :     }
     108               5 :     if (ret == CE_None) {
     109               5 :         const char *block_size_x = CPLGetXMLValue(config, "BlockSizeX", "1024");
     110               5 :         const char *block_size_y = CPLGetXMLValue(config, "BlockSizeY", "1024");
     111               5 :         m_block_size_x = atoi(block_size_x);
     112               5 :         m_block_size_y = atoi(block_size_y);
     113               5 :         if (m_block_size_x <= 0 || m_block_size_y <= 0)
     114                 :         {
     115                 :             CPLError( CE_Failure, CPLE_AppDefined,
     116               0 :                       "GDALWMS: Invalid value in BlockSizeX or BlockSizeY" );
     117               0 :             ret = CE_Failure;
     118                 :         }
     119                 :     }
     120               5 :     if (ret == CE_None)
     121                 :     {
     122               5 :         const char *data_type = CPLGetXMLValue(config, "DataType", "Byte");
     123               5 :         m_data_type = GDALGetDataTypeByName( data_type );
     124               5 :         if ( m_data_type == GDT_Unknown || m_data_type >= GDT_TypeCount )
     125                 :         {
     126                 :             CPLError( CE_Failure, CPLE_AppDefined,
     127               0 :                       "GDALWMS: Invalid value in DataType. Data type \"%s\" is not supported.", data_type );
     128               0 :             ret = CE_Failure;
     129                 :         }
     130                 :     }
     131               5 :     if (ret == CE_None) {
     132               5 :       const int clamp_requests_bool = StrToBool(CPLGetXMLValue(config, "ClampRequests", "true"));
     133               5 :       if (clamp_requests_bool == -1) {
     134               0 :       CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Invalid value of ClampRequests, true / false expected.");
     135               0 :       ret = CE_Failure;
     136                 :   } else {
     137               5 :       m_clamp_requests = clamp_requests_bool;
     138                 :   }
     139                 :     }
     140               5 :     if (ret == CE_None) {
     141               5 :         CPLXMLNode *data_window_node = CPLGetXMLNode(config, "DataWindow");
     142               5 :         if (data_window_node == NULL) {
     143               0 :             CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: DataWindow missing.");
     144               0 :             ret = CE_Failure;
     145                 :         } else {
     146               5 :             const char *overview_count = CPLGetXMLValue(config, "OverviewCount", "");
     147               5 :             const char *ulx = CPLGetXMLValue(data_window_node, "UpperLeftX", "-180.0");
     148               5 :             const char *uly = CPLGetXMLValue(data_window_node, "UpperLeftY", "90.0");
     149               5 :             const char *lrx = CPLGetXMLValue(data_window_node, "LowerRightX", "180.0");
     150               5 :             const char *lry = CPLGetXMLValue(data_window_node, "LowerRightY", "-90.0");
     151               5 :             const char *sx = CPLGetXMLValue(data_window_node, "SizeX", "");
     152               5 :             const char *sy = CPLGetXMLValue(data_window_node, "SizeY", "");
     153               5 :             const char *tx = CPLGetXMLValue(data_window_node, "TileX", "0");
     154               5 :             const char *ty = CPLGetXMLValue(data_window_node, "TileY", "0");
     155               5 :             const char *tlevel = CPLGetXMLValue(data_window_node, "TileLevel", "");
     156               5 :             const char *str_tile_count_x = CPLGetXMLValue(data_window_node, "TileCountX", "1");
     157               5 :             const char *str_tile_count_y = CPLGetXMLValue(data_window_node, "TileCountY", "1");
     158               5 :             const char *y_origin = CPLGetXMLValue(data_window_node, "YOrigin", "default");
     159                 : 
     160               5 :             if (ret == CE_None) {
     161              10 :                 if ((ulx[0] != '\0') && (uly[0] != '\0') && (lrx[0] != '\0') && (lry[0] != '\0')) {
     162               5 :                     m_data_window.m_x0 = atof(ulx);
     163               5 :                     m_data_window.m_y0 = atof(uly);
     164               5 :                     m_data_window.m_x1 = atof(lrx);
     165               5 :                     m_data_window.m_y1 = atof(lry);
     166                 :                 } else {
     167               0 :                     CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Mandatory elements of DataWindow missing: UpperLeftX, UpperLeftY, LowerRightX, LowerRightY.");
     168               0 :                     ret = CE_Failure;
     169                 :                 }
     170                 :             }
     171               5 :             if (ret == CE_None) {
     172               5 :                 if (tlevel[0] != '\0') {
     173               3 :                     m_data_window.m_tlevel = atoi(tlevel);
     174                 :                 } else {
     175               2 :                     m_data_window.m_tlevel = 0;
     176                 :                 }
     177                 :             }
     178               5 :             if (ret == CE_None) {
     179               8 :                 if ((sx[0] != '\0') && (sy[0] != '\0')) {
     180               3 :                     m_data_window.m_sx = atoi(sx);
     181               3 :                     m_data_window.m_sy = atoi(sy);
     182               4 :                 } else if ((tlevel[0] != '\0') && (str_tile_count_x[0] != '\0') && (str_tile_count_y[0] != '\0')) {
     183               2 :                     int tile_count_x = atoi(str_tile_count_x);
     184               2 :                     int tile_count_y = atoi(str_tile_count_y);
     185               2 :                     m_data_window.m_sx = tile_count_x * m_block_size_x * (1 << m_data_window.m_tlevel);
     186               2 :                     m_data_window.m_sy = tile_count_y * m_block_size_y * (1 << m_data_window.m_tlevel);
     187                 :                 } else {
     188               0 :                     CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Mandatory elements of DataWindow missing: SizeX, SizeY.");
     189               0 :                     ret = CE_Failure;
     190                 :                 }
     191                 :             }
     192               5 :             if (ret == CE_None) {
     193              10 :                 if ((tx[0] != '\0') && (ty[0] != '\0')) {
     194               5 :                     m_data_window.m_tx = atoi(tx);
     195               5 :                     m_data_window.m_ty = atoi(ty);
     196                 :                 } else {
     197               0 :                     CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Mandatory elements of DataWindow missing: TileX, TileY.");
     198               0 :                     ret = CE_Failure;
     199                 :                 }
     200                 :             }
     201               5 :             if (ret == CE_None) {
     202               5 :                 if (overview_count[0] != '\0') {
     203               1 :                     m_overview_count = atoi(overview_count);
     204               4 :                 } else if (tlevel[0] != '\0') {
     205               2 :                     m_overview_count = m_data_window.m_tlevel;
     206                 :                 } else {
     207               2 :                     const int min_overview_size = MAX(32, MIN(m_block_size_x, m_block_size_y));
     208                 :                     double a = log(static_cast<double>(MIN(m_data_window.m_sx, m_data_window.m_sy))) / log(2.0) 
     209               2 :                                 - log(static_cast<double>(min_overview_size)) / log(2.0);
     210               2 :                     m_overview_count = MAX(0, MIN(static_cast<int>(ceil(a)), 32));
     211                 :                 }
     212                 :             }
     213               5 :             if (ret == CE_None) {
     214               5 :                 CPLString y_origin_str = y_origin;
     215               5 :                 if (y_origin_str == "top") {
     216               0 :                     m_data_window.m_y_origin = GDALWMSDataWindow::TOP;
     217               5 :                 } else if (y_origin_str == "bottom") {
     218               0 :                     m_data_window.m_y_origin = GDALWMSDataWindow::BOTTOM;
     219               5 :                 } else if (y_origin_str == "default") {
     220               5 :                     m_data_window.m_y_origin = GDALWMSDataWindow::DEFAULT;
     221                 :                 } else {
     222                 :                     CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: DataWindow YOrigin must be set to " 
     223               0 :                                 "one of 'default', 'top', or 'bottom', not '%s'.", y_origin_str.c_str());
     224               0 :                     ret = CE_Failure;
     225               5 :                 }
     226                 :             }
     227                 :         }
     228                 :     }
     229               5 :     if (ret == CE_None) {
     230               5 :         const char *proj = CPLGetXMLValue(config, "Projection", "");
     231               5 :         if (proj[0] != '\0') {
     232               5 :             m_projection = ProjToWKT(proj);
     233               5 :             if (m_projection.size() == 0) {
     234               0 :                 CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Bad projection specified.");
     235               0 :                 ret = CE_Failure;
     236                 :             }
     237                 :         }
     238                 :     }
     239                 :     
     240               5 :     const char *bands_count = CPLGetXMLValue(config, "BandsCount", "3");
     241               5 :     int nBandCount = atoi(bands_count);
     242                 :     
     243               5 :     if (ret == CE_None) {
     244               5 :         CPLXMLNode *cache_node = CPLGetXMLNode(config, "Cache");
     245               5 :         if (cache_node != NULL) {
     246               1 :             m_cache = new GDALWMSCache();
     247               1 :             if (m_cache->Initialize(cache_node) != CE_None) {
     248               0 :                 delete m_cache;
     249               0 :                 m_cache = NULL;
     250               0 :                 CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Failed to initialize cache.");
     251               0 :                 ret = CE_Failure;
     252                 :             }
     253                 :         }
     254                 :     }
     255               5 :     if (ret == CE_None) {
     256               5 :         CPLXMLNode *service_node = CPLGetXMLNode(config, "Service");
     257               5 :         if (service_node != NULL) {
     258               5 :             const char *service_name = CPLGetXMLValue(service_node, "name", "");
     259               5 :             if (service_name[0] != '\0') {
     260               5 :                 GDALWMSMiniDriverManager *const mdm = GetGDALWMSMiniDriverManager();
     261               5 :                 GDALWMSMiniDriverFactory *const mdf = mdm->Find(CPLString(service_name));
     262               5 :                 if (mdf != NULL) {
     263               5 :                     m_mini_driver = mdf->New();
     264               5 :                     m_mini_driver->m_parent_dataset = this;
     265               5 :                     if (m_mini_driver->Initialize(service_node) == CE_None) {
     266               5 :                         m_mini_driver_caps.m_capabilities_version = -1;
     267               5 :                         m_mini_driver->GetCapabilities(&m_mini_driver_caps);
     268               5 :                         if (m_mini_driver_caps.m_capabilities_version == -1) {
     269               0 :                             CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Internal error, mini-driver capabilities version not set.");
     270               0 :                             ret = CE_Failure;
     271                 :                         }
     272                 :                     } else {
     273               0 :                         delete m_mini_driver;
     274               0 :                         m_mini_driver = NULL;
     275                 : 
     276               0 :                         CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Failed to initialize minidriver.");
     277               0 :                         ret = CE_Failure;
     278                 :                     }
     279                 :                 } else {
     280               0 :                     CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: No mini-driver registered for '%s'.", service_name);
     281               0 :                     ret = CE_Failure;
     282                 :                 }
     283                 :             } else {
     284               0 :                 CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: No Service specified.");
     285               0 :                 ret = CE_Failure;
     286                 :             }
     287                 :         } else {
     288               0 :             CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: No Service specified.");
     289               0 :             ret = CE_Failure;
     290                 :         }
     291                 :     }
     292               5 :     if (ret == CE_None) {
     293               5 :         nRasterXSize = m_data_window.m_sx;
     294               5 :         nRasterYSize = m_data_window.m_sy;
     295                 : 
     296               5 :         if (!GDALCheckDatasetDimensions(nRasterXSize, nRasterYSize) ||
     297                 :             !GDALCheckBandCount(nBandCount, TRUE))
     298                 :         {
     299               0 :             return CE_Failure;
     300                 :         }
     301                 : 
     302              20 :         for (int i = 0; i < nBandCount; ++i) {
     303              15 :             GDALWMSRasterBand *band = new GDALWMSRasterBand(this, i, 1.0);
     304              15 :             SetBand(i + 1, band);
     305              15 :             double scale = 0.5;
     306             222 :             for (int j = 0; j < m_overview_count; ++j) {
     307             207 :                 band->AddOverview(scale);
     308             207 :                 scale *= 0.5;
     309                 :             }
     310                 :         }
     311                 :     }
     312                 : 
     313               5 :     if (ret == CE_None) {
     314                 :         /* If we dont have projection already set ask mini-driver. */
     315               5 :         if (!m_projection.size()) {
     316               0 :             const char *proj = m_mini_driver->GetProjectionInWKT();
     317               0 :             if (proj != NULL) {
     318               0 :                 m_projection = proj;
     319                 :             }
     320                 :         }
     321                 :     }
     322                 : 
     323               5 :     return ret;
     324                 : }
     325                 : 
     326               0 : CPLErr GDALWMSDataset::IRasterIO(GDALRWFlag rw, int x0, int y0, int sx, int sy, void *buffer, int bsx, int bsy, GDALDataType bdt, int band_count, int *band_map, int pixel_space, int line_space, int band_space) {
     327                 :     CPLErr ret;
     328                 : 
     329               0 :     if (rw != GF_Read) return CE_Failure;
     330               0 :     if (buffer == NULL) return CE_Failure;
     331               0 :     if ((sx == 0) || (sy == 0) || (bsx == 0) || (bsy == 0) || (band_count == 0)) return CE_None;
     332                 : 
     333               0 :     m_hint.m_x0 = x0;
     334               0 :     m_hint.m_y0 = y0;
     335               0 :     m_hint.m_sx = sx;
     336               0 :     m_hint.m_sy = sy;
     337               0 :     m_hint.m_overview = -1;
     338               0 :     m_hint.m_valid = true;
     339                 :     //  printf("[%p] GDALWMSDataset::IRasterIO(x0: %d, y0: %d, sx: %d, sy: %d, bsx: %d, bsy: %d, band_count: %d, band_map: %p)\n", this, x0, y0, sx, sy, bsx, bsy, band_count, band_map);
     340               0 :     ret = GDALDataset::IRasterIO(rw, x0, y0, sx, sy, buffer, bsx, bsy, bdt, band_count, band_map, pixel_space, line_space, band_space);
     341               0 :     m_hint.m_valid = false;
     342                 : 
     343               0 :     return ret;
     344                 : }
     345                 : 
     346               1 : const char *GDALWMSDataset::GetProjectionRef() {
     347               1 :     return m_projection.c_str();
     348                 : }
     349                 : 
     350               0 : CPLErr GDALWMSDataset::SetProjection(const char *proj) {
     351               0 :     return CE_Failure;
     352                 : }
     353                 : 
     354               1 : CPLErr GDALWMSDataset::GetGeoTransform(double *gt) {
     355               1 :     gt[0] = m_data_window.m_x0;
     356               1 :     gt[1] = (m_data_window.m_x1 - m_data_window.m_x0) / static_cast<double>(m_data_window.m_sx);
     357               1 :     gt[2] = 0.0;
     358               1 :     gt[3] = m_data_window.m_y0;
     359               1 :     gt[4] = 0.0;
     360               1 :     gt[5] = (m_data_window.m_y1 - m_data_window.m_y0) / static_cast<double>(m_data_window.m_sy);
     361               1 :     return CE_None;
     362                 : }
     363                 : 
     364               0 : CPLErr GDALWMSDataset::SetGeoTransform(double *gt) {
     365               0 :     return CE_Failure;
     366                 : }
     367                 : 
     368               4 : const GDALWMSDataWindow *GDALWMSDataset::WMSGetDataWindow() const {
     369               4 :     return &m_data_window;
     370                 : }
     371                 : 
     372               0 : int GDALWMSDataset::WMSGetBlockSizeX() const {
     373               0 :     return m_block_size_x;
     374                 : }
     375                 : 
     376               0 : int GDALWMSDataset::WMSGetBlockSizeY() const {
     377               0 :     return m_block_size_y;
     378                 : }
     379                 : 
     380               0 : CPLErr GDALWMSDataset::AdviseRead(int x0, int y0, int sx, int sy, int bsx, int bsy, GDALDataType bdt, int band_count, int *band_map, char **options) {
     381                 : //    printf("AdviseRead(%d, %d, %d, %d)\n", x0, y0, sx, sy);
     382               0 :     if (m_offline_mode || !m_use_advise_read) return CE_None;
     383               0 :     if (m_cache == NULL) return CE_Failure;
     384                 : 
     385               0 :     GDALRasterBand *band = GetRasterBand(1);
     386               0 :     if (band == NULL) return CE_Failure;
     387               0 :     return band->AdviseRead(x0, y0, sx, sy, bsx, bsy, bdt, options);
     388                 : }

Generated by: LCOV version 1.7