LTP GCOV extension - code coverage report
Current view: directory - frmts/pcidsk/sdk/channel - cpcidskchannel.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 153
Code covered: 52.3 % Executed lines: 80

       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                 : CPCIDSKChannel::CPCIDSKChannel( PCIDSKBuffer &image_header, 
      49                 :                                 uint64 ih_offset,
      50                 :                                 CPCIDSKFile *file, 
      51                 :                                 eChanType pixel_type,
      52             242 :                                 int channel_number )
      53                 : 
      54                 : {
      55             242 :     this->pixel_type = pixel_type;
      56             242 :     this->file = file;
      57             242 :     this->channel_number = channel_number;
      58             242 :     this->ih_offset = ih_offset;
      59                 : 
      60             484 :     width = file->GetWidth();
      61             242 :     height = file->GetHeight();
      62                 : 
      63             242 :     block_width = width;
      64             242 :     block_height = 1;
      65                 : 
      66                 : /* -------------------------------------------------------------------- */
      67                 : /*      Establish if we need to byte swap the data on load/store.       */
      68                 : /* -------------------------------------------------------------------- */
      69             242 :     if( channel_number != -1 )
      70                 :     {
      71             239 :         unsigned short test_value = 1;
      72                 : 
      73             239 :         byte_order = image_header.buffer[201];
      74             239 :         if( ((uint8 *) &test_value)[0] == 1 )
      75             239 :             needs_swap = (byte_order != 'S');
      76                 :         else
      77               0 :             needs_swap = (byte_order == 'S');
      78                 :         
      79             239 :         if( pixel_type == CHN_8U )
      80             157 :             needs_swap = 0;
      81                 : 
      82             239 :         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             239 :         metadata.Initialize( file, "IMG", channel_number );
      90                 :     }
      91                 : 
      92                 : /* -------------------------------------------------------------------- */
      93                 : /*      No overviews for unassociated files, so just mark them as       */
      94                 : /*      initialized.                                                    */
      95                 : /* -------------------------------------------------------------------- */
      96             242 :     overviews_initialized = (channel_number == -1);
      97             242 : }
      98                 : 
      99                 : /************************************************************************/
     100                 : /*                          ~CPCIDSKChannel()                           */
     101                 : /************************************************************************/
     102                 : 
     103             242 : CPCIDSKChannel::~CPCIDSKChannel()
     104                 : 
     105                 : {
     106             242 :     InvalidateOverviewInfo();
     107             242 : }
     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             242 : void CPCIDSKChannel::InvalidateOverviewInfo()
     117                 : 
     118                 : {
     119             245 :     for( size_t io=0; io < overview_bands.size(); io++ )
     120                 :     {
     121               3 :         if( overview_bands[io] != NULL )
     122                 :         {
     123               3 :             delete overview_bands[io];
     124               3 :             overview_bands[io] = NULL;
     125                 :         }
     126                 :     }
     127                 : 
     128             242 :     overview_infos.clear();
     129             242 :     overview_bands.clear();
     130             242 :     overview_decimations.clear();
     131                 : 
     132             242 :     overviews_initialized = false;
     133             242 : }
     134                 : 
     135                 : /************************************************************************/
     136                 : /*                       EstablishOverviewInfo()                        */
     137                 : /************************************************************************/
     138             794 : void CPCIDSKChannel::EstablishOverviewInfo() const
     139                 : 
     140                 : {
     141             794 :     if( overviews_initialized )
     142             640 :         return;
     143                 : 
     144             154 :     overviews_initialized = true;
     145                 : 
     146             154 :     std::vector<std::string> keys = GetMetadataKeys();
     147                 :     size_t i;
     148                 : 
     149             167 :     for( i = 0; i < keys.size(); i++ )
     150                 :     {
     151              10 :         if( strncmp(keys[i].c_str(),"_Overview_",10) != 0 )
     152               7 :             continue;
     153                 : 
     154               3 :         std::string value = GetMetadataValue( keys[i] );
     155                 : 
     156               3 :         overview_infos.push_back( value );
     157               3 :         overview_bands.push_back( NULL );
     158               3 :         overview_decimations.push_back( atoi(keys[i].c_str()+10) );
     159             154 :     }
     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             474 : int CPCIDSKChannel::GetOverviewCount()
     184                 : 
     185                 : {
     186             474 :     EstablishOverviewInfo();
     187                 : 
     188             474 :     return overview_infos.size();
     189                 : }
     190                 : 
     191                 : /************************************************************************/
     192                 : /*                            GetOverview()                             */
     193                 : /************************************************************************/
     194                 : 
     195               3 : PCIDSKChannel *CPCIDSKChannel::GetOverview( int overview_index )
     196                 : 
     197                 : {
     198               3 :     EstablishOverviewInfo();
     199                 : 
     200               3 :     if( overview_index < 0 || overview_index >= (int) overview_infos.size() )
     201                 :         ThrowPCIDSKException( "Non existant overview (%d) requested.", 
     202               0 :                               overview_index );
     203                 : 
     204               3 :     if( overview_bands[overview_index] == NULL )
     205                 :     {
     206               3 :         PCIDSKBuffer image_header(1024), file_header(1024);
     207                 :         char  pseudo_filename[65];
     208                 : 
     209                 :         sprintf( pseudo_filename, "/SIS=%d", 
     210               3 :                  atoi(overview_infos[overview_index].c_str()) );
     211                 : 
     212               3 :         image_header.Put( pseudo_filename, 64, 64 );
     213                 :         
     214                 :         overview_bands[overview_index] = 
     215                 :             new CTiledChannel( image_header, 0, file_header, -1, file, 
     216               3 :                                CHN_UNKNOWN );
     217                 :     }
     218                 : 
     219               3 :     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                 : void CPCIDSKChannel::SetOverviewValidity( int overview_index, 
     270               0 :                                           bool new_validity )
     271                 : 
     272                 : {
     273               0 :     EstablishOverviewInfo();
     274                 : 
     275               0 :     if( overview_index < 0 || overview_index >= (int) overview_infos.size() )
     276                 :         ThrowPCIDSKException( "Non existant overview (%d) requested.", 
     277               0 :                               overview_index );
     278                 : 
     279               0 :     int sis_id, validity=0;
     280                 :     char resampling[17];
     281                 :     
     282                 :     sscanf( overview_infos[overview_index].c_str(), "%d %d %16s", 
     283               0 :             &sis_id, &validity, &(resampling[0]) );
     284                 :     
     285                 :     // are we already set to this value?
     286               0 :     if( new_validity == (validity != 0) )
     287               0 :         return;
     288                 : 
     289                 :     char new_info[48];
     290                 : 
     291                 :     sprintf( new_info, "%d %d %s", 
     292               0 :              sis_id, (new_validity ? 1 : 0 ), resampling );
     293                 : 
     294               0 :     overview_infos[overview_index] = new_info;
     295                 : 
     296                 :     // write back to metadata.
     297                 :     char key[20];
     298               0 :     sprintf( key, "_Overview_%d", overview_decimations[overview_index] );
     299                 : 
     300               0 :     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             317 : void CPCIDSKChannel::InvalidateOverviews()
     311                 : 
     312                 : {
     313             317 :     EstablishOverviewInfo();
     314                 : 
     315             317 :     for( int i = 0; i < GetOverviewCount(); i++ )
     316               0 :         SetOverviewValidity( i, false );
     317             317 : }
     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             154 : std::string CPCIDSKChannel::GetDescription() 
     335                 : 
     336                 : {
     337             154 :     if( ih_offset == 0 )
     338               0 :         return "";
     339                 : 
     340             154 :     PCIDSKBuffer ih_1(64);
     341             154 :     std::string ret;
     342                 : 
     343             154 :     file->ReadFromFile( ih_1.buffer, ih_offset, 64 );
     344             154 :     ih_1.Get(0,64,ret);
     345                 : 
     346             154 :     return ret;
     347                 : 
     348                 : }
     349                 : 
     350                 : /************************************************************************/
     351                 : /*                           SetDescription()                           */
     352                 : /************************************************************************/
     353                 : 
     354               0 : void CPCIDSKChannel::SetDescription( const std::string &description )
     355                 : 
     356                 : {
     357               0 :     if( ih_offset == 0 )
     358               0 :         ThrowPCIDSKException( "Description cannot be set on overviews." );
     359                 :         
     360               0 :     PCIDSKBuffer ih_1(64);
     361               0 :     ih_1.Put( description.c_str(), 0, 64 );
     362               0 :     file->WriteToFile( ih_1.buffer, ih_offset, 64 );
     363               0 : }
     364                 : 
     365                 : /************************************************************************/
     366                 : /*                            LoadHistory()                             */
     367                 : /************************************************************************/
     368                 : 
     369             239 : void CPCIDSKChannel::LoadHistory( const PCIDSKBuffer &image_header )
     370                 : 
     371                 : {
     372                 :     // Read the history from the image header. PCIDSK supports
     373                 :     // 8 history entries per channel.
     374                 : 
     375             239 :     std::string hist_msg;
     376             239 :     history_.clear();
     377            2151 :     for (unsigned int i = 0; i < 8; i++)
     378                 :     {
     379            1912 :         image_header.Get(384 + i * 80, 80, hist_msg);
     380                 : 
     381                 :         // Some programs seem to push history records with a trailing '\0'
     382                 :         // so do some extra processing to cleanup.  FUN records on segment
     383                 :         // 3 of eltoro.pix are an example of this.
     384            1912 :         size_t size = hist_msg.size();
     385            3824 :         while( size > 0 
     386                 :                && (hist_msg[size-1] == ' ' || hist_msg[size-1] == '\0') )
     387               0 :             size--;
     388                 : 
     389            1912 :         hist_msg.resize(size);
     390                 :         
     391            1912 :         history_.push_back(hist_msg);
     392             239 :     }
     393             239 : }
     394                 : 
     395                 : /************************************************************************/
     396                 : /*                         GetHistoryEntries()                          */
     397                 : /************************************************************************/
     398                 : 
     399               0 : std::vector<std::string> CPCIDSKChannel::GetHistoryEntries() const
     400                 : {
     401               0 :     return history_;
     402                 : }
     403                 : 
     404                 : /************************************************************************/
     405                 : /*                         SetHistoryEntries()                          */
     406                 : /************************************************************************/
     407                 : 
     408               0 : void CPCIDSKChannel::SetHistoryEntries(const std::vector<std::string> &entries)
     409                 : 
     410                 : {
     411               0 :     if( ih_offset == 0 )
     412               0 :         ThrowPCIDSKException( "Attempt to update history on a raster that is not\na conventional band with an image header." );
     413                 : 
     414               0 :     PCIDSKBuffer image_header(1024);
     415                 : 
     416               0 :     file->ReadFromFile( image_header.buffer, ih_offset, 1024 );
     417                 :     
     418               0 :     for( unsigned int i = 0; i < 8; i++ )
     419                 :     {
     420               0 :         const char *msg = "";
     421               0 :         if( entries.size() > i )
     422               0 :             msg = entries[i].c_str();
     423                 : 
     424               0 :         image_header.Put( msg, 384 + i * 80, 80 );
     425                 :     }
     426                 : 
     427               0 :     file->WriteToFile( image_header.buffer, ih_offset, 1024 );
     428                 : 
     429                 :     // Force reloading of history_
     430               0 :     LoadHistory( image_header );
     431               0 : }
     432                 : 
     433                 : /************************************************************************/
     434                 : /*                            PushHistory()                             */
     435                 : /************************************************************************/
     436                 : 
     437                 : void CPCIDSKChannel::PushHistory( const std::string &app,
     438               0 :                                   const std::string &message )
     439                 : 
     440                 : {
     441                 : #define MY_MIN(a,b)      ((a<b) ? a : b)
     442                 : 
     443                 :     char current_time[17];
     444                 :     char history[81];
     445                 : 
     446               0 :     GetCurrentDateTime( current_time );
     447                 : 
     448               0 :     memset( history, ' ', 80 );
     449               0 :     history[80] = '\0';
     450                 : 
     451               0 :     memcpy( history + 0, app.c_str(), MY_MIN(app.size(),7) );
     452               0 :     history[7] = ':';
     453                 :     
     454               0 :     memcpy( history + 8, message.c_str(), MY_MIN(message.size(),56) );
     455               0 :     memcpy( history + 64, current_time, 16 );
     456                 : 
     457               0 :     std::vector<std::string> history_entries = GetHistoryEntries();
     458                 : 
     459               0 :     history_entries.insert( history_entries.begin(), history );
     460               0 :     history_entries.resize(8);
     461                 : 
     462               0 :     SetHistoryEntries( history_entries );
     463               0 : }

Generated by: LTP GCOV extension version 1.5