LCOV - code coverage report
Current view: top level - frmts/wcs - wcsrasterband.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 89 115 77.4 %
Date: 2026-03-25 17:52:11 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             :  * SPDX-License-Identifier: MIT
      12             :  ****************************************************************************/
      13             : 
      14             : #include "cpl_http.h"
      15             : #include "gdal_pam.h"
      16             : #include "gdal_rasterblock.h"
      17             : 
      18             : #include <algorithm>
      19             : #include <cassert>
      20             : 
      21             : #include "wcsdataset.h"
      22             : #include "wcsrasterband.h"
      23             : 
      24             : /************************************************************************/
      25             : /*                           WCSRasterBand()                            */
      26             : /************************************************************************/
      27             : 
      28         765 : WCSRasterBand::WCSRasterBand(WCSDataset *poDSIn, int nBandIn, int iOverviewIn)
      29             :     : iOverview(iOverviewIn),
      30         765 :       nResFactor(1 << (iOverviewIn + 1)),  // iOverview == -1 is base layer
      31         765 :       poODS(poDSIn), nOverviewCount(0), papoOverviews(nullptr)
      32             : {
      33         765 :     poDS = poDSIn;
      34         765 :     nBand = nBandIn;
      35             : 
      36         765 :     eDataType = GDALGetDataTypeByName(
      37         765 :         CPLGetXMLValue(poDSIn->psService, "BandType", "Byte"));
      38             : 
      39             :     /* -------------------------------------------------------------------- */
      40             :     /*      Establish resolution reduction for this overview level.         */
      41             :     /* -------------------------------------------------------------------- */
      42             : 
      43             :     /* -------------------------------------------------------------------- */
      44             :     /*      Establish block size.                                           */
      45             :     /* -------------------------------------------------------------------- */
      46         765 :     nRasterXSize = poDS->GetRasterXSize() / nResFactor;
      47         765 :     nRasterYSize = poDS->GetRasterYSize() / nResFactor;
      48             : 
      49         765 :     nBlockXSize = atoi(CPLGetXMLValue(poDSIn->psService, "BlockXSize", "0"));
      50         765 :     nBlockYSize = atoi(CPLGetXMLValue(poDSIn->psService, "BlockYSize", "0"));
      51             : 
      52         765 :     if (nBlockXSize < 1)
      53             :     {
      54         765 :         if (nRasterXSize > 1800)
      55         417 :             nBlockXSize = 1024;
      56             :         else
      57         348 :             nBlockXSize = nRasterXSize;
      58             :     }
      59             : 
      60         765 :     if (nBlockYSize < 1)
      61             :     {
      62         765 :         if (nRasterYSize > 900)
      63         621 :             nBlockYSize = 512;
      64             :         else
      65         144 :             nBlockYSize = nRasterYSize;
      66             :     }
      67             : 
      68             :     /* -------------------------------------------------------------------- */
      69             :     /*      If this is the base layer, create the overview layers.          */
      70             :     /* -------------------------------------------------------------------- */
      71         765 :     if (iOverview == -1)
      72             :     {
      73         135 :         nOverviewCount =
      74         135 :             atoi(CPLGetXMLValue(poODS->psService, "OverviewCount", "-1"));
      75         135 :         if (nOverviewCount < 0)
      76             :         {
      77         765 :             for (nOverviewCount = 0; (std::max(nRasterXSize, nRasterYSize) /
      78         765 :                                       (1 << nOverviewCount)) > 900;
      79         630 :                  nOverviewCount++)
      80             :             {
      81             :             }
      82             :         }
      83           0 :         else if (nOverviewCount > 30)
      84             :         {
      85             :             /* There's no reason to have more than 30 overviews, because */
      86             :             /* 2^(30+1) overflows a int32 */
      87           0 :             nOverviewCount = 30;
      88             :         }
      89             : 
      90         135 :         papoOverviews =
      91         135 :             (WCSRasterBand **)CPLCalloc(nOverviewCount, sizeof(void *));
      92             : 
      93         765 :         for (int i = 0; i < nOverviewCount; i++)
      94         630 :             papoOverviews[i] = new WCSRasterBand(poODS, nBand, i);
      95             :     }
      96         765 : }
      97             : 
      98             : /************************************************************************/
      99             : /*                           ~WCSRasterBand()                           */
     100             : /************************************************************************/
     101             : 
     102        1530 : WCSRasterBand::~WCSRasterBand()
     103             : 
     104             : {
     105         765 :     FlushCache(true);
     106             : 
     107         765 :     if (nOverviewCount > 0)
     108             :     {
     109         759 :         for (int i = 0; i < nOverviewCount; i++)
     110         630 :             delete papoOverviews[i];
     111             : 
     112         129 :         CPLFree(papoOverviews);
     113             :     }
     114        1530 : }
     115             : 
     116             : /************************************************************************/
     117             : /*                             IReadBlock()                             */
     118             : /************************************************************************/
     119             : 
     120          24 : CPLErr WCSRasterBand::IReadBlock(int nBlockXOff, int nBlockYOff, void *pImage)
     121             : 
     122             : {
     123             :     CPLErr eErr;
     124          24 :     CPLHTTPResult *psResult = nullptr;
     125             : 
     126             :     // if INTERLEAVE is set to PIXEL, then we'll request all bands.
     127             :     // That is necessary at least with MapServer, which seems to often
     128             :     // return all bands instead of requested.
     129             :     // todo: in 2.0.1 the band list in this dataset may be user-defined
     130             : 
     131          24 :     int band_count = 1;
     132          24 :     if (EQUAL(CPLGetXMLValue(poODS->psService, "INTERLEAVE", ""), "PIXEL"))
     133             :     {
     134          24 :         band_count = 0;
     135             :     }
     136             : 
     137          48 :     eErr = poODS->GetCoverage(
     138          24 :         nBlockXOff * nBlockXSize * nResFactor,
     139          24 :         nBlockYOff * nBlockYSize * nResFactor, nBlockXSize * nResFactor,
     140          24 :         nBlockYSize * nResFactor, nBlockXSize, nBlockYSize, band_count, &nBand,
     141             :         nullptr, &psResult);
     142          24 :     if (eErr != CE_None)
     143           0 :         return eErr;
     144             : 
     145             :     /* -------------------------------------------------------------------- */
     146             :     /*      Try and open result as a dataset.                               */
     147             :     /* -------------------------------------------------------------------- */
     148          24 :     GDALDataset *poTileDS = poODS->GDALOpenResult(psResult);
     149             : 
     150          24 :     if (poTileDS == nullptr)
     151           0 :         return CE_Failure;
     152             : 
     153             :     /* -------------------------------------------------------------------- */
     154             :     /*      Verify configuration.                                           */
     155             :     /* -------------------------------------------------------------------- */
     156          48 :     if (poTileDS->GetRasterXSize() != nBlockXSize ||
     157          24 :         poTileDS->GetRasterYSize() != nBlockYSize)
     158             :     {
     159           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     160             :                  "Returned tile does not match expected configuration.\n"
     161             :                  "Got %dx%d instead of %dx%d.",
     162             :                  poTileDS->GetRasterXSize(), poTileDS->GetRasterYSize(),
     163             :                  nBlockXSize, nBlockYSize);
     164           0 :         delete poTileDS;
     165           0 :         return CE_Failure;
     166             :     }
     167             : 
     168          24 :     if (band_count == 1 &&
     169           0 :         ((!poODS->osBandIdentifier.empty() &&
     170           0 :           poTileDS->GetRasterCount() != 1) ||
     171           0 :          (poODS->osBandIdentifier.empty() &&
     172           0 :           poTileDS->GetRasterCount() != poODS->GetRasterCount())))
     173             :     {
     174           0 :         CPLString msg;
     175           0 :         if (!poODS->osBandIdentifier.empty() && poTileDS->GetRasterCount() != 1)
     176             :         {
     177             :             msg.Printf("Got %d bands instead of one although the coverage has "
     178             :                        "band range type.\n",
     179           0 :                        poTileDS->GetRasterCount());
     180             :         }
     181             :         else
     182             :         {
     183             :             msg.Printf(
     184             :                 "Response has %d bands while this dataset has %d bands.\n",
     185           0 :                 poTileDS->GetRasterCount(), poODS->GetRasterCount());
     186             :         }
     187           0 :         CPLError(
     188             :             CE_Failure, CPLE_AppDefined,
     189             :             "Returned tile does not match expected band configuration.\n%s",
     190             :             msg.c_str());
     191           0 :         delete poTileDS;
     192           0 :         return CE_Failure;
     193             :     }
     194             : 
     195             :     /* -------------------------------------------------------------------- */
     196             :     /*      Process all bands of memory result, copying into pBuffer, or    */
     197             :     /*      pushing into cache for other bands.                             */
     198             :     /* -------------------------------------------------------------------- */
     199             :     int iBand;
     200          24 :     eErr = CE_None;
     201             : 
     202          69 :     for (iBand = 0; iBand < poTileDS->GetRasterCount() && eErr == CE_None;
     203             :          iBand++)
     204             :     {
     205          45 :         GDALRasterBand *poTileBand = poTileDS->GetRasterBand(iBand + 1);
     206             : 
     207          45 :         if (iBand + 1 == GetBand() ||
     208           0 :             (band_count == 1 && !poODS->osBandIdentifier.empty()))
     209             :         {
     210          24 :             eErr = poTileBand->RasterIO(GF_Read, 0, 0, nBlockXSize, nBlockYSize,
     211             :                                         pImage, nBlockXSize, nBlockYSize,
     212             :                                         eDataType, 0, 0, nullptr);
     213             :         }
     214             :         else
     215             :         {
     216          21 :             GDALRasterBand *poTargBand = poODS->GetRasterBand(iBand + 1);
     217             : 
     218          21 :             if (iOverview != -1)
     219           0 :                 poTargBand = poTargBand->GetOverview(iOverview);
     220             : 
     221          21 :             assert(poTargBand);
     222             : #if defined(__GNUC__)
     223             : #pragma GCC diagnostic push
     224             : #pragma GCC diagnostic ignored "-Wnull-dereference"
     225             : #endif
     226             :             GDALRasterBlock *poBlock =
     227          21 :                 poTargBand->GetLockedBlockRef(nBlockXOff, nBlockYOff, TRUE);
     228             : #if defined(__GNUC__)
     229             : #pragma GCC diagnostic pop
     230             : #endif
     231             : 
     232          21 :             if (poBlock != nullptr)
     233             :             {
     234          21 :                 eErr = poTileBand->RasterIO(GF_Read, 0, 0, nBlockXSize,
     235             :                                             nBlockYSize, poBlock->GetDataRef(),
     236             :                                             nBlockXSize, nBlockYSize, eDataType,
     237             :                                             0, 0, nullptr);
     238          21 :                 poBlock->DropLock();
     239             :             }
     240             :             else
     241           0 :                 eErr = CE_Failure;
     242             :         }
     243             :     }
     244             : 
     245             :     /* -------------------------------------------------------------------- */
     246             :     /*      Cleanup                                                         */
     247             :     /* -------------------------------------------------------------------- */
     248          24 :     delete poTileDS;
     249             : 
     250          24 :     poODS->FlushMemoryResult();
     251             : 
     252          24 :     return eErr;
     253             : }
     254             : 
     255             : /************************************************************************/
     256             : /*                             IRasterIO()                              */
     257             : /************************************************************************/
     258             : 
     259          58 : CPLErr WCSRasterBand::IRasterIO(GDALRWFlag eRWFlag, int nXOff, int nYOff,
     260             :                                 int nXSize, int nYSize, void *pData,
     261             :                                 int nBufXSize, int nBufYSize,
     262             :                                 GDALDataType eBufType, GSpacing nPixelSpace,
     263             :                                 GSpacing nLineSpace,
     264             :                                 GDALRasterIOExtraArg *psExtraArg)
     265             : 
     266             : {
     267          58 :     if ((poODS->nMaxCols > 0 && poODS->nMaxCols < nBufXSize) ||
     268          58 :         (poODS->nMaxRows > 0 && poODS->nMaxRows < nBufYSize))
     269           0 :         return CE_Failure;
     270             : 
     271          58 :     if (poODS->TestUseBlockIO(nXOff, nYOff, nXSize, nYSize, nBufXSize,
     272          58 :                               nBufYSize))
     273          45 :         return GDALPamRasterBand::IRasterIO(
     274             :             eRWFlag, nXOff, nYOff, nXSize, nYSize, pData, nBufXSize, nBufYSize,
     275          45 :             eBufType, nPixelSpace, nLineSpace, psExtraArg);
     276             :     else
     277          26 :         return poODS->DirectRasterIO(eRWFlag, nXOff * nResFactor,
     278          13 :                                      nYOff * nResFactor, nXSize * nResFactor,
     279          13 :                                      nYSize * nResFactor, pData, nBufXSize,
     280          13 :                                      nBufYSize, eBufType, 1, &nBand,
     281          13 :                                      nPixelSpace, nLineSpace, 0, psExtraArg);
     282             : }
     283             : 
     284             : /************************************************************************/
     285             : /*                           GetNoDataValue()                           */
     286             : /************************************************************************/
     287             : 
     288         252 : double WCSRasterBand::GetNoDataValue(int *pbSuccess)
     289             : 
     290             : {
     291             :     const char *pszSV =
     292         252 :         CPLGetXMLValue(poODS->psService, "NoDataValue", nullptr);
     293             : 
     294         252 :     if (pszSV == nullptr)
     295          96 :         return GDALPamRasterBand::GetNoDataValue(pbSuccess);
     296             :     else
     297             :     {
     298         156 :         if (pbSuccess)
     299         126 :             *pbSuccess = TRUE;
     300         156 :         return CPLAtof(pszSV);
     301             :     }
     302             : }
     303             : 
     304             : /************************************************************************/
     305             : /*                          GetOverviewCount()                          */
     306             : /************************************************************************/
     307             : 
     308          96 : int WCSRasterBand::GetOverviewCount()
     309             : 
     310             : {
     311          96 :     return nOverviewCount;
     312             : }
     313             : 
     314             : /************************************************************************/
     315             : /*                            GetOverview()                             */
     316             : /************************************************************************/
     317             : 
     318           0 : GDALRasterBand *WCSRasterBand::GetOverview(int iOverviewIn)
     319             : 
     320             : {
     321           0 :     if (iOverviewIn < 0 || iOverviewIn >= nOverviewCount)
     322           0 :         return nullptr;
     323             :     else
     324           0 :         return papoOverviews[iOverviewIn];
     325             : }

Generated by: LCOV version 1.14