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

Generated by: LCOV version 1.14