LCOV - code coverage report
Current view: directory - frmts/pcidsk/sdk/channel - cpcidskchannel.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 175 106 60.6 %
Date: 2012-12-26 Functions: 25 12 48.0 %

       1                 : /******************************************************************************
       2                 :  *
       3                 :  * Purpose:  Implementation of the CPCIDSKChannel Abstract class.
       4                 :  * 
       5                 :  ******************************************************************************
       6                 :  * Copyright (c) 2009
       7                 :  * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, 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_config.h"
      29                 : #include "pcidsk_types.h"
      30                 : #include "core/pcidsk_utils.h"
      31                 : #include "pcidsk_exception.h"
      32                 : #include "pcidsk_channel.h"
      33                 : #include "core/cpcidskfile.h"
      34                 : #include "channel/cpcidskchannel.h"
      35                 : #include "channel/ctiledchannel.h"
      36                 : #include <cstring>
      37                 : #include <cassert>
      38                 : #include <cstdlib>
      39                 : #include <cstring>
      40                 : #include <cstdio>
      41                 : 
      42                 : using namespace PCIDSK;
      43                 : 
      44                 : /************************************************************************/
      45                 : /*                           CPCIDSKChannel()                           */
      46                 : /************************************************************************/
      47                 : 
      48             186 : CPCIDSKChannel::CPCIDSKChannel( PCIDSKBuffer &image_header, 
      49                 :                                 uint64 ih_offset,
      50                 :                                 CPCIDSKFile *file, 
      51                 :                                 eChanType pixel_type,
      52             186 :                                 int channel_number )
      53                 : 
      54                 : {
      55             186 :     this->pixel_type = pixel_type;
      56             186 :     this->file = file;
      57             186 :     this->channel_number = channel_number;
      58             186 :     this->ih_offset = ih_offset;
      59                 : 
      60             186 :     width = file->GetWidth();
      61             186 :     height = file->GetHeight();
      62                 : 
      63             186 :     block_width = width;
      64             186 :     block_height = 1;
      65                 : 
      66                 : /* -------------------------------------------------------------------- */
      67                 : /*      Establish if we need to byte swap the data on load/store.       */
      68                 : /* -------------------------------------------------------------------- */
      69             186 :     if( channel_number != -1 )
      70                 :     {
      71             181 :         unsigned short test_value = 1;
      72                 : 
      73             181 :         byte_order = image_header.buffer[201];
      74             181 :         if( ((uint8 *) &test_value)[0] == 1 )
      75             181 :             needs_swap = (byte_order != 'S');
      76                 :         else
      77               0 :             needs_swap = (byte_order == 'S');
      78                 :         
      79             181 :         if( pixel_type == CHN_8U )
      80             119 :             needs_swap = 0;
      81                 : 
      82             181 :         LoadHistory( image_header );
      83                 : 
      84                 : /* -------------------------------------------------------------------- */
      85                 : /*      Initialize the metadata object, but do not try to load till     */
      86                 : /*      needed.  We avoid doing this for unassociated channels such     */
      87                 : /*      as overviews.                                                   */
      88                 : /* -------------------------------------------------------------------- */
      89             181 :         metadata.Initialize( file, "IMG", channel_number );
      90                 :     }
      91                 : 
      92                 : /* -------------------------------------------------------------------- */
      93                 : /*      No overviews for unassociated files, so just mark them as       */
      94                 : /*      initialized.                                                    */
      95                 : /* -------------------------------------------------------------------- */
      96             186 :     overviews_initialized = (channel_number == -1);
      97             186 : }
      98                 : 
      99                 : /************************************************************************/
     100                 : /*                          ~CPCIDSKChannel()                           */
     101                 : /************************************************************************/
     102                 : 
     103             186 : CPCIDSKChannel::~CPCIDSKChannel()
     104                 : 
     105                 : {
     106             186 :     InvalidateOverviewInfo();
     107             186 : }
     108                 : 
     109                 : /************************************************************************/
     110                 : /*                       InvalidateOverviewInfo()                       */
     111                 : /*                                                                      */
     112                 : /*      This is called when CreateOverviews() creates overviews - we    */
     113                 : /*      invalidate our loaded info and re-establish on a next request.  */
     114                 : /************************************************************************/
     115                 : 
     116             187 : void CPCIDSKChannel::InvalidateOverviewInfo()
     117                 : 
     118                 : {
     119             192 :     for( size_t io=0; io < overview_bands.size(); io++ )
     120                 :     {
     121               5 :         if( overview_bands[io] != NULL )
     122                 :         {
     123               5 :             delete overview_bands[io];
     124               5 :             overview_bands[io] = NULL;
     125                 :         }
     126                 :     }
     127                 : 
     128             187 :     overview_infos.clear();
     129             187 :     overview_bands.clear();
     130             187 :     overview_decimations.clear();
     131                 : 
     132             187 :     overviews_initialized = false;
     133             187 : }
     134                 : 
     135                 : /************************************************************************/
     136                 : /*                       EstablishOverviewInfo()                        */
     137                 : /************************************************************************/
     138             874 : void CPCIDSKChannel::EstablishOverviewInfo() const
     139                 : 
     140                 : {
     141             874 :     if( overviews_initialized )
     142             694 :         return;
     143                 : 
     144             180 :     overviews_initialized = true;
     145                 : 
     146             180 :     std::vector<std::string> keys = GetMetadataKeys();
     147                 :     size_t i;
     148                 : 
     149             185 :     for( i = 0; i < keys.size(); i++ )
     150                 :     {
     151             155 :         if( strncmp(keys[i].c_str(),"_Overview_",10) != 0 )
     152             150 :             continue;
     153                 : 
     154               5 :         std::string value = GetMetadataValue( keys[i] );
     155                 : 
     156               5 :         overview_infos.push_back( value );
     157               5 :         overview_bands.push_back( NULL );
     158               5 :         overview_decimations.push_back( atoi(keys[i].c_str()+10) );
     159             180 :     }
     160                 : }
     161                 : 
     162                 : /************************************************************************/
     163                 : /*                           GetBlockCount()                            */
     164                 : /************************************************************************/
     165                 : 
     166               0 : int CPCIDSKChannel::GetBlockCount() const
     167                 : 
     168                 : {
     169                 :     // We deliberately call GetBlockWidth() and GetWidth() to trigger
     170                 :     // computation of the values for tiled layers.  At some point it would
     171                 :     // be good to cache the block count as this computation is a bit expensive
     172                 : 
     173               0 :     int x_block_count = (GetWidth() + GetBlockWidth() - 1) / GetBlockWidth();
     174               0 :     int y_block_count = (GetHeight() + GetBlockHeight() - 1) / GetBlockHeight();
     175                 : 
     176               0 :     return x_block_count * y_block_count;
     177                 : }
     178                 : 
     179                 : /************************************************************************/
     180                 : /*                          GetOverviewCount()                          */
     181                 : /************************************************************************/
     182                 : 
     183             527 : int CPCIDSKChannel::GetOverviewCount()
     184                 : 
     185                 : {
     186             527 :     EstablishOverviewInfo();
     187                 : 
     188             527 :     return overview_infos.size();
     189                 : }
     190                 : 
     191                 : /************************************************************************/
     192                 : /*                            GetOverview()                             */
     193                 : /************************************************************************/
     194                 : 
     195               5 : PCIDSKChannel *CPCIDSKChannel::GetOverview( int overview_index )
     196                 : 
     197                 : {
     198               5 :     EstablishOverviewInfo();
     199                 : 
     200               5 :     if( overview_index < 0 || overview_index >= (int) overview_infos.size() )
     201                 :         ThrowPCIDSKException( "Non existant overview (%d) requested.", 
     202               0 :                               overview_index );
     203                 : 
     204               5 :     if( overview_bands[overview_index] == NULL )
     205                 :     {
     206               5 :         PCIDSKBuffer image_header(1024), file_header(1024);
     207                 :         char  pseudo_filename[65];
     208                 : 
     209                 :         sprintf( pseudo_filename, "/SIS=%d", 
     210               5 :                  atoi(overview_infos[overview_index].c_str()) );
     211                 : 
     212               5 :         image_header.Put( pseudo_filename, 64, 64 );
     213                 :         
     214                 :         overview_bands[overview_index] = 
     215                 :             new CTiledChannel( image_header, 0, file_header, -1, file, 
     216               5 :                                CHN_UNKNOWN );
     217                 :     }
     218                 : 
     219               5 :     return overview_bands[overview_index];
     220                 : }
     221                 : 
     222                 : /************************************************************************/
     223                 : /*                          IsOverviewValid()                           */
     224                 : /************************************************************************/
     225                 : 
     226               0 : bool CPCIDSKChannel::IsOverviewValid( int overview_index )
     227                 : 
     228                 : {
     229               0 :     EstablishOverviewInfo();
     230                 : 
     231               0 :     if( overview_index < 0 || overview_index >= (int) overview_infos.size() )
     232                 :         ThrowPCIDSKException( "Non existant overview (%d) requested.", 
     233               0 :                               overview_index );
     234                 : 
     235               0 :     int sis_id, validity=0;
     236                 : 
     237                 :     sscanf( overview_infos[overview_index].c_str(), "%d %d", 
     238               0 :             &sis_id, &validity );
     239                 :     
     240               0 :     return validity != 0;
     241                 : }
     242                 : 
     243                 : /************************************************************************/
     244                 : /*                       GetOverviewResampling()                        */
     245                 : /************************************************************************/
     246                 : 
     247               0 : std::string CPCIDSKChannel::GetOverviewResampling( int overview_index )
     248                 : 
     249                 : {
     250               0 :     EstablishOverviewInfo();
     251                 : 
     252               0 :     if( overview_index < 0 || overview_index >= (int) overview_infos.size() )
     253                 :         ThrowPCIDSKException( "Non existant overview (%d) requested.", 
     254               0 :                               overview_index );
     255                 : 
     256               0 :     int sis_id, validity=0;
     257                 :     char resampling[17];
     258                 : 
     259                 :     sscanf( overview_infos[overview_index].c_str(), "%d %d %16s", 
     260               0 :             &sis_id, &validity, &(resampling[0]) );
     261                 :     
     262               0 :     return resampling;
     263                 : }
     264                 : 
     265                 : /************************************************************************/
     266                 : /*                        SetOverviewValidity()                         */
     267                 : /************************************************************************/
     268                 : 
     269              21 : void CPCIDSKChannel::SetOverviewValidity( int overview_index, 
     270                 :                                           bool new_validity )
     271                 : 
     272                 : {
     273              21 :     EstablishOverviewInfo();
     274                 : 
     275              21 :     if( overview_index < 0 || overview_index >= (int) overview_infos.size() )
     276                 :         ThrowPCIDSKException( "Non existant overview (%d) requested.", 
     277               0 :                               overview_index );
     278                 : 
     279              21 :     int sis_id, validity=0;
     280                 :     char resampling[17];
     281                 :     
     282                 :     sscanf( overview_infos[overview_index].c_str(), "%d %d %16s", 
     283              21 :             &sis_id, &validity, &(resampling[0]) );
     284                 :     
     285                 :     // are we already set to this value?
     286              21 :     if( new_validity == (validity != 0) )
     287              19 :         return;
     288                 : 
     289                 :     char new_info[48];
     290                 : 
     291                 :     sprintf( new_info, "%d %d %s", 
     292               2 :              sis_id, (new_validity ? 1 : 0 ), resampling );
     293                 : 
     294               2 :     overview_infos[overview_index] = new_info;
     295                 : 
     296                 :     // write back to metadata.
     297                 :     char key[20];
     298               2 :     sprintf( key, "_Overview_%d", overview_decimations[overview_index] );
     299                 : 
     300               2 :     SetMetadataValue( key, new_info );
     301                 : }
     302                 : 
     303                 : /************************************************************************/
     304                 : /*                        InvalidateOverviews()                         */
     305                 : /*                                                                      */
     306                 : /*      Whenever a write is done on this band, we will invalidate       */
     307                 : /*      any previously valid overviews.                                 */
     308                 : /************************************************************************/
     309                 : 
     310             321 : void CPCIDSKChannel::InvalidateOverviews()
     311                 : 
     312                 : {
     313             321 :     EstablishOverviewInfo();
     314                 : 
     315             341 :     for( int i = 0; i < GetOverviewCount(); i++ )
     316              20 :         SetOverviewValidity( i, false );
     317             321 : }
     318                 : 
     319                 : /************************************************************************/
     320                 : /*                  GetOverviewLevelMapping()                           */
     321                 : /************************************************************************/
     322                 : 
     323               0 : std::vector<int> CPCIDSKChannel::GetOverviewLevelMapping() const
     324                 : {
     325               0 :     EstablishOverviewInfo();
     326                 :     
     327               0 :     return overview_decimations;
     328                 : }
     329                 : 
     330                 : /************************************************************************/
     331                 : /*                           GetDescription()                           */
     332                 : /************************************************************************/
     333                 : 
     334             197 : std::string CPCIDSKChannel::GetDescription() 
     335                 : 
     336                 : {
     337             197 :     if( ih_offset == 0 )
     338               0 :         return "";
     339                 : 
     340             197 :     PCIDSKBuffer ih_1(64);
     341             197 :     std::string ret;
     342                 : 
     343             197 :     file->ReadFromFile( ih_1.buffer, ih_offset, 64 );
     344             197 :     ih_1.Get(0,64,ret);
     345                 : 
     346             197 :     return ret;
     347                 : }
     348                 : 
     349                 : /************************************************************************/
     350                 : /*                           SetDescription()                           */
     351                 : /************************************************************************/
     352                 : 
     353               1 : void CPCIDSKChannel::SetDescription( const std::string &description )
     354                 : 
     355                 : {
     356               1 :     if( ih_offset == 0 )
     357               0 :         ThrowPCIDSKException( "Description cannot be set on overviews." );
     358                 :         
     359               1 :     PCIDSKBuffer ih_1(64);
     360               1 :     ih_1.Put( description.c_str(), 0, 64 );
     361               1 :     file->WriteToFile( ih_1.buffer, ih_offset, 64 );
     362               1 : }
     363                 : 
     364                 : /************************************************************************/
     365                 : /*                            LoadHistory()                             */
     366                 : /************************************************************************/
     367                 : 
     368             181 : void CPCIDSKChannel::LoadHistory( const PCIDSKBuffer &image_header )
     369                 : 
     370                 : {
     371                 :     // Read the history from the image header. PCIDSK supports
     372                 :     // 8 history entries per channel.
     373                 : 
     374             181 :     std::string hist_msg;
     375             181 :     history_.clear();
     376            1629 :     for (unsigned int i = 0; i < 8; i++)
     377                 :     {
     378            1448 :         image_header.Get(384 + i * 80, 80, hist_msg);
     379                 : 
     380                 :         // Some programs seem to push history records with a trailing '\0'
     381                 :         // so do some extra processing to cleanup.  FUN records on segment
     382                 :         // 3 of eltoro.pix are an example of this.
     383            1448 :         size_t size = hist_msg.size();
     384            2896 :         while( size > 0 
     385                 :                && (hist_msg[size-1] == ' ' || hist_msg[size-1] == '\0') )
     386               0 :             size--;
     387                 : 
     388            1448 :         hist_msg.resize(size);
     389                 :         
     390            1448 :         history_.push_back(hist_msg);
     391             181 :     }
     392             181 : }
     393                 : 
     394                 : /************************************************************************/
     395                 : /*                         GetHistoryEntries()                          */
     396                 : /************************************************************************/
     397                 : 
     398               0 : std::vector<std::string> CPCIDSKChannel::GetHistoryEntries() const
     399                 : {
     400               0 :     return history_;
     401                 : }
     402                 : 
     403                 : /************************************************************************/
     404                 : /*                         SetHistoryEntries()                          */
     405                 : /************************************************************************/
     406                 : 
     407               0 : void CPCIDSKChannel::SetHistoryEntries(const std::vector<std::string> &entries)
     408                 : 
     409                 : {
     410               0 :     if( ih_offset == 0 )
     411               0 :         ThrowPCIDSKException( "Attempt to update history on a raster that is not\na conventional band with an image header." );
     412                 : 
     413               0 :     PCIDSKBuffer image_header(1024);
     414                 : 
     415               0 :     file->ReadFromFile( image_header.buffer, ih_offset, 1024 );
     416                 :     
     417               0 :     for( unsigned int i = 0; i < 8; i++ )
     418                 :     {
     419               0 :         const char *msg = "";
     420               0 :         if( entries.size() > i )
     421               0 :             msg = entries[i].c_str();
     422                 : 
     423               0 :         image_header.Put( msg, 384 + i * 80, 80 );
     424                 :     }
     425                 : 
     426               0 :     file->WriteToFile( image_header.buffer, ih_offset, 1024 );
     427                 : 
     428                 :     // Force reloading of history_
     429               0 :     LoadHistory( image_header );
     430               0 : }
     431                 : 
     432                 : /************************************************************************/
     433                 : /*                            PushHistory()                             */
     434                 : /************************************************************************/
     435                 : 
     436               0 : void CPCIDSKChannel::PushHistory( const std::string &app,
     437                 :                                   const std::string &message )
     438                 : 
     439                 : {
     440                 : #define MY_MIN(a,b)      ((a<b) ? a : b)
     441                 : 
     442                 :     char current_time[17];
     443                 :     char history[81];
     444                 : 
     445               0 :     GetCurrentDateTime( current_time );
     446                 : 
     447               0 :     memset( history, ' ', 80 );
     448               0 :     history[80] = '\0';
     449                 : 
     450               0 :     memcpy( history + 0, app.c_str(), MY_MIN(app.size(),7) );
     451               0 :     history[7] = ':';
     452                 :     
     453               0 :     memcpy( history + 8, message.c_str(), MY_MIN(message.size(),56) );
     454               0 :     memcpy( history + 64, current_time, 16 );
     455                 : 
     456               0 :     std::vector<std::string> history_entries = GetHistoryEntries();
     457                 : 
     458               0 :     history_entries.insert( history_entries.begin(), history );
     459               0 :     history_entries.resize(8);
     460                 : 
     461               0 :     SetHistoryEntries( history_entries );
     462               0 : }
     463                 : 
     464                 : /************************************************************************/
     465                 : /*                            GetChanInfo()                             */
     466                 : /************************************************************************/
     467               3 : void CPCIDSKChannel::GetChanInfo( std::string &filename, uint64 &image_offset, 
     468                 :                                   uint64 &pixel_offset, uint64 &line_offset, 
     469                 :                                   bool &little_endian ) const
     470                 : 
     471                 : {
     472               3 :     image_offset = 0;
     473               3 :     pixel_offset = 0;
     474               3 :     line_offset = 0;
     475               3 :     little_endian = true;
     476               3 :     filename = "";
     477               3 : }
     478                 : 
     479                 : /************************************************************************/
     480                 : /*                            SetChanInfo()                             */
     481                 : /************************************************************************/
     482                 : 
     483               0 : void CPCIDSKChannel::SetChanInfo( std::string filename, uint64 image_offset, 
     484                 :                                   uint64 pixel_offset, uint64 line_offset, 
     485                 :                                   bool little_endian )
     486                 : 
     487                 : {
     488               0 :     ThrowPCIDSKException( "Attempt to SetChanInfo() on a channel that is not FILE interleaved." );
     489               0 : }
     490                 : 
     491                 : /************************************************************************/
     492                 : /*                            GetEChanInfo()                            */
     493                 : /************************************************************************/
     494               0 : void CPCIDSKChannel::GetEChanInfo( std::string &filename, int &echannel,
     495                 :                                    int &exoff, int &eyoff, 
     496                 :                                    int &exsize, int &eysize ) const
     497                 : 
     498                 : {
     499               0 :     echannel = 0;
     500               0 :     exoff = 0;
     501               0 :     eyoff = 0;
     502               0 :     exsize = 0;
     503               0 :     eysize = 0;
     504               0 :     filename = "";
     505               0 : }
     506                 : 
     507                 : /************************************************************************/
     508                 : /*                            SetEChanInfo()                            */
     509                 : /************************************************************************/
     510                 : 
     511               0 : void CPCIDSKChannel::SetEChanInfo( std::string filename, int echannel,
     512                 :                                    int exoff, int eyoff, 
     513                 :                                    int exsize, int eysize )
     514                 : 
     515                 : {
     516               0 :     ThrowPCIDSKException( "Attempt to SetEChanInfo() on a channel that is not FILE interleaved." );
     517               0 : }

Generated by: LCOV version 1.7