LCOV - code coverage report
Current view: top level - frmts/wcs - wcsrasterband.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 83 113 73.5 %
Date: 2024-05-04 12:52:34 Functions: 7 8 87.5 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  WCS Client Driver
       4             :  * Purpose:  Implementation of RasterBand classes for WCS.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2006, Frank Warmerdam
       9             :  * Copyright (c) 2008-2013, Even Rouault <even dot rouault at spatialys.com>
      10             :  *
      11             :  * Permission is hereby granted, free of charge, to any person obtaining a
      12             :  * copy of this software and associated documentation files (the "Software"),
      13             :  * to deal in the Software without restriction, including without limitation
      14             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15             :  * and/or sell copies of the Software, and to permit persons to whom the
      16             :  * Software is furnished to do so, subject to the following conditions:
      17             :  *
      18             :  * The above copyright notice and this permission notice shall be included
      19             :  * in all copies or substantial portions of the Software.
      20             :  *
      21             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27             :  * DEALINGS IN THE SOFTWARE.
      28             :  ****************************************************************************/
      29             : 
      30             : #include "cpl_http.h"
      31             : #include "gdal_pam.h"
      32             : 
      33             : #include <algorithm>
      34             : 
      35             : #include "wcsdataset.h"
      36             : #include "wcsrasterband.h"
      37             : 
      38             : /************************************************************************/
      39             : /*                           WCSRasterBand()                            */
      40             : /************************************************************************/
      41             : 
      42         765 : WCSRasterBand::WCSRasterBand(WCSDataset *poDSIn, int nBandIn, int iOverviewIn)
      43             :     : iOverview(iOverviewIn),
      44         765 :       nResFactor(1 << (iOverviewIn + 1)),  // iOverview == -1 is base layer
      45         765 :       poODS(poDSIn), nOverviewCount(0), papoOverviews(nullptr)
      46             : {
      47         765 :     poDS = poDSIn;
      48         765 :     nBand = nBandIn;
      49             : 
      50         765 :     eDataType = GDALGetDataTypeByName(
      51         765 :         CPLGetXMLValue(poDSIn->psService, "BandType", "Byte"));
      52             : 
      53             :     /* -------------------------------------------------------------------- */
      54             :     /*      Establish resolution reduction for this overview level.         */
      55             :     /* -------------------------------------------------------------------- */
      56             : 
      57             :     /* -------------------------------------------------------------------- */
      58             :     /*      Establish block size.                                           */
      59             :     /* -------------------------------------------------------------------- */
      60         765 :     nRasterXSize = poDS->GetRasterXSize() / nResFactor;
      61         765 :     nRasterYSize = poDS->GetRasterYSize() / nResFactor;
      62             : 
      63         765 :     nBlockXSize = atoi(CPLGetXMLValue(poDSIn->psService, "BlockXSize", "0"));
      64         765 :     nBlockYSize = atoi(CPLGetXMLValue(poDSIn->psService, "BlockYSize", "0"));
      65             : 
      66         765 :     if (nBlockXSize < 1)
      67             :     {
      68         765 :         if (nRasterXSize > 1800)
      69         417 :             nBlockXSize = 1024;
      70             :         else
      71         348 :             nBlockXSize = nRasterXSize;
      72             :     }
      73             : 
      74         765 :     if (nBlockYSize < 1)
      75             :     {
      76         765 :         if (nRasterYSize > 900)
      77         621 :             nBlockYSize = 512;
      78             :         else
      79         144 :             nBlockYSize = nRasterYSize;
      80             :     }
      81             : 
      82             :     /* -------------------------------------------------------------------- */
      83             :     /*      If this is the base layer, create the overview layers.          */
      84             :     /* -------------------------------------------------------------------- */
      85         765 :     if (iOverview == -1)
      86             :     {
      87         135 :         nOverviewCount =
      88         135 :             atoi(CPLGetXMLValue(poODS->psService, "OverviewCount", "-1"));
      89         135 :         if (nOverviewCount < 0)
      90             :         {
      91         765 :             for (nOverviewCount = 0; (std::max(nRasterXSize, nRasterYSize) /
      92         765 :                                       (1 << nOverviewCount)) > 900;
      93         630 :                  nOverviewCount++)
      94             :             {
      95             :             }
      96             :         }
      97           0 :         else if (nOverviewCount > 30)
      98             :         {
      99             :             /* There's no reason to have more than 30 overviews, because */
     100             :             /* 2^(30+1) overflows a int32 */
     101           0 :             nOverviewCount = 30;
     102             :         }
     103             : 
     104         135 :         papoOverviews =
     105         135 :             (WCSRasterBand **)CPLCalloc(nOverviewCount, sizeof(void *));
     106             : 
     107         765 :         for (int i = 0; i < nOverviewCount; i++)
     108         630 :             papoOverviews[i] = new WCSRasterBand(poODS, nBand, i);
     109             :     }
     110         765 : }
     111             : 
     112             : /************************************************************************/
     113             : /*                           ~WCSRasterBand()                           */
     114             : /************************************************************************/
     115             : 
     116        1530 : WCSRasterBand::~WCSRasterBand()
     117             : 
     118             : {
     119         765 :     FlushCache(true);
     120             : 
     121         765 :     if (nOverviewCount > 0)
     122             :     {
     123         759 :         for (int i = 0; i < nOverviewCount; i++)
     124         630 :             delete papoOverviews[i];
     125             : 
     126         129 :         CPLFree(papoOverviews);
     127             :     }
     128        1530 : }
     129             : 
     130             : /************************************************************************/
     131             : /*                             IReadBlock()                             */
     132             : /************************************************************************/
     133             : 
     134          24 : CPLErr WCSRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage)
     135             : 
     136             : {
     137             :     CPLErr eErr;
     138          24 :     CPLHTTPResult *psResult = nullptr;
     139             : 
     140             :     // if INTERLEAVE is set to PIXEL, then we'll request all bands.
     141             :     // That is necessary at least with MapServer, which seems to often
     142             :     // return all bands instead of requested.
     143             :     // todo: in 2.0.1 the band list in this dataset may be user-defined
     144             : 
     145          24 :     int band_count = 1;
     146          24 :     if (EQUAL(CPLGetXMLValue(poODS->psService, "INTERLEAVE", ""), "PIXEL"))
     147             :     {
     148          24 :         band_count = 0;
     149             :     }
     150             : 
     151          48 :     eErr = poODS->GetCoverage(
     152          24 :         nBlockXOff * nBlockXSize * nResFactor,
     153          24 :         nBlockYOff * nBlockYSize * nResFactor, nBlockXSize * nResFactor,
     154          24 :         nBlockYSize * nResFactor, nBlockXSize, nBlockYSize, band_count, &nBand,
     155             :         nullptr, &psResult);
     156          24 :     if (eErr != CE_None)
     157           0 :         return eErr;
     158             : 
     159             :     /* -------------------------------------------------------------------- */
     160             :     /*      Try and open result as a dataset.                               */
     161             :     /* -------------------------------------------------------------------- */
     162          24 :     GDALDataset *poTileDS = poODS->GDALOpenResult(psResult);
     163             : 
     164          24 :     if (poTileDS == nullptr)
     165           0 :         return CE_Failure;
     166             : 
     167             :     /* -------------------------------------------------------------------- */
     168             :     /*      Verify configuration.                                           */
     169             :     /* -------------------------------------------------------------------- */
     170          48 :     if (poTileDS->GetRasterXSize() != nBlockXSize ||
     171          24 :         poTileDS->GetRasterYSize() != nBlockYSize)
     172             :     {
     173           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     174             :                  "Returned tile does not match expected configuration.\n"
     175             :                  "Got %dx%d instead of %dx%d.",
     176             :                  poTileDS->GetRasterXSize(), poTileDS->GetRasterYSize(),
     177             :                  nBlockXSize, nBlockYSize);
     178           0 :         delete poTileDS;
     179           0 :         return CE_Failure;
     180             :     }
     181             : 
     182          24 :     if (band_count == 1 &&
     183           0 :         ((!poODS->osBandIdentifier.empty() &&
     184           0 :           poTileDS->GetRasterCount() != 1) ||
     185           0 :          (poODS->osBandIdentifier.empty() &&
     186           0 :           poTileDS->GetRasterCount() != poODS->GetRasterCount())))
     187             :     {
     188           0 :         CPLString msg;
     189           0 :         if (!poODS->osBandIdentifier.empty() && poTileDS->GetRasterCount() != 1)
     190             :         {
     191             :             msg.Printf("Got %d bands instead of one although the coverage has "
     192             :                        "band range type.\n",
     193           0 :                        poTileDS->GetRasterCount());
     194             :         }
     195             :         else
     196             :         {
     197             :             msg.Printf(
     198             :                 "Response has %d bands while this dataset has %d bands.\n",
     199           0 :                 poTileDS->GetRasterCount(), poODS->GetRasterCount());
     200             :         }
     201           0 :         CPLError(
     202             :             CE_Failure, CPLE_AppDefined,
     203             :             "Returned tile does not match expected band configuration.\n%s",
     204             :             msg.c_str());
     205           0 :         delete poTileDS;
     206           0 :         return CE_Failure;
     207             :     }
     208             : 
     209             :     /* -------------------------------------------------------------------- */
     210             :     /*      Process all bands of memory result, copying into pBuffer, or    */
     211             :     /*      pushing into cache for other bands.                             */
     212             :     /* -------------------------------------------------------------------- */
     213             :     int iBand;
     214          24 :     eErr = CE_None;
     215             : 
     216          69 :     for (iBand = 0; iBand < poTileDS->GetRasterCount() && eErr == CE_None;
     217             :          iBand++)
     218             :     {
     219          45 :         GDALRasterBand *poTileBand = poTileDS->GetRasterBand(iBand + 1);
     220             : 
     221          45 :         if (iBand + 1 == GetBand() ||
     222           0 :             (band_count == 1 && !poODS->osBandIdentifier.empty()))
     223             :         {
     224          24 :             eErr = poTileBand->RasterIO(GF_Read, 0, 0, nBlockXSize, nBlockYSize,
     225             :                                         pImage, nBlockXSize, nBlockYSize,
     226             :                                         eDataType, 0, 0, nullptr);
     227             :         }
     228             :         else
     229             :         {
     230          21 :             GDALRasterBand *poTargBand = poODS->GetRasterBand(iBand + 1);
     231             : 
     232          21 :             if (iOverview != -1)
     233           0 :                 poTargBand = poTargBand->GetOverview(iOverview);
     234             : 
     235             :             GDALRasterBlock *poBlock =
     236          21 :                 poTargBand->GetLockedBlockRef(nBlockXOff, nBlockYOff, TRUE);
     237             : 
     238          21 :             if (poBlock != nullptr)
     239             :             {
     240          21 :                 eErr = poTileBand->RasterIO(GF_Read, 0, 0, nBlockXSize,
     241             :                                             nBlockYSize, poBlock->GetDataRef(),
     242             :                                             nBlockXSize, nBlockYSize, eDataType,
     243             :                                             0, 0, nullptr);
     244          21 :                 poBlock->DropLock();
     245             :             }
     246             :             else
     247           0 :                 eErr = CE_Failure;
     248             :         }
     249             :     }
     250             : 
     251             :     /* -------------------------------------------------------------------- */
     252             :     /*      Cleanup                                                         */
     253             :     /* -------------------------------------------------------------------- */
     254          24 :     delete poTileDS;
     255             : 
     256          24 :     poODS->FlushMemoryResult();
     257             : 
     258          24 :     return eErr;
     259             : }
     260             : 
     261             : /************************************************************************/
     262             : /*                             IRasterIO()                              */
     263             : /************************************************************************/
     264             : 
     265          45 : CPLErr WCSRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
     266             :                                 int nXSize, int nYSize, void *pData,
     267             :                                 int nBufXSize, int nBufYSize,
     268             :                                 GDALDataType eBufType, GSpacing nPixelSpace,
     269             :                                 GSpacing nLineSpace,
     270             :                                 GDALRasterIOExtraArg *psExtraArg)
     271             : 
     272             : {
     273          45 :     if ((poODS->nMaxCols > 0 && poODS->nMaxCols < nBufXSize) ||
     274          45 :         (poODS->nMaxRows > 0 && poODS->nMaxRows < nBufYSize))
     275           0 :         return CE_Failure;
     276             : 
     277          45 :     if (poODS->TestUseBlockIO(nXOff, nYOff, nXSize, nYSize, nBufXSize,
     278          45 :                               nBufYSize))
     279          45 :         return GDALPamRasterBand::IRasterIO(
     280             :             eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
     281          45 :             eBufType, nPixelSpace, nLineSpace, psExtraArg);
     282             :     else
     283           0 :         return poODS->DirectRasterIO(eRWFlag, nXOff * nResFactor,
     284           0 :                                      nYOff * nResFactor, nXSize * nResFactor,
     285           0 :                                      nYSize * nResFactor, pData, nBufXSize,
     286             :                                      nBufYSize, eBufType, 1, &nBand,
     287           0 :                                      nPixelSpace, nLineSpace, 0, psExtraArg);
     288             : }
     289             : 
     290             : /************************************************************************/
     291             : /*                           GetNoDataValue()                           */
     292             : /************************************************************************/
     293             : 
     294         210 : double WCSRasterBand::GetNoDataValue(int *pbSuccess)
     295             : 
     296             : {
     297             :     const char *pszSV =
     298         210 :         CPLGetXMLValue(poODS->psService, "NoDataValue", nullptr);
     299             : 
     300         210 :     if (pszSV == nullptr)
     301          96 :         return GDALPamRasterBand::GetNoDataValue(pbSuccess);
     302             :     else
     303             :     {
     304         114 :         if (pbSuccess)
     305          84 :             *pbSuccess = TRUE;
     306         114 :         return CPLAtof(pszSV);
     307             :     }
     308             : }
     309             : 
     310             : /************************************************************************/
     311             : /*                          GetOverviewCount()                          */
     312             : /************************************************************************/
     313             : 
     314          96 : int WCSRasterBand::GetOverviewCount()
     315             : 
     316             : {
     317          96 :     return nOverviewCount;
     318             : }
     319             : 
     320             : /************************************************************************/
     321             : /*                            GetOverview()                             */
     322             : /************************************************************************/
     323             : 
     324           0 : GDALRasterBand *WCSRasterBand::GetOverview(int iOverviewIn)
     325             : 
     326             : {
     327           0 :     if (iOverviewIn < 0 || iOverviewIn >= nOverviewCount)
     328           0 :         return nullptr;
     329             :     else
     330           0 :         return papoOverviews[iOverviewIn];
     331             : }

Generated by: LCOV version 1.14