LCOV - code coverage report
Current view: directory - frmts/pcidsk/sdk/channel - cexternalchannel.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 313 0 0.0 %
Date: 2012-12-26 Functions: 12 0 0.0 %

       1                 : /******************************************************************************
       2                 :  *
       3                 :  * Purpose:  Implementation of the CExternalChannel class.
       4                 :  *
       5                 :  * This class is used to implement band interleaved channels that are
       6                 :  * references to an external image database that is not just a raw file.
       7                 :  * It uses the application supplied EDB interface to access non-PCIDSK files.
       8                 :  * 
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 2010
      11                 :  * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
      12                 :  *
      13                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      14                 :  * copy of this software and associated documentation files (the "Software"),
      15                 :  * to deal in the Software without restriction, including without limitation
      16                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      17                 :  * and/or sell copies of the Software, and to permit persons to whom the
      18                 :  * Software is furnished to do so, subject to the following conditions:
      19                 :  *
      20                 :  * The above copyright notice and this permission notice shall be included
      21                 :  * in all copies or substantial portions of the Software.
      22                 :  *
      23                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      24                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      25                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      26                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      27                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      28                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      29                 :  * DEALINGS IN THE SOFTWARE.
      30                 :  ****************************************************************************/
      31                 : 
      32                 : #include "pcidsk_config.h"
      33                 : #include "pcidsk_types.h"
      34                 : #include "pcidsk_channel.h"
      35                 : #include "pcidsk_buffer.h"
      36                 : #include "pcidsk_exception.h"
      37                 : #include "pcidsk_file.h"
      38                 : #include "core/pcidsk_utils.h"
      39                 : #include "core/cpcidskfile.h"
      40                 : #include "channel/cexternalchannel.h"
      41                 : #include "core/clinksegment.h"
      42                 : #include <cassert>
      43                 : #include <cstring>
      44                 : #include <cstdio>
      45                 : #include <cstdlib>
      46                 : 
      47                 : using namespace PCIDSK;
      48                 : 
      49                 : /************************************************************************/
      50                 : /*                          CExternalChannel()                          */
      51                 : /************************************************************************/
      52                 : 
      53               0 : CExternalChannel::CExternalChannel( PCIDSKBuffer &image_header, 
      54                 :                                     uint64 ih_offset, 
      55                 :                                     PCIDSKBuffer &file_header,
      56                 :                                     std::string filename,
      57                 :                                     int channelnum,
      58                 :                                     CPCIDSKFile *file,
      59                 :                                     eChanType pixel_type )
      60               0 :         : CPCIDSKChannel( image_header, ih_offset, file, pixel_type, channelnum)
      61                 : 
      62                 : {
      63               0 :     db = NULL;
      64               0 :     mutex = NULL;
      65                 : 
      66                 : /* -------------------------------------------------------------------- */
      67                 : /*      Establish the data window.                                      */
      68                 : /* -------------------------------------------------------------------- */
      69               0 :     exoff  = atoi(image_header.Get( 250, 8 ));
      70               0 :     eyoff  = atoi(image_header.Get( 258, 8 ));
      71               0 :     exsize = atoi(image_header.Get( 266, 8 ));
      72               0 :     eysize = atoi(image_header.Get( 274, 8 ));
      73                 : 
      74               0 :     echannel = atoi(image_header.Get( 282, 8 ));
      75                 : 
      76               0 :     if (echannel == 0) {
      77               0 :         echannel = channelnum;
      78                 :     }
      79                 : 
      80                 : /* -------------------------------------------------------------------- */
      81                 : /*      Establish the file we will be accessing.                        */
      82                 : /* -------------------------------------------------------------------- */
      83               0 :     if( filename != "" )
      84               0 :         this->filename = filename;
      85                 :     else
      86               0 :         image_header.Get(64,64,this->filename);
      87               0 : }
      88                 : 
      89                 : /************************************************************************/
      90                 : /*                         ~CExternalChannel()                          */
      91                 : /************************************************************************/
      92                 : 
      93               0 : CExternalChannel::~CExternalChannel()
      94                 : 
      95                 : {
      96                 :     // no need to deaccess the EDBFile - the file is responsible for that.
      97               0 : }
      98                 : 
      99                 : /************************************************************************/
     100                 : /*                              AccessDB()                              */
     101                 : /************************************************************************/
     102                 : 
     103               0 : void CExternalChannel::AccessDB() const
     104                 : 
     105                 : {
     106               0 :     if( db != NULL )
     107               0 :         return;
     108                 : 
     109                 : /* -------------------------------------------------------------------- */
     110                 : /*      open, or fetch an already open file handle.                     */
     111                 : /* -------------------------------------------------------------------- */
     112               0 :     writable = file->GetEDBFileDetails( &db, &mutex, filename );
     113                 : 
     114                 : /* -------------------------------------------------------------------- */
     115                 : /*      Capture the block size.                                         */
     116                 : /* -------------------------------------------------------------------- */
     117               0 :     block_width = db->GetBlockWidth( echannel );
     118               0 :     if( block_width > width )
     119               0 :         block_width = width;
     120               0 :     block_height = db->GetBlockHeight( echannel );
     121               0 :     if( block_height > height )
     122               0 :         block_height = height;
     123                 : 
     124               0 :     blocks_per_row = (GetWidth() + block_width - 1) / block_width;
     125                 : }
     126                 : 
     127                 : /************************************************************************/
     128                 : /*                           GetBlockWidth()                            */
     129                 : /************************************************************************/
     130                 : 
     131               0 : int CExternalChannel::GetBlockWidth() const
     132                 : 
     133                 : {
     134               0 :     AccessDB();
     135                 : 
     136               0 :     return block_width;
     137                 : }
     138                 : 
     139                 : /************************************************************************/
     140                 : /*                           GetBlockHeight()                           */
     141                 : /************************************************************************/
     142                 : 
     143               0 : int CExternalChannel::GetBlockHeight() const
     144                 : 
     145                 : {
     146               0 :     AccessDB();
     147                 : 
     148               0 :     return block_height;
     149                 : }
     150                 : 
     151                 : /************************************************************************/
     152                 : /*                             ReadBlock()                              */
     153                 : /************************************************************************/
     154                 : 
     155               0 : int CExternalChannel::ReadBlock( int block_index, void *buffer,
     156                 :                                  int xoff, int yoff, 
     157                 :                                  int xsize, int ysize )
     158                 : 
     159                 : {
     160               0 :     AccessDB();
     161                 : 
     162                 : /* -------------------------------------------------------------------- */
     163                 : /*      Default window if needed.                                       */
     164                 : /* -------------------------------------------------------------------- */
     165               0 :     if( xoff == -1 && yoff == -1 && xsize == -1 && ysize == -1 )
     166                 :     {
     167               0 :         xoff = 0;
     168               0 :         yoff = 0;
     169               0 :         xsize = GetBlockWidth();
     170               0 :         ysize = GetBlockHeight();
     171                 :     }
     172                 : 
     173                 : /* -------------------------------------------------------------------- */
     174                 : /*      Validate Window                                                 */
     175                 : /* -------------------------------------------------------------------- */
     176               0 :     if( xoff < 0 || xoff + xsize > GetBlockWidth()
     177               0 :         || yoff < 0 || yoff + ysize > GetBlockHeight() )
     178                 :     {
     179                 :         ThrowPCIDSKException( 
     180                 :             "Invalid window in ReadBlock(): xoff=%d,yoff=%d,xsize=%d,ysize=%d",
     181               0 :             xoff, yoff, xsize, ysize );
     182                 :     }
     183                 : 
     184                 : /* -------------------------------------------------------------------- */
     185                 : /*      Do a direct call for the simpliest case of 1:1 block mapping.   */
     186                 : /* -------------------------------------------------------------------- */
     187               0 :     if( exoff == 0 && eyoff == 0 
     188               0 :         && exsize == db->GetWidth()
     189               0 :         && eysize == db->GetHeight() )
     190                 :     {
     191               0 :         MutexHolder oHolder( mutex );
     192                 :         return db->ReadBlock( echannel, block_index, buffer, 
     193               0 :                               xoff, yoff, xsize, ysize );
     194                 :     }
     195                 : 
     196                 : /* ==================================================================== */
     197                 : /*      Otherwise we need to break this down into potentially up to     */
     198                 : /*      four requests against the source file.                          */
     199                 : /* ==================================================================== */
     200               0 :     int src_block_width  = db->GetBlockWidth( echannel );
     201               0 :     int src_block_height = db->GetBlockHeight( echannel );
     202               0 :     int src_blocks_per_row = (db->GetWidth() + src_block_width - 1) 
     203               0 :         / src_block_width;
     204               0 :     int pixel_size = DataTypeSize(GetType());
     205                 :     uint8 *temp_buffer = (uint8 *) calloc(src_block_width*src_block_height,
     206               0 :                                           pixel_size);
     207                 :     int txoff, tyoff, txsize, tysize;
     208                 :     int dst_blockx, dst_blocky;
     209                 : 
     210               0 :     if( temp_buffer == NULL )
     211               0 :         ThrowPCIDSKException( "Failed to allocate temporary block buffer." );
     212                 : 
     213               0 :     dst_blockx = block_index % blocks_per_row;
     214               0 :     dst_blocky = block_index / blocks_per_row;
     215                 : 
     216                 :     // what is the region of our desired data on the destination file?
     217                 : 
     218               0 :     txoff = dst_blockx * block_width + exoff + xoff;
     219               0 :     tyoff = dst_blocky * block_height + eyoff + yoff;
     220               0 :     txsize = xsize;
     221               0 :     tysize = ysize;
     222                 :     
     223                 : /* -------------------------------------------------------------------- */
     224                 : /*      read external block for top left corner of target block.        */
     225                 : /* -------------------------------------------------------------------- */
     226                 :     int ablock_x, ablock_y, i_line;
     227                 :     int axoff, ayoff, axsize, aysize;
     228               0 :     int block1_xsize=0, block1_ysize=0;
     229                 :     int ttxoff, ttyoff, ttxsize, ttysize;
     230                 :     
     231               0 :     ttxoff = txoff;
     232               0 :     ttyoff = tyoff;
     233               0 :     ttxsize = txsize;
     234               0 :     ttysize = tysize;
     235                 :     
     236               0 :     ablock_x = ttxoff / src_block_width;
     237               0 :     ablock_y = ttyoff / src_block_height;
     238                 : 
     239               0 :     axoff = ttxoff - ablock_x * src_block_width;
     240               0 :     ayoff = ttyoff - ablock_y * src_block_height;
     241                 : 
     242               0 :     if( axoff + ttxsize > src_block_width )
     243               0 :         axsize = src_block_width - axoff;
     244                 :     else
     245               0 :         axsize = ttxsize;
     246                 : 
     247               0 :     if( ayoff + ttysize > src_block_height )
     248               0 :         aysize = src_block_height - ayoff;
     249                 :     else
     250               0 :         aysize = ttysize;
     251                 : 
     252               0 :     if( axsize > 0 )
     253               0 :         block1_xsize = axsize;
     254                 :     else
     255               0 :         block1_xsize = 0;
     256                 : 
     257               0 :     if( aysize > 0 )
     258               0 :         block1_ysize = aysize;
     259                 :     else
     260               0 :         block1_ysize = 0;
     261                 : 
     262               0 :     if( axsize > 0 && aysize > 0 )
     263                 :     {
     264               0 :         MutexHolder oHolder( mutex );
     265                 :         db->ReadBlock( echannel, ablock_x + ablock_y * src_blocks_per_row, 
     266               0 :                        temp_buffer, axoff, ayoff, axsize, aysize );
     267                 :                        
     268               0 :         for( i_line = 0; i_line < aysize; i_line++ )
     269                 :         {
     270                 :             memcpy( ((uint8*) buffer) + i_line * xsize * pixel_size, 
     271                 :                     temp_buffer + i_line * axsize * pixel_size,
     272               0 :                     axsize * pixel_size );
     273               0 :         }
     274                 :     }
     275                 :     
     276                 : /* -------------------------------------------------------------------- */
     277                 : /*      read external block for top right corner of target block.       */
     278                 : /* -------------------------------------------------------------------- */
     279               0 :     ttxoff = txoff + block1_xsize;
     280               0 :     ttyoff = tyoff;
     281               0 :     ttxsize = txsize - block1_xsize;
     282               0 :     ttysize = tysize;
     283                 :     
     284               0 :     ablock_x = ttxoff / src_block_width;
     285               0 :     ablock_y = ttyoff / src_block_height;
     286                 : 
     287               0 :     axoff = ttxoff - ablock_x * src_block_width;
     288               0 :     ayoff = ttyoff - ablock_y * src_block_height;
     289                 : 
     290               0 :     if( axoff + ttxsize > src_block_width )
     291               0 :         axsize = src_block_width - axoff;
     292                 :     else
     293               0 :         axsize = ttxsize;
     294                 : 
     295               0 :     if( ayoff + ttysize > src_block_height )
     296               0 :         aysize = src_block_height - ayoff;
     297                 :     else
     298               0 :         aysize = ttysize;
     299                 : 
     300               0 :     if( axsize > 0 && aysize > 0 )
     301                 :     {
     302               0 :         MutexHolder oHolder( mutex );
     303                 :         db->ReadBlock( echannel, ablock_x + ablock_y * src_blocks_per_row, 
     304               0 :                        temp_buffer, axoff, ayoff, axsize, aysize );
     305                 :                        
     306               0 :         for( i_line = 0; i_line < aysize; i_line++ )
     307                 :         {
     308                 :             memcpy( ((uint8*) buffer) 
     309                 :                     + (block1_xsize + i_line * xsize) * pixel_size, 
     310                 :                     temp_buffer + i_line * axsize * pixel_size,
     311               0 :                     axsize * pixel_size );
     312               0 :         }
     313                 :     }
     314                 :     
     315                 : /* -------------------------------------------------------------------- */
     316                 : /*      read external block for bottom left corner of target block.     */
     317                 : /* -------------------------------------------------------------------- */
     318               0 :     ttxoff = txoff;
     319               0 :     ttyoff = tyoff + block1_ysize;
     320               0 :     ttxsize = txsize;
     321               0 :     ttysize = tysize - block1_ysize;
     322                 :     
     323               0 :     ablock_x = ttxoff / src_block_width;
     324               0 :     ablock_y = ttyoff / src_block_height;
     325                 : 
     326               0 :     axoff = ttxoff - ablock_x * src_block_width;
     327               0 :     ayoff = ttyoff - ablock_y * src_block_height;
     328                 : 
     329               0 :     if( axoff + ttxsize > src_block_width )
     330               0 :         axsize = src_block_width - axoff;
     331                 :     else
     332               0 :         axsize = ttxsize;
     333                 : 
     334               0 :     if( ayoff + ttysize > src_block_height )
     335               0 :         aysize = src_block_height - ayoff;
     336                 :     else
     337               0 :         aysize = ttysize;
     338                 : 
     339               0 :     if( axsize > 0 && aysize > 0 )
     340                 :     {
     341               0 :         MutexHolder oHolder( mutex );
     342                 :         db->ReadBlock( echannel, ablock_x + ablock_y * src_blocks_per_row, 
     343               0 :                        temp_buffer, axoff, ayoff, axsize, aysize );
     344                 :                        
     345               0 :         for( i_line = 0; i_line < aysize; i_line++ )
     346                 :         {
     347                 :             memcpy( ((uint8*) buffer) 
     348                 :                     + (i_line + block1_ysize) * xsize * pixel_size, 
     349                 :                     temp_buffer + i_line * axsize * pixel_size,
     350               0 :                     axsize * pixel_size );
     351               0 :         }
     352                 :     }
     353                 :     
     354                 : /* -------------------------------------------------------------------- */
     355                 : /*      read external block for bottom left corner of target block.     */
     356                 : /* -------------------------------------------------------------------- */
     357               0 :     ttxoff = txoff + block1_xsize;
     358               0 :     ttyoff = tyoff + block1_ysize;
     359               0 :     ttxsize = txsize - block1_xsize;
     360               0 :     ttysize = tysize - block1_ysize;
     361                 :     
     362               0 :     ablock_x = ttxoff / src_block_width;
     363               0 :     ablock_y = ttyoff / src_block_height;
     364                 : 
     365               0 :     axoff = ttxoff - ablock_x * src_block_width;
     366               0 :     ayoff = ttyoff - ablock_y * src_block_height;
     367                 : 
     368               0 :     if( axoff + ttxsize > src_block_width )
     369               0 :         axsize = src_block_width - axoff;
     370                 :     else
     371               0 :         axsize = ttxsize;
     372                 : 
     373               0 :     if( ayoff + ttysize > src_block_height )
     374               0 :         aysize = src_block_height - ayoff;
     375                 :     else
     376               0 :         aysize = ttysize;
     377                 : 
     378               0 :     if( axsize > 0 && aysize > 0 )
     379                 :     {
     380               0 :         MutexHolder oHolder( mutex );
     381                 :         db->ReadBlock( echannel, ablock_x + ablock_y * src_blocks_per_row, 
     382               0 :                        temp_buffer, axoff, ayoff, axsize, aysize );
     383                 :                        
     384               0 :         for( i_line = 0; i_line < aysize; i_line++ )
     385                 :         {
     386                 :             memcpy( ((uint8*) buffer) 
     387                 :                     + (block1_xsize + (i_line + block1_ysize) * xsize) * pixel_size, 
     388                 :                     temp_buffer + i_line * axsize * pixel_size,
     389               0 :                     axsize * pixel_size );
     390               0 :         }
     391                 :     }
     392                 :     
     393               0 :     free( temp_buffer );
     394                 : 
     395               0 :     return 1;
     396                 : }
     397                 : 
     398                 : /************************************************************************/
     399                 : /*                             WriteBlock()                             */
     400                 : /************************************************************************/
     401                 : 
     402               0 : int CExternalChannel::WriteBlock( int block_index, void *buffer )
     403                 : 
     404                 : {
     405               0 :     AccessDB();
     406                 : 
     407               0 :     if( !file->GetUpdatable() || !writable )
     408               0 :         throw PCIDSKException( "File not open for update in WriteBlock()" );
     409                 : 
     410                 : /* -------------------------------------------------------------------- */
     411                 : /*      Pass the request on directly in the simple case.                */
     412                 : /* -------------------------------------------------------------------- */
     413               0 :     if( exoff == 0 && eyoff == 0 
     414               0 :         && exsize == db->GetWidth()
     415               0 :         && eysize == db->GetHeight() )
     416                 :     {
     417               0 :         MutexHolder oHolder( mutex );
     418               0 :         return db->WriteBlock( echannel, block_index, buffer ); 
     419                 :     }
     420                 : 
     421                 : /* ==================================================================== */
     422                 : /*      Otherwise we need to break this down into potentially up to     */
     423                 : /*      four requests against the source file.                          */
     424                 : /* ==================================================================== */
     425               0 :     int src_block_width  = db->GetBlockWidth( echannel );
     426               0 :     int src_block_height = db->GetBlockHeight( echannel );
     427               0 :     int src_blocks_per_row = (db->GetWidth() + src_block_width - 1) 
     428               0 :         / src_block_width;
     429               0 :     int pixel_size = DataTypeSize(GetType());
     430                 :     uint8 *temp_buffer = (uint8 *) calloc(src_block_width*src_block_height,
     431               0 :                                           pixel_size);
     432                 :     int txoff, tyoff, txsize, tysize;
     433                 :     int dst_blockx, dst_blocky;
     434                 : 
     435               0 :     if( temp_buffer == NULL )
     436               0 :         ThrowPCIDSKException( "Failed to allocate temporary block buffer." );
     437                 : 
     438               0 :     dst_blockx = block_index % blocks_per_row;
     439               0 :     dst_blocky = block_index / blocks_per_row;
     440                 : 
     441                 :     // what is the region of our desired data on the destination file?
     442                 : 
     443               0 :     txoff = dst_blockx * block_width + exoff;
     444               0 :     tyoff = dst_blocky * block_height + eyoff;
     445               0 :     txsize = block_width;
     446               0 :     tysize = block_height;
     447                 :     
     448                 : /* -------------------------------------------------------------------- */
     449                 : /*      process external block for top left corner of target block.     */
     450                 : /* -------------------------------------------------------------------- */
     451                 :     int ablock_x, ablock_y, i_line;
     452                 :     int axoff, ayoff, axsize, aysize;
     453               0 :     int block1_xsize=0, block1_ysize=0;
     454                 :     int ttxoff, ttyoff, ttxsize, ttysize;
     455                 :     
     456               0 :     ttxoff = txoff;
     457               0 :     ttyoff = tyoff;
     458               0 :     ttxsize = txsize;
     459               0 :     ttysize = tysize;
     460                 :     
     461               0 :     ablock_x = ttxoff / src_block_width;
     462               0 :     ablock_y = ttyoff / src_block_height;
     463                 : 
     464               0 :     axoff = ttxoff - ablock_x * src_block_width;
     465               0 :     ayoff = ttyoff - ablock_y * src_block_height;
     466                 : 
     467               0 :     if( axoff + ttxsize > src_block_width )
     468               0 :         axsize = src_block_width - axoff;
     469                 :     else
     470               0 :         axsize = ttxsize;
     471                 : 
     472               0 :     if( ayoff + ttysize > src_block_height )
     473               0 :         aysize = src_block_height - ayoff;
     474                 :     else
     475               0 :         aysize = ttysize;
     476                 : 
     477               0 :     if( axsize > 0 )
     478               0 :         block1_xsize = axsize;
     479                 :     else
     480               0 :         block1_xsize = 0;
     481                 : 
     482               0 :     if( aysize > 0 )
     483               0 :         block1_ysize = aysize;
     484                 :     else
     485               0 :         block1_ysize = 0;
     486                 : 
     487               0 :     if( axsize > 0 && aysize > 0 )
     488                 :     {
     489               0 :         MutexHolder oHolder( mutex );
     490                 :         db->ReadBlock( echannel, ablock_x + ablock_y * src_blocks_per_row, 
     491               0 :                        temp_buffer );
     492                 :                        
     493               0 :         for( i_line = 0; i_line < aysize; i_line++ )
     494                 :         {
     495                 :             memcpy( temp_buffer 
     496                 :                     + (i_line+ayoff) * src_block_width * pixel_size
     497                 :                     + axoff * pixel_size,
     498                 :                     ((uint8*) buffer) + i_line * block_width * pixel_size, 
     499               0 :                     axsize * pixel_size );
     500                 :         }
     501                 : 
     502                 :         db->WriteBlock( echannel, ablock_x + ablock_y * src_blocks_per_row, 
     503               0 :                         temp_buffer );
     504                 :     }
     505                 : 
     506                 : /* -------------------------------------------------------------------- */
     507                 : /*      read external block for top right corner of target block.       */
     508                 : /* -------------------------------------------------------------------- */
     509               0 :     ttxoff = txoff + block1_xsize;
     510               0 :     ttyoff = tyoff;
     511               0 :     ttxsize = txsize - block1_xsize;
     512               0 :     ttysize = tysize;
     513                 :     
     514               0 :     ablock_x = ttxoff / src_block_width;
     515               0 :     ablock_y = ttyoff / src_block_height;
     516                 : 
     517               0 :     axoff = ttxoff - ablock_x * src_block_width;
     518               0 :     ayoff = ttyoff - ablock_y * src_block_height;
     519                 : 
     520               0 :     if( axoff + ttxsize > src_block_width )
     521               0 :         axsize = src_block_width - axoff;
     522                 :     else
     523               0 :         axsize = ttxsize;
     524                 : 
     525               0 :     if( ayoff + ttysize > src_block_height )
     526               0 :         aysize = src_block_height - ayoff;
     527                 :     else
     528               0 :         aysize = ttysize;
     529                 : 
     530               0 :     if( axsize > 0 && aysize > 0 )
     531                 :     {
     532               0 :         MutexHolder oHolder( mutex );
     533                 :         db->ReadBlock( echannel, ablock_x + ablock_y * src_blocks_per_row, 
     534               0 :                        temp_buffer );
     535                 :                        
     536               0 :         for( i_line = 0; i_line < aysize; i_line++ )
     537                 :         {
     538                 :             memcpy( temp_buffer 
     539                 :                     + (i_line+ayoff) * src_block_width * pixel_size
     540                 :                     + axoff * pixel_size,
     541                 :                     ((uint8*) buffer) + i_line * block_width * pixel_size
     542                 :                     + block1_xsize * pixel_size,
     543               0 :                     axsize * pixel_size );
     544                 :         }
     545                 : 
     546                 :         db->WriteBlock( echannel, ablock_x + ablock_y * src_blocks_per_row, 
     547               0 :                         temp_buffer );
     548                 :     }
     549                 :     
     550                 : /* -------------------------------------------------------------------- */
     551                 : /*      read external block for bottom left corner of target block.     */
     552                 : /* -------------------------------------------------------------------- */
     553               0 :     ttxoff = txoff;
     554               0 :     ttyoff = tyoff + block1_ysize;
     555               0 :     ttxsize = txsize;
     556               0 :     ttysize = tysize - block1_ysize;
     557                 :     
     558               0 :     ablock_x = ttxoff / src_block_width;
     559               0 :     ablock_y = ttyoff / src_block_height;
     560                 : 
     561               0 :     axoff = ttxoff - ablock_x * src_block_width;
     562               0 :     ayoff = ttyoff - ablock_y * src_block_height;
     563                 : 
     564               0 :     if( axoff + ttxsize > src_block_width )
     565               0 :         axsize = src_block_width - axoff;
     566                 :     else
     567               0 :         axsize = ttxsize;
     568                 : 
     569               0 :     if( ayoff + ttysize > src_block_height )
     570               0 :         aysize = src_block_height - ayoff;
     571                 :     else
     572               0 :         aysize = ttysize;
     573                 : 
     574               0 :     if( axsize > 0 && aysize > 0 )
     575                 :     {
     576               0 :         MutexHolder oHolder( mutex );
     577                 :         db->ReadBlock( echannel, ablock_x + ablock_y * src_blocks_per_row, 
     578               0 :                        temp_buffer );
     579                 :                        
     580               0 :         for( i_line = 0; i_line < aysize; i_line++ )
     581                 :         {
     582                 :             memcpy( temp_buffer 
     583                 :                     + (i_line+ayoff) * src_block_width * pixel_size
     584                 :                     + axoff * pixel_size,
     585                 :                     ((uint8*) buffer) 
     586                 :                     + (i_line+block1_ysize) * block_width * pixel_size,
     587               0 :                     axsize * pixel_size );
     588                 :         }
     589                 : 
     590                 :         db->WriteBlock( echannel, ablock_x + ablock_y * src_blocks_per_row, 
     591               0 :                         temp_buffer );
     592                 :     }
     593                 :     
     594                 : /* -------------------------------------------------------------------- */
     595                 : /*      read external block for bottom left corner of target block.     */
     596                 : /* -------------------------------------------------------------------- */
     597               0 :     ttxoff = txoff + block1_xsize;
     598               0 :     ttyoff = tyoff + block1_ysize;
     599               0 :     ttxsize = txsize - block1_xsize;
     600               0 :     ttysize = tysize - block1_ysize;
     601                 :     
     602               0 :     ablock_x = ttxoff / src_block_width;
     603               0 :     ablock_y = ttyoff / src_block_height;
     604                 : 
     605               0 :     axoff = ttxoff - ablock_x * src_block_width;
     606               0 :     ayoff = ttyoff - ablock_y * src_block_height;
     607                 : 
     608               0 :     if( axoff + ttxsize > src_block_width )
     609               0 :         axsize = src_block_width - axoff;
     610                 :     else
     611               0 :         axsize = ttxsize;
     612                 : 
     613               0 :     if( ayoff + ttysize > src_block_height )
     614               0 :         aysize = src_block_height - ayoff;
     615                 :     else
     616               0 :         aysize = ttysize;
     617                 : 
     618               0 :     if( axsize > 0 && aysize > 0 )
     619                 :     {
     620               0 :         MutexHolder oHolder( mutex );
     621                 :         db->ReadBlock( echannel, ablock_x + ablock_y * src_blocks_per_row, 
     622               0 :                        temp_buffer );
     623                 :                        
     624               0 :         for( i_line = 0; i_line < aysize; i_line++ )
     625                 :         {
     626                 :             memcpy( temp_buffer 
     627                 :                     + (i_line+ayoff) * src_block_width * pixel_size
     628                 :                     + axoff * pixel_size,
     629                 :                     ((uint8*) buffer) 
     630                 :                     + (i_line+block1_ysize) * block_width * pixel_size
     631                 :                     + block1_xsize * pixel_size,
     632               0 :                     axsize * pixel_size );
     633                 :         }
     634                 : 
     635                 :         db->WriteBlock( echannel, ablock_x + ablock_y * src_blocks_per_row, 
     636               0 :                         temp_buffer );
     637                 :     }
     638                 : 
     639               0 :     free( temp_buffer );
     640                 : 
     641               0 :     return 1;
     642                 : }
     643                 : 
     644                 : /************************************************************************/
     645                 : /*                            GetEChanInfo()                            */
     646                 : /************************************************************************/
     647               0 : void CExternalChannel::GetEChanInfo( std::string &filename, int &echannel,
     648                 :                                      int &exoff, int &eyoff, 
     649                 :                                      int &exsize, int &eysize ) const
     650                 : 
     651                 : {
     652               0 :     echannel = this->echannel;
     653               0 :     exoff = this->exoff;
     654               0 :     eyoff = this->eyoff;
     655               0 :     exsize = this->exsize;
     656               0 :     eysize = this->eysize;
     657               0 :     filename = this->filename;
     658               0 : }
     659                 : 
     660                 : /************************************************************************/
     661                 : /*                            SetEChanInfo()                            */
     662                 : /************************************************************************/
     663                 : 
     664               0 : void CExternalChannel::SetEChanInfo( std::string filename, int echannel,
     665                 :                                      int exoff, int eyoff, 
     666                 :                                      int exsize, int eysize )
     667                 : 
     668                 : {
     669               0 :     if( ih_offset == 0 )
     670               0 :         ThrowPCIDSKException( "No Image Header available for this channel." );
     671                 : 
     672                 : /* -------------------------------------------------------------------- */
     673                 : /*      Fetch the existing image header.                                */
     674                 : /* -------------------------------------------------------------------- */
     675               0 :     PCIDSKBuffer ih(1024);
     676                 : 
     677               0 :     file->ReadFromFile( ih.buffer, ih_offset, 1024 );
     678                 : 
     679                 : /* -------------------------------------------------------------------- */
     680                 : /*      If the linked filename is too long to fit in the 64             */
     681                 : /*      character IHi.2 field, then we need to use a link segment to    */
     682                 : /*      store the filename.                                             */
     683                 : /* -------------------------------------------------------------------- */
     684               0 :     std::string IHi2_filename;
     685                 :     
     686               0 :     if( filename.size() > 64 )
     687                 :     {
     688                 :         int link_segment;
     689                 :         
     690               0 :         ih.Get( 64, 64, IHi2_filename );
     691                 :                 
     692               0 :         if( IHi2_filename.substr(0,3) == "LNK" )
     693                 :         {
     694               0 :             link_segment = std::atoi( IHi2_filename.c_str() + 4 );
     695                 :         }
     696                 :         else
     697                 :         {
     698                 :             char link_filename[64];
     699                 :            
     700                 :             link_segment = 
     701                 :                 file->CreateSegment( "Link    ", 
     702                 :                                      "Long external channel filename link.", 
     703               0 :                                      SEG_SYS, 1 );
     704                 : 
     705               0 :             sprintf( link_filename, "LNK %4d", link_segment );
     706               0 :             IHi2_filename = link_filename;
     707                 :         }
     708                 : 
     709                 :         CLinkSegment *link = 
     710               0 :             dynamic_cast<CLinkSegment*>( file->GetSegment( link_segment ) );
     711                 :         
     712               0 :         if( link != NULL )
     713                 :         {
     714               0 :             link->SetPath( filename );
     715               0 :             link->Synchronize();
     716                 :         }
     717                 :     }
     718                 :     
     719                 : /* -------------------------------------------------------------------- */
     720                 : /*      If we used to have a link segment but no longer need it, we     */
     721                 : /*      need to delete the link segment.                                */
     722                 : /* -------------------------------------------------------------------- */
     723                 :     else
     724                 :     {
     725               0 :         ih.Get( 64, 64, IHi2_filename );
     726                 :                 
     727               0 :         if( IHi2_filename.substr(0,3) == "LNK" )
     728                 :         {
     729               0 :             int link_segment = std::atoi( IHi2_filename.c_str() + 4 );
     730                 : 
     731               0 :             file->DeleteSegment( link_segment );
     732                 :         }
     733                 :         
     734               0 :         IHi2_filename = filename;
     735                 :     }
     736                 :         
     737                 : /* -------------------------------------------------------------------- */
     738                 : /*      Update the image header.                                        */
     739                 : /* -------------------------------------------------------------------- */
     740                 :     // IHi.2
     741               0 :     ih.Put( IHi2_filename.c_str(), 64, 64 );
     742                 : 
     743                 :     // IHi.6.1
     744               0 :     ih.Put( "", 168, 16 );
     745                 : 
     746                 :     // IHi.6.2
     747               0 :     ih.Put( "", 184, 8 );
     748                 : 
     749                 :     // IHi.6.3
     750               0 :     ih.Put( "", 192, 8 );
     751                 : 
     752                 :     // IHi.6.5
     753               0 :     ih.Put( "", 201, 1 );
     754                 : 
     755                 :     // IHi.6.7
     756               0 :     ih.Put( exoff, 250, 8 );
     757                 : 
     758                 :     // IHi.6.8
     759               0 :     ih.Put( eyoff, 258, 8 );
     760                 : 
     761                 :     // IHi.6.9
     762               0 :     ih.Put( exsize, 266, 8 );
     763                 : 
     764                 :     // IHi.6.10
     765               0 :     ih.Put( eysize, 274, 8 );
     766                 : 
     767                 :     // IHi.6.11
     768               0 :     ih.Put( echannel, 282, 8 );
     769                 : 
     770               0 :     file->WriteToFile( ih.buffer, ih_offset, 1024 );
     771                 : 
     772                 : /* -------------------------------------------------------------------- */
     773                 : /*      Update local configuration.                                     */
     774                 : /* -------------------------------------------------------------------- */
     775               0 :     this->filename = MergeRelativePath( file->GetInterfaces()->io,
     776                 :                                         file->GetFilename(), 
     777               0 :                                         filename );
     778                 : 
     779               0 :     this->exoff = exoff;
     780               0 :     this->eyoff = eyoff;
     781               0 :     this->exsize = exsize;
     782               0 :     this->eysize = eysize;
     783               0 :     this->echannel = echannel;
     784               0 : }

Generated by: LCOV version 1.7