LCOV - code coverage report
Current view: top level - frmts/pcidsk/sdk/segment - cpcidsk_array.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 0 112 0.0 %
Date: 2025-06-28 21:28:23 Functions: 0 16 0.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Purpose:  Implementation of the CPCIDSK_TEX class.
       4             :  *
       5             :  ******************************************************************************
       6             :  * Copyright (c) 2010
       7             :  * PCI Geomatics, 90 Allstate Parkway, Markham, Ontario, Canada.
       8             :  *
       9             :  * SPDX-License-Identifier: MIT
      10             :  ****************************************************************************/
      11             : 
      12             : #include "pcidsk_exception.h"
      13             : #include "segment/cpcidsk_array.h"
      14             : #include "core/cpcidskfile.h"
      15             : #include <cstring>
      16             : #include <sstream>
      17             : #include <cassert>
      18             : #include "core/pcidsk_utils.h"
      19             : 
      20             : using namespace PCIDSK;
      21             : 
      22             : PCIDSK_ARRAY::~PCIDSK_ARRAY() = default;
      23             : 
      24             : /************************************************************************/
      25             : /*                            CPCIDSK_ARRAY()                           */
      26             : /************************************************************************/
      27             : 
      28           0 : CPCIDSK_ARRAY::CPCIDSK_ARRAY( PCIDSKFile *fileIn, int segmentIn,
      29           0 :                               const char *segment_pointer )
      30             :         : CPCIDSKSegment( fileIn, segmentIn, segment_pointer ),
      31           0 :         loaded_(false),mbModified(false)
      32             : {
      33           0 :     MAX_DIMENSIONS = 8;
      34           0 :     Load();
      35           0 : }
      36             : 
      37             : /************************************************************************/
      38             : /*                            ~CPCIDSK_ARRAY                            */
      39             : /************************************************************************/
      40             : 
      41           0 : CPCIDSK_ARRAY::~CPCIDSK_ARRAY()
      42             : 
      43             : {
      44           0 : }
      45             : 
      46             : /**
      47             :  * Load the contents of the segment
      48             :  */
      49           0 : void CPCIDSK_ARRAY::Load()
      50             : {
      51             :     // Check if we've already loaded the segment into memory
      52           0 :     if (loaded_) {
      53           0 :         return;
      54             :     }
      55             : 
      56           0 :     PCIDSKBuffer& seg_header = this->GetHeader();
      57           0 :     seg_data.SetSize(!IsContentSizeValid() ? -1 : // will throw exception
      58           0 :                      static_cast<int>(GetContentSize()));
      59           0 :     ReadFromFile(seg_data.buffer, 0, seg_data.buffer_size);
      60             : 
      61           0 :     if(!STARTS_WITH(seg_header.buffer+160, "64R     "))
      62             :     {
      63           0 :         seg_header.Put("64R     ",160,8);
      64           0 :         loaded_ = true;
      65           0 :         return ;
      66             :     }
      67             : 
      68           0 :     int nDimension = seg_header.GetInt(160+8,8);
      69           0 :     if(nDimension < 1 || nDimension > MAX_DIMENSIONS)
      70             :     {
      71           0 :         std::stringstream oStream;
      72           0 :         oStream << "Invalid array dimension " << nDimension;
      73           0 :         oStream << " stored in the segment.";
      74           0 :         std::string oMsg = oStream.str();
      75           0 :         return ThrowPCIDSKException("%s", oMsg.c_str());
      76             :     }
      77           0 :     mnDimension = static_cast<unsigned char>(nDimension);
      78             : 
      79           0 :     moSizes.clear();
      80           0 :     for( int i = 0; i < mnDimension; i++ )
      81             :     {
      82           0 :         int nSize = seg_header.GetInt(160+24 + i*8,8);
      83           0 :         if(nSize < 1)
      84             :         {
      85           0 :             std::stringstream oStream;
      86           0 :             oStream << "Invalid size " << nSize << " for dimension " << i+1;
      87           0 :             std::string oMsg = oStream.str();
      88           0 :             return ThrowPCIDSKException("%s", oMsg.c_str());
      89             :         }
      90           0 :         moSizes.push_back( nSize );
      91             :     }
      92             : 
      93             :     //calculate the total number of elements in the array.
      94           0 :     unsigned int nElements = 1;
      95           0 :     for(unsigned int i=0 ; i < moSizes.size() ; i++)
      96             :     {
      97           0 :         nElements *= moSizes[i];
      98             :     }
      99             : 
     100           0 :     moArray.resize(nElements);
     101           0 :     for( unsigned int i = 0; i < nElements; i++ )
     102             :     {
     103           0 :         const double* pdValue = (const double*)seg_data.Get(i*8,8);
     104             :         char uValue[8];
     105           0 :         std::memcpy(uValue,pdValue,8);
     106           0 :         SwapData(uValue,8,1);
     107           0 :         memcpy(&moArray[i], uValue, 8);
     108             :     }
     109             : 
     110             :     //PCIDSK doesn't have support for headers.
     111             : 
     112             :     // We've now loaded the structure up with data. Mark it as being loaded
     113             :     // properly.
     114           0 :     loaded_ = true;
     115             : 
     116             : }
     117             : 
     118             : /**
     119             :  * Write the segment on disk
     120             :  */
     121           0 : void CPCIDSK_ARRAY::Write(void)
     122             : {
     123             :     //We are not writing if nothing was loaded.
     124           0 :     if (!loaded_) {
     125           0 :         return;
     126             :     }
     127             : 
     128           0 :     PCIDSKBuffer& seg_header = this->GetHeader();
     129           0 :     int nBlocks = (static_cast<int>(moArray.size())*8 + 511)/512 ;
     130           0 :     unsigned int nSizeBuffer = (nBlocks)*512 ;
     131             :     //64 values can be put into 512 bytes.
     132           0 :     unsigned int nRest = nBlocks*64 - static_cast<unsigned int>(moArray.size());
     133             : 
     134           0 :     seg_data.SetSize(nSizeBuffer);
     135             : 
     136           0 :     seg_header.Put("64R     ",160,8);
     137           0 :     seg_header.Put((int)mnDimension,160+8,8);
     138             : 
     139           0 :     for( int i = 0; i < mnDimension; i++ )
     140             :     {
     141           0 :         int nSize = static_cast<int>(moSizes[i]);
     142           0 :         seg_header.Put(nSize,160+24 + i*8,8);
     143             :     }
     144             : 
     145           0 :     for( unsigned int i = 0; i < moArray.size(); i++ )
     146             :     {
     147           0 :         double dValue = moArray[i];
     148           0 :         SwapData(&dValue,8,1);
     149           0 :         seg_data.PutBin(dValue,i*8);
     150             :     }
     151             : 
     152             :     //set the end of the buffer to 0.
     153           0 :     for( unsigned int i=0 ; i < nRest ; i++)
     154             :     {
     155           0 :         seg_data.Put(0.0,(static_cast<int>(moArray.size())+i)*8,8,"%22.14f");
     156             :     }
     157             : 
     158           0 :     WriteToFile(seg_data.buffer,0,seg_data.buffer_size);
     159             : 
     160           0 :     mbModified = false;
     161             : }
     162             : 
     163             : /**
     164             :  * Synchronize the segment, if it was modified then
     165             :  * write it into disk.
     166             :  */
     167           0 : void CPCIDSK_ARRAY::Synchronize()
     168             : {
     169           0 :     if(mbModified)
     170             :     {
     171           0 :         this->Write();
     172             :         //write the modified header
     173           0 :         file->WriteToFile( header.buffer, data_offset, 1024 );
     174             :     }
     175           0 : }
     176             : 
     177             : /**
     178             :  * This function returns the number of dimension in the array.
     179             :  * an array segment can have minimum 1 dimension and maximum
     180             :  * 8 dimension.
     181             :  *
     182             :  * @return the dimension of the array in [1,8]
     183             :  */
     184           0 : unsigned char CPCIDSK_ARRAY::GetDimensionCount() const
     185             : {
     186           0 :     return mnDimension;
     187             : }
     188             : 
     189             : /**
     190             :  * This function set the dimension of the array. the dimension
     191             :  * must be in [1,8] or a pci::Exception is thrown.
     192             :  *
     193             :  * @param nDim number of dimension, should be in [1,8]
     194             :  */
     195           0 : void CPCIDSK_ARRAY::SetDimensionCount(unsigned char nDim)
     196             : {
     197           0 :     if( !file->GetUpdatable() )
     198           0 :         return ThrowPCIDSKException("File not open for update.");
     199           0 :     if(nDim < 1 || nDim > 8)
     200             :     {
     201           0 :         return ThrowPCIDSKException("An array cannot have a "
     202           0 :             "dimension bigger than 8 or smaller than 1.");
     203             :     }
     204           0 :     mnDimension = nDim;
     205           0 :     mbModified = true;
     206             : }
     207             : 
     208             : /**
     209             :  * Get the number of element that can be put in each of the dimension
     210             :  * of the array. the size of the return vector is GetDimensionCount().
     211             :  *
     212             :  * @return the size of each dimension.
     213             :  */
     214           0 : const std::vector<unsigned int>& CPCIDSK_ARRAY::GetSizes() const
     215             : {
     216           0 :     return moSizes;
     217             : }
     218             : 
     219             : /**
     220             :  * Set the size of each dimension. If the size of the array is bigger
     221             :  * or smaller than GetDimensionCount(), then a pci::Exception is thrown
     222             :  * if one of the sizes is 0, then a pci::Exception is thrown.
     223             :  *
     224             :  * @param oSizes the size of each dimension
     225             :  */
     226           0 : void CPCIDSK_ARRAY::SetSizes(const std::vector<unsigned int>& oSizes)
     227             : {
     228           0 :     if(oSizes.size() != GetDimensionCount())
     229             :     {
     230           0 :         return ThrowPCIDSKException("You need to specify the sizes"
     231           0 :             " for each dimension of the array");
     232             :     }
     233             : 
     234           0 :     for( unsigned int i=0 ; i < oSizes.size() ; i++)
     235             :     {
     236           0 :         if(oSizes[i] == 0)
     237             :         {
     238           0 :             return ThrowPCIDSKException("You cannot define the size of a dimension to 0.");
     239             :         }
     240             :     }
     241           0 :     moSizes = oSizes;
     242           0 :     mbModified = true;
     243             : }
     244             : 
     245             : /**
     246             :  * Get the array in a vector. the size of this vector is
     247             :  * GetSize()[0]*GetSize()[2]*...*GetSize()[GetDimensionCount()-1].
     248             :  * value are stored in the following order inside this vector:
     249             :  * ViDj = Value i of Dimension j
     250             :  * n = size of dimension 1
     251             :  * p = size of dimension 2
     252             :  * h = size of dimension k
     253             :  *
     254             :  * V1D1 ... VnD1 V1D2 ... VpD2 ... V1Dk ... VhDk
     255             :  *
     256             :  * @return the array.
     257             :  */
     258           0 : const std::vector<double>& CPCIDSK_ARRAY::GetArray() const
     259             : {
     260           0 :     return moArray;
     261             : }
     262             : 
     263             : /**
     264             :  * Set the array in the segment. the size of this vector is
     265             :  * GetSize()[0]*GetSize()[2]*...*GetSize()[GetDimensionCount()-1].
     266             :  * value are stored in the following order inside this vector:
     267             :  * ViDj = Value i of Dimension j
     268             :  * n = size of dimension 1
     269             :  * p = size of dimension 2
     270             :  * h = size of dimension k
     271             :  *
     272             :  * V1D1 ... VnD1 V1D2 ... VpD2 ... V1Dk ... VhDk
     273             :  *
     274             :  * If the size of oArray doesn't match the sizes and dimensions
     275             :  * then a pci::Exception is thrown.
     276             :  *
     277             :  * @param oArray the array.
     278             :  */
     279           0 : void CPCIDSK_ARRAY::SetArray(const std::vector<double>& oArray)
     280             : {
     281           0 :     if( !file->GetUpdatable() )
     282           0 :         return ThrowPCIDSKException("File not open for update.");
     283           0 :     unsigned int nLength = 1;
     284           0 :     for( unsigned int i=0 ; i < moSizes.size() ; i++)
     285             :     {
     286           0 :         nLength *= moSizes[i];
     287             :     }
     288             : 
     289           0 :     if(nLength != oArray.size())
     290             :     {
     291           0 :         return ThrowPCIDSKException("the size of this array doesn't match "
     292             :             "the size specified in GetSizes(). See documentation for"
     293           0 :             " more information.");
     294             :     }
     295           0 :     moArray = oArray;
     296           0 :     mbModified = true;
     297             : }
     298             : 
     299             : /**
     300             :  * Get the headers of this array. If no headers has be specified, then
     301             :  * this function return an empty vector.
     302             :  * the size of this vector should be equal to the size of the first dimension
     303             :  * returned by GetSize()[0]
     304             :  *
     305             :  * @return the headers.
     306             :  */
     307           0 : const std::vector<std::string>&  CPCIDSK_ARRAY::GetHeaders() const
     308             : {
     309           0 :     return moHeaders;
     310             : }
     311             : 
     312             : /**
     313             :  * Set the headers of this array. An empty vector can be specified to clear
     314             :  * the headers in the segment.
     315             :  * the size of this vector should be equal to the size of the first dimension
     316             :  * returned by GetSize()[0]. If it is not the case, a pci::Exception is thrown.
     317             :  *
     318             :  * @param oHeaders the headers.
     319             :  */
     320           0 : void CPCIDSK_ARRAY::SetHeaders(const std::vector<std::string>& oHeaders)
     321             : {
     322           0 :     moHeaders = oHeaders;
     323           0 :     mbModified = true;
     324           0 : }

Generated by: LCOV version 1.14