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

Generated by: LCOV version 1.14