LCOV - code coverage report
Current view: directory - frmts/wms - rasterband.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 388 215 55.4 %
Date: 2011-12-18 Functions: 20 12 60.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: rasterband.cpp 23192 2011-10-06 20:31:54Z 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             440 : GDALWMSRasterBand::GDALWMSRasterBand(GDALWMSDataset *parent_dataset, int band, double scale) {
      34                 :     //  printf("[%p] GDALWMSRasterBand::GDALWMSRasterBand(%p, %d, %f)\n", this, parent_dataset, band, scale);
      35             440 :     m_parent_dataset = parent_dataset;
      36             440 :     m_scale = scale;
      37             440 :     m_overview = -1;
      38             440 :     m_color_interp = GCI_Undefined;
      39                 : 
      40             440 :     poDS = parent_dataset;
      41             440 :     nRasterXSize = static_cast<int>(m_parent_dataset->m_data_window.m_sx * scale + 0.5);
      42             440 :     nRasterYSize = static_cast<int>(m_parent_dataset->m_data_window.m_sy * scale + 0.5);
      43             440 :     nBand = band;
      44             440 :     eDataType = m_parent_dataset->m_data_type;
      45             440 :     nBlockXSize = m_parent_dataset->m_block_size_x;
      46             440 :     nBlockYSize = m_parent_dataset->m_block_size_y;
      47             440 : }
      48                 : 
      49             440 : GDALWMSRasterBand::~GDALWMSRasterBand() {
      50             855 :     for (std::vector<GDALWMSRasterBand *>::iterator it = m_overviews.begin(); it != m_overviews.end(); ++it) {
      51             415 :         GDALWMSRasterBand *p = *it;
      52             415 :         delete p;
      53                 :     }
      54             440 : }
      55                 : 
      56               2 : CPLErr GDALWMSRasterBand::ReadBlocks(int x, int y, void *buffer, int bx0, int by0, int bx1, int by1, int advise_read) {
      57               2 :     CPLErr ret = CE_None;
      58                 :     int i;
      59                 : 
      60               2 :     int max_request_count = (bx1 - bx0 + 1) * (by1 - by0 + 1);
      61               2 :     int request_count = 0;
      62               2 :     CPLHTTPRequest *download_requests = NULL;
      63               2 :     GDALWMSCache *cache = m_parent_dataset->m_cache;
      64                 :     struct BlockXY {
      65                 :         int x, y;
      66               2 :     } *download_blocks = NULL;
      67               2 :     if (!m_parent_dataset->m_offline_mode) {
      68               2 :         download_requests = new CPLHTTPRequest[max_request_count];
      69               2 :         download_blocks = new BlockXY[max_request_count];
      70                 :     }
      71                 : 
      72               2 :     char **http_request_opts = NULL;
      73               2 :     if (m_parent_dataset->m_http_timeout != -1) {
      74               2 :   CPLString http_request_optstr;
      75               2 :         http_request_optstr.Printf("TIMEOUT=%d", m_parent_dataset->m_http_timeout);
      76               2 :         http_request_opts = CSLAddString(http_request_opts, http_request_optstr.c_str());
      77                 :     }
      78                 : 
      79               2 :     if (m_parent_dataset->m_osUserAgent.size() != 0)
      80                 :     {
      81               0 :         CPLString osUserAgentOptStr("USERAGENT=");
      82               0 :         osUserAgentOptStr += m_parent_dataset->m_osUserAgent;
      83               0 :         http_request_opts = CSLAddString(http_request_opts, osUserAgentOptStr.c_str());
      84                 :     }
      85               2 :     if (m_parent_dataset->m_osReferer.size() != 0)
      86                 :     {
      87               0 :         CPLString osRefererOptStr("REFERER=");
      88               0 :         osRefererOptStr += m_parent_dataset->m_osReferer;
      89               0 :         http_request_opts = CSLAddString(http_request_opts, osRefererOptStr.c_str());
      90                 :     }
      91               2 :     if (m_parent_dataset->m_unsafeSsl >= 1) {
      92               0 :         http_request_opts = CSLAddString(http_request_opts, "UNSAFESSL=1");
      93                 :     }
      94                 : 
      95               4 :     for (int iy = by0; iy <= by1; ++iy) {
      96               5 :         for (int ix = bx0; ix <= bx1; ++ix) {
      97               3 :             bool need_this_block = false;
      98               3 :             if (!advise_read) {
      99               8 :                 for (int ib = 1; ib <= m_parent_dataset->nBands; ++ib) {
     100               7 :                     if ((ix == x) && (iy == y) && (ib == nBand)) {
     101               2 :                         need_this_block = true;
     102                 :                     } else {
     103               3 :                         GDALWMSRasterBand *band = static_cast<GDALWMSRasterBand *>(m_parent_dataset->GetRasterBand(ib));
     104               3 :                         if (m_overview >= 0) band = static_cast<GDALWMSRasterBand *>(band->GetOverview(m_overview));
     105               3 :                         if (!band->IsBlockInCache(ix, iy)) need_this_block = true;
     106                 :                     }
     107                 :                 }
     108                 :             } else {
     109               0 :                 need_this_block = true;
     110                 :             }
     111               3 :             CPLString url;
     112               3 :             if (need_this_block) {
     113               3 :                 CPLString file_name;
     114               3 :                 AskMiniDriverForBlock(&url, ix, iy);
     115               3 :                 if ((cache != NULL) && (cache->Read(url.c_str(), &file_name) == CE_None)) {
     116               0 :                     if (advise_read) {
     117               0 :                         need_this_block = false;
     118                 :                     } else {
     119               0 :                         void *p = 0;
     120               0 :                         if ((ix == x) && (iy == y)) p = buffer;
     121               0 :                         if (ReadBlockFromFile(ix, iy, file_name.c_str(), nBand, p, 0) == CE_None) need_this_block = false;
     122                 :                     }
     123               3 :                 }
     124                 :             }
     125               3 :             if (need_this_block) {
     126               3 :                 if (m_parent_dataset->m_offline_mode) {
     127               0 :                     if (!advise_read) {
     128               0 :                         void *p = 0;
     129               0 :                         if ((ix == x) && (iy == y)) p = buffer;
     130               0 :                         if (ZeroBlock(ix, iy, nBand, p) != CE_None) {
     131               0 :                             CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: ZeroBlock failed.");
     132               0 :                             ret = CE_Failure;
     133                 :                         }
     134                 :                     }
     135                 :                 } else {
     136               3 :                     CPLHTTPInitializeRequest(&download_requests[request_count], url.c_str(), http_request_opts);
     137               3 :                     download_blocks[request_count].x = ix;
     138               3 :                     download_blocks[request_count].y = iy;
     139               3 :                     ++request_count;
     140                 :                 }
     141                 :             }
     142                 :         }
     143                 :     }
     144               2 :     if (http_request_opts != NULL) {
     145               2 :         CSLDestroy(http_request_opts);
     146                 :     }
     147                 : 
     148               2 :     if (request_count > 0) {
     149               2 :         char **opts = NULL;
     150               2 :         CPLString optstr;
     151               2 :         if (m_parent_dataset->m_http_max_conn != -1) {
     152               2 :             optstr.Printf("MAXCONN=%d", m_parent_dataset->m_http_max_conn);
     153               2 :             opts = CSLAddString(opts, optstr.c_str());
     154                 :         }
     155               2 :         if (CPLHTTPFetchMulti(download_requests, request_count, opts) != CE_None) {
     156               0 :             CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: CPLHTTPFetchMulti failed.");
     157               0 :             ret = CE_Failure;
     158                 :         }
     159               2 :         if (opts != NULL) {
     160               2 :             CSLDestroy(opts);
     161               2 :         }
     162                 :     }
     163                 : 
     164               5 :     for (i = 0; i < request_count; ++i) {
     165               3 :         if (ret == CE_None) {
     166               6 :             if ((download_requests[i].nStatus == 200) && (download_requests[i].pabyData != NULL) && (download_requests[i].nDataLen > 0)) {
     167               3 :                 CPLString file_name(BufferToVSIFile(download_requests[i].pabyData, download_requests[i].nDataLen));
     168               3 :                 if (file_name.size() > 0) {
     169               3 :                     bool wms_exception = false;
     170                 :                     /* check for error xml */
     171               3 :                     if (download_requests[i].nDataLen >= 20) {
     172               3 :                         const char *download_data = reinterpret_cast<char *>(download_requests[i].pabyData);
     173               3 :                         if (EQUALN(download_data, "<?xml ", 6) 
     174                 :                         || EQUALN(download_data, "<!DOCTYPE ", 10)
     175                 :                         || EQUALN(download_data, "<ServiceException", 17)) {
     176               0 :                             if (ReportWMSException(file_name.c_str()) != CE_None) {
     177               0 :                                 CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: The server returned unknown exception.");
     178                 :                             }
     179               0 :                             wms_exception = true;
     180               0 :                             ret = CE_Failure;
     181                 :                         }
     182                 :                     }
     183               3 :                     if (ret == CE_None) {
     184               3 :                         if (advise_read && !m_parent_dataset->m_verify_advise_read) {
     185               0 :                             if (cache != NULL) {
     186               0 :                                 cache->Write(download_requests[i].pszURL, file_name);
     187                 :                             }
     188                 :                         } else {
     189               3 :                             void *p = 0;
     190               3 :                             if ((download_blocks[i].x == x) && (download_blocks[i].y == y)) p = buffer;
     191               3 :                             if (ReadBlockFromFile(download_blocks[i].x, download_blocks[i].y, file_name.c_str(), nBand, p, advise_read) == CE_None) {
     192               3 :                                 if (cache != NULL) {
     193               0 :                                     cache->Write(download_requests[i].pszURL, file_name);
     194                 :                                 }
     195                 :                             } else {
     196                 :                                 CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: ReadBlockFromFile (%s) failed.",
     197               0 :                                          download_requests[i].pszURL);
     198               0 :                                 ret = CE_Failure;
     199                 :                             }
     200                 :                         }
     201               0 :                     } else if( wms_exception && m_parent_dataset->m_zeroblock_on_serverexceptions ) {
     202               0 :                          void *p = 0;
     203               0 :                          if ((download_blocks[i].x == x) && (download_blocks[i].y == y)) p = buffer;
     204               0 :                          if (ZeroBlock(download_blocks[i].x, download_blocks[i].y, nBand, p) != CE_None) {
     205               0 :                              CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: ZeroBlock failed.");
     206                 :                          } else {
     207               0 :                              ret = CE_None;
     208                 :                          }
     209                 : 
     210                 :                     }
     211               3 :                     VSIUnlink(file_name.c_str());
     212               3 :                 }
     213                 :             } else {
     214                 :                std::vector<int>::iterator zero_it = std::find(
     215                 :                      m_parent_dataset->m_http_zeroblock_codes.begin(),
     216                 :                      m_parent_dataset->m_http_zeroblock_codes.end(),
     217               0 :                      download_requests[i].nStatus);
     218               0 :                if ( zero_it != m_parent_dataset->m_http_zeroblock_codes.end() ) {
     219               0 :                     if (!advise_read) {
     220               0 :                         void *p = 0;
     221               0 :                         if ((download_blocks[i].x == x) && (download_blocks[i].y == y)) p = buffer;
     222               0 :                         if (ZeroBlock(download_blocks[i].x, download_blocks[i].y, nBand, p) != CE_None) {
     223               0 :                             CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: ZeroBlock failed.");
     224               0 :                             ret = CE_Failure;
     225                 :                         }
     226                 :                     }
     227                 :                 } else {
     228                 :                     CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Unable to download block %d, %d.\n  URL: %s\n  HTTP status code: %d, error: %s.",
     229               0 :                         download_blocks[i].x, download_blocks[i].y, download_requests[i].pszURL, download_requests[i].nStatus, 
     230               0 :         download_requests[i].pszError ? download_requests[i].pszError : "(null)");
     231               0 :                     ret = CE_Failure;
     232                 :                 }
     233                 :             }
     234                 :         }
     235               3 :         CPLHTTPCleanupRequest(&download_requests[i]);
     236                 :     }
     237               2 :     if (!m_parent_dataset->m_offline_mode) {
     238               2 :         delete[] download_blocks;
     239               2 :         delete[] download_requests;
     240                 :     }
     241                 : 
     242               2 :     return ret;
     243                 : }
     244                 : 
     245               2 : CPLErr GDALWMSRasterBand::IReadBlock(int x, int y, void *buffer) {
     246               2 :     int bx0 = x;
     247               2 :     int by0 = y;
     248               2 :     int bx1 = x;
     249               2 :     int by1 = y;
     250                 : 
     251               2 :     if ((m_parent_dataset->m_hint.m_valid) && (m_parent_dataset->m_hint.m_overview == m_overview)) {
     252               2 :         int tbx0 = m_parent_dataset->m_hint.m_x0 / nBlockXSize;
     253               2 :         int tby0 = m_parent_dataset->m_hint.m_y0 / nBlockYSize;
     254               2 :         int tbx1 = (m_parent_dataset->m_hint.m_x0 + m_parent_dataset->m_hint.m_sx - 1) / nBlockXSize;
     255               2 :         int tby1 = (m_parent_dataset->m_hint.m_y0 + m_parent_dataset->m_hint.m_sy - 1) / nBlockYSize;
     256               2 :         if ((tbx0 <= bx0) && (tby0 <= by0) && (tbx1 >= bx1) && (tby1 >= by1)) {
     257               2 :             bx0 = tbx0;
     258               2 :             by0 = tby0;
     259               2 :             bx1 = tbx1;
     260               2 :             by1 = tby1;
     261                 :         }
     262                 :     }
     263                 : 
     264               2 :     CPLErr eErr = ReadBlocks(x, y, buffer, bx0, by0, bx1, by1, 0);
     265                 : 
     266               2 :     if ((m_parent_dataset->m_hint.m_valid) && (m_parent_dataset->m_hint.m_overview == m_overview))
     267                 :     {
     268               2 :         m_parent_dataset->m_hint.m_valid = false;
     269                 :     }
     270                 : 
     271               2 :     return eErr;
     272                 : }
     273                 : 
     274             217 : CPLErr GDALWMSRasterBand::IRasterIO(GDALRWFlag rw, int x0, int y0, int sx, int sy, void *buffer, int bsx, int bsy, GDALDataType bdt, int pixel_space, int line_space) {
     275                 :     CPLErr ret;
     276                 : 
     277             217 :     if (rw != GF_Read) return CE_Failure;
     278             217 :     if (buffer == NULL) return CE_Failure;
     279             217 :     if ((sx == 0) || (sy == 0) || (bsx == 0) || (bsy == 0)) return CE_None;
     280                 : 
     281             217 :     m_parent_dataset->m_hint.m_x0 = x0;
     282             217 :     m_parent_dataset->m_hint.m_y0 = y0;
     283             217 :     m_parent_dataset->m_hint.m_sx = sx;
     284             217 :     m_parent_dataset->m_hint.m_sy = sy;
     285             217 :     m_parent_dataset->m_hint.m_overview = m_overview;
     286             217 :     m_parent_dataset->m_hint.m_valid = true;
     287             217 :     ret = GDALRasterBand::IRasterIO(rw, x0, y0, sx, sy, buffer, bsx, bsy, bdt, pixel_space, line_space);
     288             217 :     m_parent_dataset->m_hint.m_valid = false;
     289                 : 
     290             217 :     return ret;
     291                 : }
     292                 : 
     293               0 : int GDALWMSRasterBand::HasArbitraryOverviews() {
     294                 : //    return m_parent_dataset->m_mini_driver_caps.m_has_arb_overviews;
     295               0 :     return 0; // not implemented yet
     296                 : }
     297                 : 
     298               8 : int GDALWMSRasterBand::GetOverviewCount() {
     299               8 :     return m_overviews.size();
     300                 : }
     301                 : 
     302              70 : GDALRasterBand *GDALWMSRasterBand::GetOverview(int n) {
     303              70 :     if ((m_overviews.size() > 0) && (static_cast<size_t>(n) < m_overviews.size())) return m_overviews[n];
     304               0 :     else return NULL;
     305                 : }
     306                 : 
     307             415 : void GDALWMSRasterBand::AddOverview(double scale) {
     308             415 :     GDALWMSRasterBand *overview = new GDALWMSRasterBand(m_parent_dataset, nBand, scale);
     309             415 :     std::vector<GDALWMSRasterBand *>::iterator it = m_overviews.begin();
     310            3808 :     for (; it != m_overviews.end(); ++it) {
     311            3393 :         GDALWMSRasterBand *p = *it;
     312            3393 :         if (p->m_scale < scale) break;
     313                 :     }
     314             415 :     m_overviews.insert(it, overview);
     315             415 :     it = m_overviews.begin();
     316            4223 :     for (int i = 0; it != m_overviews.end(); ++it, ++i) {
     317            3808 :         GDALWMSRasterBand *p = *it;
     318            3808 :         p->m_overview = i;
     319                 :     }
     320             415 : }
     321                 : 
     322               6 : bool GDALWMSRasterBand::IsBlockInCache(int x, int y) {
     323               6 :     bool ret = false;
     324               6 :     GDALRasterBlock *b = TryGetLockedBlockRef(x, y);
     325               6 :     if (b != NULL) {
     326               0 :         ret = true;
     327               0 :         b->DropLock();
     328                 :     }
     329               6 :     return ret;
     330                 : }
     331                 : 
     332                 : 
     333                 : // This is the function that calculates the block coordinates for the fetch
     334               3 : void GDALWMSRasterBand::AskMiniDriverForBlock(CPLString *url, int x, int y) {
     335                 :     GDALWMSImageRequestInfo iri;
     336                 :     GDALWMSTiledImageRequestInfo tiri;
     337                 : 
     338               3 :     int x0 = MAX(0, x * nBlockXSize);
     339               3 :     int y0 = MAX(0, y * nBlockYSize);
     340               3 :     int x1 = MAX(0, (x + 1) * nBlockXSize);
     341               3 :     int y1 = MAX(0, (y + 1) * nBlockYSize);
     342               3 :     if (m_parent_dataset->m_clamp_requests) {
     343               1 :   x0 = MIN(x0, nRasterXSize);
     344               1 :   y0 = MIN(y0, nRasterYSize);
     345               1 :   x1 = MIN(x1, nRasterXSize);
     346               1 :   y1 = MIN(y1, nRasterYSize);
     347                 :     }
     348                 :     
     349               3 :     const double rx = (m_parent_dataset->m_data_window.m_x1 - m_parent_dataset->m_data_window.m_x0) / static_cast<double>(nRasterXSize);
     350               3 :     const double ry = (m_parent_dataset->m_data_window.m_y1 - m_parent_dataset->m_data_window.m_y0) / static_cast<double>(nRasterYSize);
     351                 :     /* Use different method for x0,y0 and x1,y1 to make sure calculated values are exact for corner requests */
     352               3 :     iri.m_x0 = x0 * rx + m_parent_dataset->m_data_window.m_x0;
     353               3 :     iri.m_y0 = y0 * ry + m_parent_dataset->m_data_window.m_y0;
     354               3 :     iri.m_x1 = m_parent_dataset->m_data_window.m_x1 - (nRasterXSize - x1) * rx;
     355               3 :     iri.m_y1 = m_parent_dataset->m_data_window.m_y1 - (nRasterYSize - y1) * ry;
     356               3 :     iri.m_sx = x1 - x0;
     357               3 :     iri.m_sy = y1 - y0;
     358                 : 
     359               3 :     int level = m_overview + 1;
     360               3 :     tiri.m_x = (m_parent_dataset->m_data_window.m_tx >> level) + x;
     361               3 :     tiri.m_y = (m_parent_dataset->m_data_window.m_ty >> level) + y;
     362               3 :     tiri.m_level = m_parent_dataset->m_data_window.m_tlevel - level;
     363                 : 
     364               3 :     m_parent_dataset->m_mini_driver->TiledImageRequest(url, iri, tiri);
     365               3 : }
     366                 : 
     367               3 : CPLErr GDALWMSRasterBand::ReadBlockFromFile(int x, int y, const char *file_name, int to_buffer_band, void *buffer, int advise_read) {
     368               3 :     CPLErr ret = CE_None;
     369               3 :     GDALDataset *ds = 0;
     370               3 :     GByte *color_table = NULL;
     371                 :     int i;
     372                 : 
     373                 :     //CPLDebug("WMS", "ReadBlockFromFile: to_buffer_band=%d, (x,y)=(%d, %d)", to_buffer_band, x, y);
     374                 : 
     375                 :     /* expected size */
     376               3 :     const int esx = MIN(MAX(0, (x + 1) * nBlockXSize), nRasterXSize) - MIN(MAX(0, x * nBlockXSize), nRasterXSize);
     377               3 :     const int esy = MIN(MAX(0, (y + 1) * nBlockYSize), nRasterYSize) - MIN(MAX(0, y * nBlockYSize), nRasterYSize);
     378               3 :     ds = reinterpret_cast<GDALDataset*>(GDALOpen(file_name, GA_ReadOnly));
     379               3 :     if (ds != NULL) {
     380               3 :         int sx = ds->GetRasterXSize();
     381               3 :         int sy = ds->GetRasterYSize();
     382               3 :         bool accepted_as_no_alpha = false;  // if the request is for 4 bands but the wms returns 3  
     383                 :         /* Allow bigger than expected so pre-tiled constant size images work on corners */
     384               3 :         if ((sx > nBlockXSize) || (sy > nBlockYSize) || (sx < esx) || (sy < esy)) {
     385                 :             CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Incorrect size %d x %d of downloaded block, expected %d x %d, max %d x %d.",
     386               0 :                 sx, sy, esx, esy, nBlockXSize, nBlockYSize);
     387               0 :             ret = CE_Failure;
     388                 :         }
     389               3 :         if (ret == CE_None) {
     390               3 :             int nDSRasterCount = ds->GetRasterCount();
     391               3 :             if (nDSRasterCount != m_parent_dataset->nBands) {
     392                 :                 /* Maybe its an image with color table */
     393               0 :                 bool accepted_as_ct = false;
     394               0 :                 if ((eDataType == GDT_Byte) && (ds->GetRasterCount() == 1)) {
     395               0 :                     GDALRasterBand *rb = ds->GetRasterBand(1);
     396               0 :                     if (rb->GetRasterDataType() == GDT_Byte) {
     397               0 :                         GDALColorTable *ct = rb->GetColorTable();
     398               0 :                         if (ct != NULL) {
     399               0 :                             accepted_as_ct = true;
     400               0 :                             if (!advise_read) {
     401               0 :                                 color_table = new GByte[256 * 4];
     402               0 :                                 const int count = MIN(256, ct->GetColorEntryCount());
     403               0 :                                 for (i = 0; i < count; ++i) {
     404                 :                                     GDALColorEntry ce;
     405               0 :                                     ct->GetColorEntryAsRGB(i, &ce);
     406               0 :                                     color_table[i] = static_cast<GByte>(ce.c1);
     407               0 :                                     color_table[i + 256] = static_cast<GByte>(ce.c2);
     408               0 :                                     color_table[i + 512] = static_cast<GByte>(ce.c3);
     409               0 :                                     color_table[i + 768] = static_cast<GByte>(ce.c4);
     410                 :                                 }
     411               0 :                                 for (i = count; i < 256; ++i) {
     412               0 :                                     color_table[i] = 0;
     413               0 :                                     color_table[i + 256] = 0;
     414               0 :                                     color_table[i + 512] = 0;
     415               0 :                                     color_table[i + 768] = 0;
     416                 :                                 }
     417                 :                             }
     418                 :                         }
     419                 :                     }
     420                 :                 }
     421                 : 
     422               0 :                 if (nDSRasterCount == 4 && m_parent_dataset->nBands == 3)
     423                 :                 {
     424                 :                     /* metacarta TMS service sometimes return a 4 band PNG instead of the expected 3 band... */
     425                 :                 }
     426               0 :                 else if (!accepted_as_ct) {
     427               0 :                    if (ds->GetRasterCount()==3 && m_parent_dataset->nBands == 4 && (eDataType == GDT_Byte))
     428                 :                    { // WMS returned a file with no alpha so we will fill the alpha band with "opaque" 
     429               0 :                       accepted_as_no_alpha = true;
     430                 :                    }
     431                 :                    else
     432                 :                    {
     433                 :                       CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Incorrect bands count %d in downloaded block, expected %d.",
     434               0 :                          nDSRasterCount, m_parent_dataset->nBands);
     435               0 :                       ret = CE_Failure;
     436                 :                    }
     437                 :                 }
     438                 :             }
     439                 :         }
     440               3 :         if (!advise_read) {
     441               8 :             for (int ib = 1; ib <= m_parent_dataset->nBands; ++ib) {
     442               5 :                 if (ret == CE_None) {
     443               5 :                     void *p = NULL;
     444               5 :                     GDALRasterBlock *b = NULL;
     445               7 :                     if ((buffer != NULL) && (ib == to_buffer_band)) {
     446               2 :                         p = buffer;
     447                 :                     } else {
     448               3 :                         GDALWMSRasterBand *band = static_cast<GDALWMSRasterBand *>(m_parent_dataset->GetRasterBand(ib));
     449               3 :                         if (m_overview >= 0) band = static_cast<GDALWMSRasterBand *>(band->GetOverview(m_overview));
     450               3 :                         if (!band->IsBlockInCache(x, y)) {
     451               3 :                             b = band->GetLockedBlockRef(x, y, true);
     452               3 :                             if (b != NULL) {
     453               3 :                                 p = b->GetDataRef();
     454               3 :                                 if (p == NULL) {
     455               0 :                                   CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: GetDataRef returned NULL.");
     456               0 :                                   ret = CE_Failure;
     457                 :                                 }
     458                 :                             }
     459                 :                         }
     460                 :                         else
     461                 :                         {
     462                 :                             //CPLDebug("WMS", "Band %d, block (x,y)=(%d, %d) already in cache", band->GetBand(), x, y);
     463                 :                         }
     464                 :                     }
     465               5 :                     if (p != NULL) {
     466               5 :                         int pixel_space = GDALGetDataTypeSize(eDataType) / 8;
     467               5 :                         int line_space = pixel_space * nBlockXSize;
     468               5 :                         if (color_table == NULL) {
     469               5 :                             if( ib <= ds->GetRasterCount()) {
     470               5 :         GDALDataType dt=eDataType;
     471                 :         // Get the data from the PNG as stored instead of converting, if the server asks for that
     472                 :                                 // TODO: This hack is from #3493 - not sure it really belongs here.
     473               5 :         if ((GDT_Int16==dt)&&(GDT_UInt16==ds->GetRasterBand(ib)->GetRasterDataType()))
     474               2 :             dt=GDT_UInt16;
     475               5 :         if (ds->RasterIO(GF_Read, 0, 0, sx, sy, p, sx, sy, dt, 1, &ib, pixel_space, line_space, 0) != CE_None) {
     476               0 :             CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: RasterIO failed on downloaded block.");
     477               0 :             ret = CE_Failure;
     478                 :         }
     479                 :                             }
     480                 :                             else
     481                 :                             {  // parent expects 4 bands but file only has 3 so generate a all "opaque" 4th band
     482               0 :                                if (accepted_as_no_alpha)
     483                 :                                {
     484                 :                                   // the file had 3 bands and we are reading band 4 (Alpha) so fill with 255 (no alpha)
     485               0 :                                   GByte *byte_buffer = reinterpret_cast<GByte *>(p);
     486               0 :                                   for (int y = 0; y < sy; ++y) {
     487               0 :                                      for (int x = 0; x < sx; ++x) {
     488               0 :                                         const int offset = x + y * line_space;
     489               0 :                                         byte_buffer[offset] = 255;  // fill with opaque
     490                 :                                      }
     491                 :                                   }
     492                 :                                }
     493                 :                                else
     494                 :                                {  // we should never get here because this case was caught above
     495                 :                                   CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Incorrect bands count %d in downloaded block, expected %d.",
     496               0 :                                      ds->GetRasterCount(), m_parent_dataset->nBands);
     497               0 :                                   ret = CE_Failure;
     498                 :                                }     
     499                 :                             }
     500               0 :                         } else if (ib <= 4) {
     501               0 :                             if (ds->RasterIO(GF_Read, 0, 0, sx, sy, p, sx, sy, eDataType, 1, NULL, pixel_space, line_space, 0) != CE_None) {
     502               0 :                                 CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: RasterIO failed on downloaded block.");
     503               0 :                                 ret = CE_Failure;
     504                 :                             }
     505               0 :                             if (ret == CE_None) {
     506               0 :                                 GByte *band_color_table = color_table + 256 * (ib - 1);
     507               0 :                                 GByte *byte_buffer = reinterpret_cast<GByte *>(p);
     508               0 :                                 for (int y = 0; y < sy; ++y) {
     509               0 :                                     for (int x = 0; x < sx; ++x) {
     510               0 :                                         const int offset = x + y * line_space;
     511               0 :                                         byte_buffer[offset] = band_color_table[byte_buffer[offset]];
     512                 :                                     }
     513                 :                                 }
     514                 :                             }
     515                 :                         } else {
     516               0 :                             CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Color table supports at most 4 components.");
     517               0 :                             ret = CE_Failure;
     518                 :                         }
     519                 :                     }
     520               5 :                     if (b != NULL) {
     521               3 :                         b->DropLock();
     522                 :                     }
     523                 :                 }
     524                 :             }
     525                 :         }
     526               3 :         GDALClose(ds);
     527                 :     } else {
     528               0 :         CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: Unable to open downloaded block.");
     529               0 :         ret = CE_Failure;
     530                 :     }
     531                 : 
     532               3 :     if (color_table != NULL) {
     533               0 :         delete[] color_table;
     534                 :     }
     535                 : 
     536               3 :     return ret;
     537                 : }
     538                 : 
     539               0 : CPLErr GDALWMSRasterBand::ZeroBlock(int x, int y, int to_buffer_band, void *buffer) {
     540               0 :     CPLErr ret = CE_None;
     541                 : 
     542               0 :     for (int ib = 1; ib <= m_parent_dataset->nBands; ++ib) {
     543               0 :         if (ret == CE_None) {
     544               0 :             void *p = NULL;
     545               0 :             GDALRasterBlock *b = NULL;
     546               0 :             if ((buffer != NULL) && (ib == to_buffer_band)) {
     547               0 :                 p = buffer;
     548                 :             } else {
     549               0 :                 GDALWMSRasterBand *band = static_cast<GDALWMSRasterBand *>(m_parent_dataset->GetRasterBand(ib));
     550               0 :                 if (m_overview >= 0) band = static_cast<GDALWMSRasterBand *>(band->GetOverview(m_overview));
     551               0 :                 if (!band->IsBlockInCache(x, y)) {
     552               0 :                     b = band->GetLockedBlockRef(x, y, true);
     553               0 :                     if (b != NULL) {
     554               0 :                         p = b->GetDataRef();
     555               0 :                         if (p == NULL) {
     556               0 :                           CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: GetDataRef returned NULL.");
     557               0 :                           ret = CE_Failure;
     558                 :                         }
     559                 :                     }
     560                 :                 }
     561                 :             }
     562               0 :             if (p != NULL) {
     563               0 :                 unsigned char *b = reinterpret_cast<unsigned char *>(p);
     564               0 :                 int block_size = nBlockXSize * nBlockYSize * (GDALGetDataTypeSize(eDataType) / 8);
     565               0 :                 for (int i = 0; i < block_size; ++i) b[i] = 0;
     566                 :             }
     567               0 :             if (b != NULL) {
     568               0 :                 b->DropLock();
     569                 :             }
     570                 :         }
     571                 :     }
     572                 : 
     573               0 :     return ret;
     574                 : }
     575                 : 
     576               0 : CPLErr GDALWMSRasterBand::ReportWMSException(const char *file_name) {
     577               0 :     CPLErr ret = CE_None;
     578               0 :     int reported_errors_count = 0;
     579                 : 
     580               0 :     CPLXMLNode *orig_root = CPLParseXMLFile(file_name);
     581               0 :     CPLXMLNode *root = orig_root;
     582               0 :     if (root != NULL) {
     583               0 :         root = CPLGetXMLNode(root, "=ServiceExceptionReport");
     584                 :     }
     585               0 :     if (root != NULL) {
     586               0 :         CPLXMLNode *n = CPLGetXMLNode(root, "ServiceException");
     587               0 :         while (n != NULL) {
     588               0 :             const char *exception = CPLGetXMLValue(n, "=ServiceException", "");
     589               0 :             const char *exception_code = CPLGetXMLValue(n, "=ServiceException.code", "");
     590               0 :             if (exception[0] != '\0') {
     591               0 :                 if (exception_code[0] != '\0') {
     592               0 :                     CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: The server returned exception code '%s': %s", exception_code, exception);
     593               0 :                     ++reported_errors_count;
     594                 :                 } else {
     595               0 :                     CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: The server returned exception: %s", exception);
     596               0 :                     ++reported_errors_count;
     597                 :                 }
     598               0 :             } else if (exception_code[0] != '\0') {
     599               0 :                 CPLError(CE_Failure, CPLE_AppDefined, "GDALWMS: The server returned exception code '%s'.", exception_code);
     600               0 :                 ++reported_errors_count;
     601                 :             }
     602                 : 
     603               0 :             n = n->psNext;
     604               0 :             if (n != NULL) {
     605               0 :                 n = CPLGetXMLNode(n, "=ServiceException");
     606                 :             }
     607                 :         }
     608                 :     } else {
     609               0 :         ret = CE_Failure;
     610                 :     }
     611               0 :     if (orig_root != NULL) {
     612               0 :         CPLDestroyXMLNode(orig_root);
     613                 :     }
     614                 : 
     615               0 :     if (reported_errors_count == 0) {
     616               0 :         ret = CE_Failure;
     617                 :     }
     618                 : 
     619               0 :     return ret;
     620                 : }
     621                 : 
     622                 : 
     623               0 : CPLErr GDALWMSRasterBand::AdviseRead(int x0, int y0, int sx, int sy, int bsx, int bsy, GDALDataType bdt, char **options) {
     624                 : //    printf("AdviseRead(%d, %d, %d, %d)\n", x0, y0, sx, sy);
     625               0 :     if (m_parent_dataset->m_offline_mode || !m_parent_dataset->m_use_advise_read) return CE_None;
     626               0 :     if (m_parent_dataset->m_cache == NULL) return CE_Failure;
     627                 : 
     628               0 :     int bx0 = x0 / nBlockXSize;
     629               0 :     int by0 = y0 / nBlockYSize;
     630               0 :     int bx1 = (x0 + sx - 1) / nBlockXSize;
     631               0 :     int by1 = (y0 + sy - 1) / nBlockYSize;
     632                 : 
     633               0 :     return ReadBlocks(0, 0, NULL, bx0, by0, bx1, by1, 1);
     634                 : }
     635                 : 
     636               0 : GDALColorInterp GDALWMSRasterBand::GetColorInterpretation() {
     637               0 :     return m_color_interp;
     638                 : }
     639                 : 
     640               4 : CPLErr GDALWMSRasterBand::SetColorInterpretation( GDALColorInterp eNewInterp )
     641                 : {
     642               4 :     m_color_interp = eNewInterp;
     643               4 :     return CE_None;
     644                 : }
     645                 : 

Generated by: LCOV version 1.7