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

Generated by: LCOV version 1.14