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

Generated by: LCOV version 1.14