LCOV - code coverage report
Current view: top level - frmts/sdts - sdtsrasterreader.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 110 186 59.1 %
Date: 2024-05-04 12:52:34 Functions: 6 8 75.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  SDTS Translator
       4             :  * Purpose:  Implementation of SDTSRasterReader class.
       5             :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 1999, 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 "sdts_al.h"
      31             : 
      32             : #include <algorithm>
      33             : 
      34             : /************************************************************************/
      35             : /*                          SDTSRasterReader()                          */
      36             : /************************************************************************/
      37             : 
      38           2 : SDTSRasterReader::SDTSRasterReader()
      39             :     : nXSize(0), nYSize(0), nXBlockSize(0), nYBlockSize(0), nXStart(0),
      40           2 :       nYStart(0)
      41             : {
      42           2 :     strcpy(szINTR, "CE");
      43           2 :     memset(szModule, 0, sizeof(szModule));
      44           2 :     memset(adfTransform, 0, sizeof(adfTransform));
      45           2 :     memset(szFMT, 0, sizeof(szFMT));
      46           2 :     memset(szUNITS, 0, sizeof(szUNITS));
      47           2 :     memset(szLabel, 0, sizeof(szLabel));
      48           2 : }
      49             : 
      50             : /************************************************************************/
      51             : /*                             ~SDTSRasterReader()                     */
      52             : /************************************************************************/
      53             : 
      54           2 : SDTSRasterReader::~SDTSRasterReader()
      55             : {
      56           2 : }
      57             : 
      58             : /************************************************************************/
      59             : /*                               Close()                                */
      60             : /************************************************************************/
      61             : 
      62           0 : void SDTSRasterReader::Close()
      63             : 
      64             : {
      65           0 :     oDDFModule.Close();
      66           0 : }
      67             : 
      68             : /************************************************************************/
      69             : /*                                Open()                                */
      70             : /*                                                                      */
      71             : /*      Open the requested cell file, and collect required              */
      72             : /*      information.                                                    */
      73             : /************************************************************************/
      74             : 
      75           2 : int SDTSRasterReader::Open(SDTS_CATD *poCATD, SDTS_IREF *poIREF,
      76             :                            const char *pszModule)
      77             : 
      78             : {
      79           2 :     snprintf(szModule, sizeof(szModule), "%s", pszModule);
      80             : 
      81             :     /* ==================================================================== */
      82             :     /*      Search the LDEF module for the requested cell module.           */
      83             :     /* ==================================================================== */
      84             : 
      85             :     /* -------------------------------------------------------------------- */
      86             :     /*      Open the LDEF module, and report failure if it is missing.      */
      87             :     /* -------------------------------------------------------------------- */
      88           2 :     if (poCATD->GetModuleFilePath("LDEF") == nullptr)
      89             :     {
      90           0 :         CPLError(CE_Failure, CPLE_AppDefined,
      91             :                  "Can't find LDEF entry in CATD module ... "
      92             :                  "can't treat as raster.\n");
      93           0 :         return FALSE;
      94             :     }
      95             : 
      96           4 :     DDFModule oLDEF;
      97           2 :     if (!oLDEF.Open(poCATD->GetModuleFilePath("LDEF")))
      98           0 :         return FALSE;
      99             : 
     100             :     /* -------------------------------------------------------------------- */
     101             :     /*      Read each record, till we find what we want.                    */
     102             :     /* -------------------------------------------------------------------- */
     103           2 :     DDFRecord *poRecord = nullptr;
     104           2 :     while ((poRecord = oLDEF.ReadRecord()) != nullptr)
     105             :     {
     106             :         const char *pszCandidateModule =
     107           2 :             poRecord->GetStringSubfield("LDEF", 0, "CMNM", 0);
     108           2 :         if (pszCandidateModule == nullptr)
     109             :         {
     110           0 :             poRecord = nullptr;
     111           0 :             break;
     112             :         }
     113           2 :         if (EQUAL(pszCandidateModule, pszModule))
     114           2 :             break;
     115             :     }
     116             : 
     117           2 :     if (poRecord == nullptr)
     118             :     {
     119           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     120             :                  "Can't find module `%s' in LDEF file.\n", pszModule);
     121           0 :         return FALSE;
     122             :     }
     123             : 
     124             :     /* -------------------------------------------------------------------- */
     125             :     /*      Extract raster dimensions, and origin offset (0/1).             */
     126             :     /* -------------------------------------------------------------------- */
     127           2 :     nXSize = poRecord->GetIntSubfield("LDEF", 0, "NCOL", 0);
     128           2 :     nYSize = poRecord->GetIntSubfield("LDEF", 0, "NROW", 0);
     129             : 
     130           2 :     nXStart = poRecord->GetIntSubfield("LDEF", 0, "SOCI", 0);
     131           2 :     nYStart = poRecord->GetIntSubfield("LDEF", 0, "SORI", 0);
     132             : 
     133             :     /* -------------------------------------------------------------------- */
     134             :     /*      Get the point in the pixel that the origin defines.  We only    */
     135             :     /*      support top left and center.                                    */
     136             :     /* -------------------------------------------------------------------- */
     137           2 :     const char *pszINTR = poRecord->GetStringSubfield("LDEF", 0, "INTR", 0);
     138           2 :     if (pszINTR == nullptr)
     139             :     {
     140           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     141             :                  "Can't find INTR subfield of LDEF field");
     142           0 :         return FALSE;
     143             :     }
     144           2 :     snprintf(szINTR, sizeof(szINTR), "%s", pszINTR);
     145           2 :     if (EQUAL(szINTR, ""))
     146           0 :         snprintf(szINTR, sizeof(szINTR), "%s", "CE");
     147             : 
     148           2 :     if (!EQUAL(szINTR, "CE") && !EQUAL(szINTR, "TL"))
     149             :     {
     150           0 :         CPLError(CE_Warning, CPLE_AppDefined,
     151             :                  "Unsupported INTR value of `%s', assume CE.\n"
     152             :                  "Positions may be off by one pixel.\n",
     153           0 :                  szINTR);
     154           0 :         snprintf(szINTR, sizeof(szINTR), "%s", "CE");
     155             :     }
     156             : 
     157             :     /* -------------------------------------------------------------------- */
     158             :     /*      Record the LDEF record number we used so we can find the        */
     159             :     /*      corresponding RSDF record.                                      */
     160             :     /* -------------------------------------------------------------------- */
     161           2 :     int nLDEF_RCID = poRecord->GetIntSubfield("LDEF", 0, "RCID", 0);
     162             : 
     163           2 :     oLDEF.Close();
     164             : 
     165             :     /* ==================================================================== */
     166             :     /*      Search the RSDF module for the requested cell module.           */
     167             :     /* ==================================================================== */
     168             : 
     169             :     /* -------------------------------------------------------------------- */
     170             :     /*      Open the RSDF module, and report failure if it is missing.      */
     171             :     /* -------------------------------------------------------------------- */
     172           2 :     if (poCATD->GetModuleFilePath("RSDF") == nullptr)
     173             :     {
     174           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     175             :                  "Can't find RSDF entry in CATD module ... "
     176             :                  "can't treat as raster.\n");
     177           0 :         return FALSE;
     178             :     }
     179             : 
     180           4 :     DDFModule oRSDF;
     181           2 :     if (!oRSDF.Open(poCATD->GetModuleFilePath("RSDF")))
     182           0 :         return FALSE;
     183             : 
     184             :     /* -------------------------------------------------------------------- */
     185             :     /*      Read each record, till we find what we want.                    */
     186             :     /* -------------------------------------------------------------------- */
     187           2 :     while ((poRecord = oRSDF.ReadRecord()) != nullptr)
     188             :     {
     189           2 :         if (poRecord->GetIntSubfield("LYID", 0, "RCID", 0) == nLDEF_RCID)
     190           2 :             break;
     191             :     }
     192             : 
     193           2 :     if (poRecord == nullptr)
     194             :     {
     195           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     196             :                  "Can't find LDEF:%d record in RSDF file.\n", nLDEF_RCID);
     197           0 :         return FALSE;
     198             :     }
     199             : 
     200             :     /* -------------------------------------------------------------------- */
     201             :     /*      Establish the raster pixel/line to georef transformation.       */
     202             :     /* -------------------------------------------------------------------- */
     203             : 
     204           2 :     if (poRecord->FindField("SADR") == nullptr)
     205             :     {
     206           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     207             :                  "Can't find SADR field in RSDF record.\n");
     208           0 :         return FALSE;
     209             :     }
     210             : 
     211             :     double dfZ;
     212           2 :     poIREF->GetSADR(poRecord->FindField("SADR"), 1, adfTransform + 0,
     213           2 :                     adfTransform + 3, &dfZ);
     214             : 
     215           2 :     adfTransform[1] = poIREF->dfXRes;
     216           2 :     adfTransform[2] = 0.0;
     217           2 :     adfTransform[4] = 0.0;
     218           2 :     adfTransform[5] = -1 * poIREF->dfYRes;
     219             : 
     220             :     /* -------------------------------------------------------------------- */
     221             :     /*      If the origin is the center of the pixel, then shift it back    */
     222             :     /*      half a pixel to the top left of the top left.                   */
     223             :     /* -------------------------------------------------------------------- */
     224           2 :     if (EQUAL(szINTR, "CE"))
     225             :     {
     226           2 :         adfTransform[0] -= adfTransform[1] * 0.5;
     227           2 :         adfTransform[3] -= adfTransform[5] * 0.5;
     228             :     }
     229             : 
     230             :     /* -------------------------------------------------------------------- */
     231             :     /*      Verify some other assumptions.                                  */
     232             :     /* -------------------------------------------------------------------- */
     233           2 :     const char *pszString = poRecord->GetStringSubfield("RSDF", 0, "OBRP", 0);
     234           2 :     if (pszString == nullptr)
     235           0 :         pszString = "";
     236           2 :     if (!EQUAL(pszString, "G2"))
     237             :     {
     238           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     239             :                  "OBRP value of `%s' not expected 2D raster code (G2).\n",
     240             :                  pszString);
     241           0 :         return FALSE;
     242             :     }
     243             : 
     244           2 :     pszString = poRecord->GetStringSubfield("RSDF", 0, "SCOR", 0);
     245           2 :     if (pszString == nullptr)
     246           0 :         pszString = "";
     247           2 :     if (!EQUAL(pszString, "TL"))
     248             :     {
     249           0 :         CPLError(CE_Warning, CPLE_AppDefined,
     250             :                  "SCOR (origin) is `%s' instead of expected top left.\n"
     251             :                  "Georef coordinates will likely be incorrect.\n",
     252             :                  pszString);
     253             :     }
     254             : 
     255           2 :     oRSDF.Close();
     256             : 
     257             :     /* -------------------------------------------------------------------- */
     258             :     /*      For now we will assume that the block size is one scanline.     */
     259             :     /*      We will blow a gasket later while reading the cell file if      */
     260             :     /*      this isn't the case.                                            */
     261             :     /*                                                                      */
     262             :     /*      This isn't a very flexible raster implementation!               */
     263             :     /* -------------------------------------------------------------------- */
     264           2 :     nXBlockSize = nXSize;
     265           2 :     nYBlockSize = 1;
     266             : 
     267             :     /* ==================================================================== */
     268             :     /*      Fetch the data type used for the raster, and the units from     */
     269             :     /*      the data dictionary/schema record (DDSH).                       */
     270             :     /* ==================================================================== */
     271             : 
     272             :     /* -------------------------------------------------------------------- */
     273             :     /*      Open the DDSH module, and report failure if it is missing.      */
     274             :     /* -------------------------------------------------------------------- */
     275           2 :     if (poCATD->GetModuleFilePath("DDSH") == nullptr)
     276             :     {
     277           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     278             :                  "Can't find DDSH entry in CATD module ... "
     279             :                  "can't treat as raster.\n");
     280           0 :         return FALSE;
     281             :     }
     282             : 
     283           4 :     DDFModule oDDSH;
     284           2 :     if (!oDDSH.Open(poCATD->GetModuleFilePath("DDSH")))
     285           0 :         return FALSE;
     286             : 
     287             :     /* -------------------------------------------------------------------- */
     288             :     /*      Read each record, till we find what we want.                    */
     289             :     /* -------------------------------------------------------------------- */
     290           2 :     while ((poRecord = oDDSH.ReadRecord()) != nullptr)
     291             :     {
     292           2 :         const char *pszName = poRecord->GetStringSubfield("DDSH", 0, "NAME", 0);
     293           2 :         if (pszName == nullptr)
     294             :         {
     295           0 :             poRecord = nullptr;
     296           0 :             break;
     297             :         }
     298           2 :         if (EQUAL(pszName, pszModule))
     299           2 :             break;
     300             :     }
     301             : 
     302           2 :     if (poRecord == nullptr)
     303             :     {
     304           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     305             :                  "Can't find DDSH record for %s.\n", pszModule);
     306           0 :         return FALSE;
     307             :     }
     308             : 
     309             :     /* -------------------------------------------------------------------- */
     310             :     /*      Get some values we are interested in.                           */
     311             :     /* -------------------------------------------------------------------- */
     312           2 :     if (poRecord->GetStringSubfield("DDSH", 0, "FMT", 0) != nullptr)
     313           2 :         snprintf(szFMT, sizeof(szFMT), "%s",
     314             :                  poRecord->GetStringSubfield("DDSH", 0, "FMT", 0));
     315             :     else
     316           0 :         snprintf(szFMT, sizeof(szFMT), "%s", "BI16");
     317           2 :     if (!EQUAL(szFMT, "BI16") && !EQUAL(szFMT, "BFP32"))
     318             :     {
     319           0 :         CPLError(CE_Failure, CPLE_AppDefined, "Unhandled FMT=%s", szFMT);
     320           0 :         return FALSE;
     321             :     }
     322             : 
     323           2 :     if (poRecord->GetStringSubfield("DDSH", 0, "UNIT", 0) != nullptr)
     324           2 :         snprintf(szUNITS, sizeof(szUNITS), "%s",
     325             :                  poRecord->GetStringSubfield("DDSH", 0, "UNIT", 0));
     326             :     else
     327           0 :         snprintf(szUNITS, sizeof(szUNITS), "%s", "METERS");
     328             : 
     329           2 :     if (poRecord->GetStringSubfield("DDSH", 0, "ATLB", 0) != nullptr)
     330           2 :         snprintf(szLabel, sizeof(szLabel), "%s",
     331             :                  poRecord->GetStringSubfield("DDSH", 0, "ATLB", 0));
     332             :     else
     333           0 :         strcpy(szLabel, "");
     334             : 
     335             :     /* -------------------------------------------------------------------- */
     336             :     /*      Open the cell file.                                             */
     337             :     /* -------------------------------------------------------------------- */
     338           2 :     return oDDFModule.Open(poCATD->GetModuleFilePath(pszModule));
     339             : }
     340             : 
     341             : /************************************************************************/
     342             : /*                              GetBlock()                              */
     343             : /*                                                                      */
     344             : /*      Read a requested block of raster data from the file.            */
     345             : /*                                                                      */
     346             : /*      Currently we will always use sequential access.  In the         */
     347             : /*      future we should modify the iso8211 library to support          */
     348             : /*      seeking, and modify this to seek directly to the right          */
     349             : /*      record once its location is known.                              */
     350             : /************************************************************************/
     351             : 
     352             : /**
     353             :   Read a block of raster data from the file.
     354             : 
     355             :   @param nXOffset X block offset into the file.  Normally zero for scanline
     356             :   organized raster files.
     357             : 
     358             :   @param nYOffset Y block offset into the file.  Normally the scanline offset
     359             :   from top of raster for scanline organized raster files.
     360             : 
     361             :   @param pData pointer to GInt16 (signed short) buffer of data into which to
     362             :   read the raster.
     363             : 
     364             :   @return TRUE on success and FALSE on error.
     365             : 
     366             :   */
     367             : 
     368          25 : int SDTSRasterReader::GetBlock(CPL_UNUSED int nXOffset, int nYOffset,
     369             :                                void *pData)
     370             : {
     371          25 :     CPLAssert(nXOffset == 0);
     372             : 
     373             :     /* -------------------------------------------------------------------- */
     374             :     /*      Analyse the datatype.                                           */
     375             :     /* -------------------------------------------------------------------- */
     376          25 :     CPLAssert(EQUAL(szFMT, "BI16") || EQUAL(szFMT, "BFP32"));
     377             : 
     378             :     int nBytesPerValue;
     379          25 :     if (EQUAL(szFMT, "BI16"))
     380          25 :         nBytesPerValue = 2;
     381             :     else
     382           0 :         nBytesPerValue = 4;
     383             : 
     384          25 :     DDFRecord *poRecord = nullptr;
     385             : 
     386          25 :     for (int iTry = 0; iTry < 2; iTry++)
     387             :     {
     388             :         /* --------------------------------------------------------------------
     389             :          */
     390             :         /*      Read through till we find the desired record. */
     391             :         /* --------------------------------------------------------------------
     392             :          */
     393          25 :         CPLErrorReset();
     394          25 :         while ((poRecord = oDDFModule.ReadRecord()) != nullptr)
     395             :         {
     396          25 :             if (poRecord->GetIntSubfield("CELL", 0, "ROWI", 0) ==
     397          25 :                 nYOffset + nYStart)
     398             :             {
     399          25 :                 break;
     400             :             }
     401             :         }
     402             : 
     403          25 :         if (CPLGetLastErrorType() == CE_Failure)
     404           0 :             return FALSE;
     405             : 
     406             :         /* --------------------------------------------------------------------
     407             :          */
     408             :         /*      If we didn't get what we needed just start over. */
     409             :         /* --------------------------------------------------------------------
     410             :          */
     411          25 :         if (poRecord == nullptr)
     412             :         {
     413           0 :             if (iTry == 0)
     414           0 :                 oDDFModule.Rewind();
     415             :             else
     416             :             {
     417           0 :                 CPLError(CE_Failure, CPLE_AppDefined,
     418             :                          "Cannot read scanline %d.  Raster access failed.\n",
     419             :                          nYOffset);
     420           0 :                 return FALSE;
     421             :             }
     422             :         }
     423             :         else
     424             :         {
     425          25 :             break;
     426             :         }
     427             :     }
     428             : 
     429             :     /* -------------------------------------------------------------------- */
     430             :     /*      Validate the records size.  Does it represent exactly one       */
     431             :     /*      scanline?                                                       */
     432             :     /* -------------------------------------------------------------------- */
     433          25 :     DDFField *poCVLS = poRecord->FindField("CVLS");
     434          25 :     if (poCVLS == nullptr)
     435           0 :         return FALSE;
     436             : 
     437          25 :     if (poCVLS->GetRepeatCount() != nXSize)
     438             :     {
     439           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     440             :                  "Cell record is %d long, but we expected %d, the number\n"
     441             :                  "of pixels in a scanline.  Raster access failed.\n",
     442             :                  poCVLS->GetRepeatCount(), nXSize);
     443           0 :         return FALSE;
     444             :     }
     445             : 
     446             :     /* -------------------------------------------------------------------- */
     447             :     /*      Does the CVLS field consist of exactly 1 B(16) field?           */
     448             :     /* -------------------------------------------------------------------- */
     449          50 :     if (poCVLS->GetDataSize() < nBytesPerValue * nXSize ||
     450          25 :         poCVLS->GetDataSize() > nBytesPerValue * nXSize + 1)
     451             :     {
     452           0 :         CPLError(CE_Failure, CPLE_AppDefined,
     453             :                  "Cell record is not of expected format.  Raster access "
     454             :                  "failed.\n");
     455             : 
     456           0 :         return FALSE;
     457             :     }
     458             : 
     459             :     /* -------------------------------------------------------------------- */
     460             :     /*      Copy the data to the application buffer, and byte swap if       */
     461             :     /*      required.                                                       */
     462             :     /* -------------------------------------------------------------------- */
     463          50 :     memcpy(pData, poCVLS->GetData(),
     464          25 :            static_cast<size_t>(nXSize) * nBytesPerValue);
     465             : 
     466             : #ifdef CPL_LSB
     467          25 :     if (nBytesPerValue == 2)
     468             :     {
     469        8500 :         for (int i = 0; i < nXSize; i++)
     470             :         {
     471        8475 :             reinterpret_cast<GInt16 *>(pData)[i] =
     472        8475 :                 CPL_MSBWORD16(reinterpret_cast<GInt16 *>(pData)[i]);
     473             :         }
     474             :     }
     475             :     else
     476             :     {
     477           0 :         for (int i = 0; i < nXSize; i++)
     478             :         {
     479           0 :             CPL_MSBPTR32(reinterpret_cast<GByte *>(pData) + i * 4);
     480             :         }
     481             :     }
     482             : #endif
     483             : 
     484          25 :     return TRUE;
     485             : }
     486             : 
     487             : /************************************************************************/
     488             : /*                            GetTransform()                            */
     489             : /************************************************************************/
     490             : 
     491             : /**
     492             :   Fetch the transformation between pixel/line coordinates and georeferenced
     493             :   coordinates.
     494             : 
     495             :   @param padfTransformOut pointer to an array of six doubles which will be
     496             :   filled with the georeferencing transform.
     497             : 
     498             :   @return TRUE is returned, indicating success.
     499             : 
     500             :   The padfTransformOut array consists of six values.  The pixel/line coordinate
     501             :   (Xp,Yp) can be related to a georeferenced coordinate (Xg,Yg) or (Easting,
     502             :   Northing).
     503             : 
     504             :   <pre>
     505             :   Xg = padfTransformOut[0] + Xp * padfTransform[1] + Yp * padfTransform[2]
     506             :   Yg = padfTransformOut[3] + Xp * padfTransform[4] + Yp * padfTransform[5]
     507             :   </pre>
     508             : 
     509             :   In other words, for a north up image the top left corner of the top left
     510             :   pixel is at georeferenced coordinate (padfTransform[0],padfTransform[3])
     511             :   the pixel width is padfTransform[1], the pixel height is padfTransform[5]
     512             :   and padfTransform[2] and padfTransform[4] will be zero.
     513             : 
     514             :   */
     515             : 
     516           1 : int SDTSRasterReader::GetTransform(double *padfTransformOut)
     517             : 
     518             : {
     519           1 :     memcpy(padfTransformOut, adfTransform, sizeof(double) * 6);
     520             : 
     521           1 :     return TRUE;
     522             : }
     523             : 
     524             : /************************************************************************/
     525             : /*                           GetRasterType()                            */
     526             : /************************************************************************/
     527             : 
     528             : /**
     529             :  * Fetch the pixel data type.
     530             :  *
     531             :  * Returns one of SDTS_RT_INT16 (1) or SDTS_RT_FLOAT32 (6) indicating the
     532             :  * type of buffer that should be passed to GetBlock().
     533             :  */
     534             : 
     535           2 : int SDTSRasterReader::GetRasterType()
     536             : 
     537             : {
     538           2 :     if (EQUAL(szFMT, "BFP32"))
     539           0 :         return SDTS_RT_FLOAT32;
     540             : 
     541           2 :     return SDTS_RT_INT16;
     542             : }
     543             : 
     544             : /************************************************************************/
     545             : /*                             GetMinMax()                              */
     546             : /************************************************************************/
     547             : 
     548             : /**
     549             :  * Fetch the minimum and maximum raster values that occur in the file.
     550             :  *
     551             :  * Note this operation current results in a scan of the entire file.
     552             :  *
     553             :  * @param pdfMin variable in which the minimum value encountered is returned.
     554             :  * @param pdfMax variable in which the maximum value encountered is returned.
     555             :  * @param dfNoData a value to ignore when computing min/max, defaults to
     556             :  * -32766.
     557             :  *
     558             :  * @return TRUE on success, or FALSE if an error occurs.
     559             :  */
     560             : 
     561           0 : int SDTSRasterReader::GetMinMax(double *pdfMin, double *pdfMax, double dfNoData)
     562             : 
     563             : {
     564           0 :     CPLAssert(GetBlockXSize() == GetXSize() && GetBlockYSize() == 1);
     565             : 
     566           0 :     bool bFirst = true;
     567           0 :     const bool b32Bit = GetRasterType() == SDTS_RT_FLOAT32;
     568           0 :     void *pBuffer = CPLMalloc(sizeof(float) * GetXSize());
     569             : 
     570           0 :     for (int iLine = 0; iLine < GetYSize(); iLine++)
     571             :     {
     572           0 :         if (!GetBlock(0, iLine, pBuffer))
     573             :         {
     574           0 :             CPLFree(pBuffer);
     575           0 :             return FALSE;
     576             :         }
     577             : 
     578           0 :         for (int iPixel = 0; iPixel < GetXSize(); iPixel++)
     579             :         {
     580             :             double dfValue;
     581             : 
     582           0 :             if (b32Bit)
     583           0 :                 dfValue = reinterpret_cast<float *>(pBuffer)[iPixel];
     584             :             else
     585           0 :                 dfValue = reinterpret_cast<short *>(pBuffer)[iPixel];
     586             : 
     587           0 :             if (dfValue != dfNoData)
     588             :             {
     589           0 :                 if (bFirst)
     590             :                 {
     591           0 :                     *pdfMin = dfValue;
     592           0 :                     *pdfMax = dfValue;
     593           0 :                     bFirst = false;
     594             :                 }
     595             :                 else
     596             :                 {
     597           0 :                     *pdfMin = std::min(*pdfMin, dfValue);
     598           0 :                     *pdfMax = std::max(*pdfMax, dfValue);
     599             :                 }
     600             :             }
     601             :         }
     602             :     }
     603             : 
     604           0 :     CPLFree(pBuffer);
     605             : 
     606           0 :     return !bFirst;
     607             : }

Generated by: LCOV version 1.14