LCOV - code coverage report
Current view: top level - frmts/pcidsk/sdk/channel - cexternalchannel.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 0 371 0.0 %
Date: 2024-05-07 17:03:27 Functions: 0 11 0.0 %

          Line data    Source code
       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, 90 Allstate Parkway, Markham, Ontario, 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             : #include <climits>
      47             : 
      48             : using namespace PCIDSK;
      49             : 
      50             : /************************************************************************/
      51             : /*                          CExternalChannel()                          */
      52             : /************************************************************************/
      53             : 
      54           0 : CExternalChannel::CExternalChannel( PCIDSKBuffer &image_headerIn,
      55             :                                     uint64 ih_offsetIn,
      56             :                                     CPL_UNUSED PCIDSKBuffer &file_headerIn,
      57             :                                     const std::string& filenameIn,
      58             :                                     int channelnumIn,
      59             :                                     CPCIDSKFile *fileIn,
      60           0 :                                     eChanType pixel_typeIn )
      61           0 :         : CPCIDSKChannel( image_headerIn, ih_offsetIn, fileIn, pixel_typeIn, channelnumIn)
      62             : 
      63             : {
      64           0 :     db = nullptr;
      65           0 :     mutex = nullptr;
      66           0 :     writable = false;
      67           0 :     blocks_per_row = 0;
      68             : 
      69             : /* -------------------------------------------------------------------- */
      70             : /*      Establish the data window.                                      */
      71             : /* -------------------------------------------------------------------- */
      72           0 :     exoff  = atoi(image_headerIn.Get( 250, 8 ));
      73           0 :     eyoff  = atoi(image_headerIn.Get( 258, 8 ));
      74           0 :     exsize = atoi(image_headerIn.Get( 266, 8 ));
      75           0 :     eysize = atoi(image_headerIn.Get( 274, 8 ));
      76             : 
      77           0 :     echannel = atoi(image_headerIn.Get( 282, 8 ));
      78             : 
      79           0 :     if (echannel == 0) {
      80           0 :         echannel = channelnumIn;
      81             :     }
      82             : 
      83           0 :     if( exoff < 0 || eyoff < 0 || exsize < 0 || eysize < 0 )
      84             :     {
      85           0 :         ThrowPCIDSKException("Invalid data window parameters for CExternalChannel");
      86             :     }
      87             : 
      88             : /* -------------------------------------------------------------------- */
      89             : /*      Establish the file we will be accessing.                        */
      90             : /* -------------------------------------------------------------------- */
      91           0 :     if( filenameIn != "" )
      92           0 :         this->filename = filenameIn;
      93             :     else
      94           0 :         image_headerIn.Get(64,64,this->filename);
      95           0 : }
      96             : 
      97             : /************************************************************************/
      98             : /*                         ~CExternalChannel()                          */
      99             : /************************************************************************/
     100             : 
     101           0 : CExternalChannel::~CExternalChannel()
     102             : 
     103             : {
     104             :     // no need to deaccess the EDBFile - the file is responsible for that.
     105           0 : }
     106             : 
     107             : /************************************************************************/
     108             : /*                              AccessDB()                              */
     109             : /************************************************************************/
     110             : 
     111           0 : void CExternalChannel::AccessDB() const
     112             : 
     113             : {
     114           0 :     if( db )
     115           0 :         return;
     116             : 
     117             : /* -------------------------------------------------------------------- */
     118             : /*      open, or fetch an already open file handle.                     */
     119             : /* -------------------------------------------------------------------- */
     120           0 :     writable = file->GetEDBFileDetails( &db, &mutex, filename );
     121             : 
     122           0 :     if( !db )
     123             :     {
     124           0 :         ThrowPCIDSKException("db == nullptr");
     125             :     }
     126             :     else
     127             :     {
     128           0 :         if( echannel < 0 || echannel > db->GetChannels() )
     129             :         {
     130           0 :             ThrowPCIDSKException( 0,
     131           0 :                 "Invalid channel number: %d", echannel );
     132             :         }
     133             : 
     134           0 :         pixel_type = db->GetType(echannel);
     135             : 
     136             :     /* -------------------------------------------------------------------- */
     137             :     /*      Capture the block size.                                         */
     138             :     /* -------------------------------------------------------------------- */
     139           0 :         block_width = db->GetBlockWidth( echannel );
     140           0 :         if( block_width > width )
     141           0 :             block_width = width;
     142           0 :         block_height = db->GetBlockHeight( echannel );
     143           0 :         if( block_height > height )
     144           0 :             block_height = height;
     145             : 
     146           0 :         blocks_per_row = (GetWidth() + block_width - 1) / block_width;
     147             :     }
     148             : }
     149             : 
     150             : /************************************************************************/
     151             : /*                              GetType()                               */
     152             : /************************************************************************/
     153             : 
     154           0 : eChanType CExternalChannel::GetType() const
     155             : {
     156           0 :     AccessDB();
     157             : 
     158           0 :     return pixel_type;
     159             : }
     160             : 
     161             : /************************************************************************/
     162             : /*                           GetBlockWidth()                            */
     163             : /************************************************************************/
     164             : 
     165           0 : int CExternalChannel::GetBlockWidth() const
     166             : 
     167             : {
     168           0 :     AccessDB();
     169             : 
     170           0 :     return block_width;
     171             : }
     172             : 
     173             : /************************************************************************/
     174             : /*                           GetBlockHeight()                           */
     175             : /************************************************************************/
     176             : 
     177           0 : int CExternalChannel::GetBlockHeight() const
     178             : 
     179             : {
     180           0 :     AccessDB();
     181             : 
     182           0 :     return block_height;
     183             : }
     184             : 
     185             : /************************************************************************/
     186             : /*                             ReadBlock()                              */
     187             : /************************************************************************/
     188             : 
     189           0 : int CExternalChannel::ReadBlock( int block_index, void *buffer,
     190             :                                  int xoff, int yoff,
     191             :                                  int xsize, int ysize )
     192             : 
     193             : {
     194           0 :     AccessDB();
     195             : 
     196             : /* -------------------------------------------------------------------- */
     197             : /*      Default window if needed.                                       */
     198             : /* -------------------------------------------------------------------- */
     199           0 :     if( xoff == -1 && yoff == -1 && xsize == -1 && ysize == -1 )
     200             :     {
     201           0 :         xoff = 0;
     202           0 :         yoff = 0;
     203           0 :         xsize = GetBlockWidth();
     204           0 :         ysize = GetBlockHeight();
     205             :     }
     206             : 
     207             : /* -------------------------------------------------------------------- */
     208             : /*      Validate Window                                                 */
     209             : /* -------------------------------------------------------------------- */
     210           0 :     if( xoff < 0 || xoff + xsize > GetBlockWidth()
     211           0 :         || yoff < 0 || yoff + ysize > GetBlockHeight() )
     212             :     {
     213           0 :         return ThrowPCIDSKException( 0,
     214             :             "Invalid window in ReadBlock(): xoff=%d,yoff=%d,xsize=%d,ysize=%d",
     215           0 :             xoff, yoff, xsize, ysize );
     216             :     }
     217             : 
     218             : /* -------------------------------------------------------------------- */
     219             : /*      Do a direct call for the simplest case of 1:1 block mapping.   */
     220             : /* -------------------------------------------------------------------- */
     221           0 :     if( exoff == 0 && eyoff == 0
     222           0 :         && exsize == db->GetWidth()
     223           0 :         && eysize == db->GetHeight() )
     224             :     {
     225           0 :         MutexHolder oHolder( mutex );
     226           0 :         return db->ReadBlock( echannel, block_index, buffer,
     227           0 :                               xoff, yoff, xsize, ysize );
     228             :     }
     229             : 
     230             : /* ==================================================================== */
     231             : /*      Otherwise we need to break this down into potentially up to     */
     232             : /*      four requests against the source file.                          */
     233             : /* ==================================================================== */
     234           0 :     int src_block_width  = db->GetBlockWidth( echannel );
     235           0 :     int src_block_height = db->GetBlockHeight( echannel );
     236           0 :     int src_blocks_per_row = (db->GetWidth() + src_block_width - 1)
     237           0 :         / src_block_width;
     238           0 :     int pixel_size = DataTypeSize(GetType());
     239           0 :     std::vector<uint8> temp_buffer_vec;
     240             :     try
     241             :     {
     242           0 :         temp_buffer_vec.resize(static_cast<size_t>(src_block_width)*src_block_height*pixel_size);
     243             :     }
     244           0 :     catch( const std::exception& )
     245             :     {
     246           0 :         return ThrowPCIDSKException(0, "Failed to allocate temporary block buffer." );
     247             :     }
     248           0 :     uint8 *temp_buffer = &temp_buffer_vec[0];
     249             :     int txoff, tyoff, txsize, tysize;
     250             :     int dst_blockx, dst_blocky;
     251             : 
     252           0 :     dst_blockx = block_index % blocks_per_row;
     253           0 :     dst_blocky = block_index / blocks_per_row;
     254             : 
     255             :     // what is the region of our desired data on the destination file?
     256             : 
     257           0 :     txoff = dst_blockx * block_width + exoff + xoff;
     258           0 :     tyoff = dst_blocky * block_height + eyoff + yoff;
     259           0 :     txsize = xsize;
     260           0 :     tysize = ysize;
     261             : 
     262             : /* -------------------------------------------------------------------- */
     263             : /*      read external block for top left corner of target block.        */
     264             : /* -------------------------------------------------------------------- */
     265             :     int ablock_x, ablock_y, i_line;
     266             :     int axoff, ayoff, axsize, aysize;
     267           0 :     int block1_xsize=0, block1_ysize=0;
     268             :     int ttxoff, ttyoff, ttxsize, ttysize;
     269             : 
     270           0 :     ttxoff = txoff;
     271           0 :     ttyoff = tyoff;
     272           0 :     ttxsize = txsize;
     273           0 :     ttysize = tysize;
     274             : 
     275           0 :     ablock_x = ttxoff / src_block_width;
     276           0 :     ablock_y = ttyoff / src_block_height;
     277             : 
     278           0 :     axoff = ttxoff - ablock_x * src_block_width;
     279           0 :     ayoff = ttyoff - ablock_y * src_block_height;
     280             : 
     281           0 :     if( axoff + ttxsize > src_block_width )
     282           0 :         axsize = src_block_width - axoff;
     283             :     else
     284           0 :         axsize = ttxsize;
     285             : 
     286           0 :     if( ayoff + ttysize > src_block_height )
     287           0 :         aysize = src_block_height - ayoff;
     288             :     else
     289           0 :         aysize = ttysize;
     290             : 
     291           0 :     if( axsize > 0 )
     292           0 :         block1_xsize = axsize;
     293             :     else
     294           0 :         block1_xsize = 0;
     295             : 
     296           0 :     if( aysize > 0 )
     297           0 :         block1_ysize = aysize;
     298             :     else
     299           0 :         block1_ysize = 0;
     300             : 
     301           0 :     if( axsize > 0 && aysize > 0 )
     302             :     {
     303           0 :         MutexHolder oHolder( mutex );
     304           0 :         if( src_blocks_per_row > 0 &&
     305           0 :             (ablock_y > INT_MAX / src_blocks_per_row ||
     306           0 :              ablock_y * src_blocks_per_row > INT_MAX - ablock_x) )
     307             :         {
     308           0 :             ThrowPCIDSKException(0, "Integer overflow." );
     309             :         }
     310           0 :         db->ReadBlock( echannel, ablock_x + ablock_y * src_blocks_per_row,
     311           0 :                        temp_buffer, axoff, ayoff, axsize, aysize );
     312             : 
     313           0 :         for( i_line = 0; i_line < aysize; i_line++ )
     314             :         {
     315           0 :             memcpy( ((uint8*) buffer) + i_line * xsize * pixel_size,
     316           0 :                     temp_buffer + i_line * axsize * pixel_size,
     317           0 :                     static_cast<size_t>(axsize) * pixel_size );
     318             :         }
     319             :     }
     320             : 
     321             : /* -------------------------------------------------------------------- */
     322             : /*      read external block for top right corner of target block.       */
     323             : /* -------------------------------------------------------------------- */
     324           0 :     ttxoff = txoff + block1_xsize;
     325           0 :     ttyoff = tyoff;
     326           0 :     ttxsize = txsize - block1_xsize;
     327           0 :     ttysize = tysize;
     328             : 
     329           0 :     ablock_x = ttxoff / src_block_width;
     330           0 :     ablock_y = ttyoff / src_block_height;
     331             : 
     332           0 :     axoff = ttxoff - ablock_x * src_block_width;
     333           0 :     ayoff = ttyoff - ablock_y * src_block_height;
     334             : 
     335           0 :     if( axoff + ttxsize > src_block_width )
     336           0 :         axsize = src_block_width - axoff;
     337             :     else
     338           0 :         axsize = ttxsize;
     339             : 
     340           0 :     if( ayoff + ttysize > src_block_height )
     341           0 :         aysize = src_block_height - ayoff;
     342             :     else
     343           0 :         aysize = ttysize;
     344             : 
     345           0 :     if( axsize > 0 && aysize > 0 )
     346             :     {
     347           0 :         MutexHolder oHolder( mutex );
     348           0 :         db->ReadBlock( echannel, ablock_x + ablock_y * src_blocks_per_row,
     349           0 :                        temp_buffer, axoff, ayoff, axsize, aysize );
     350             : 
     351           0 :         for( i_line = 0; i_line < aysize; i_line++ )
     352             :         {
     353           0 :             memcpy( ((uint8*) buffer)
     354           0 :                     + (block1_xsize + i_line * xsize) * pixel_size,
     355           0 :                     temp_buffer + i_line * axsize * pixel_size,
     356           0 :                     static_cast<size_t>(axsize) * pixel_size );
     357             :         }
     358             :     }
     359             : 
     360             : /* -------------------------------------------------------------------- */
     361             : /*      read external block for bottom left corner of target block.     */
     362             : /* -------------------------------------------------------------------- */
     363           0 :     ttxoff = txoff;
     364           0 :     ttyoff = tyoff + block1_ysize;
     365           0 :     ttxsize = txsize;
     366           0 :     ttysize = tysize - block1_ysize;
     367             : 
     368           0 :     ablock_x = ttxoff / src_block_width;
     369           0 :     ablock_y = ttyoff / src_block_height;
     370             : 
     371           0 :     axoff = ttxoff - ablock_x * src_block_width;
     372           0 :     ayoff = ttyoff - ablock_y * src_block_height;
     373             : 
     374           0 :     if( axoff + ttxsize > src_block_width )
     375           0 :         axsize = src_block_width - axoff;
     376             :     else
     377           0 :         axsize = ttxsize;
     378             : 
     379           0 :     if( ayoff + ttysize > src_block_height )
     380           0 :         aysize = src_block_height - ayoff;
     381             :     else
     382           0 :         aysize = ttysize;
     383             : 
     384           0 :     if( axsize > 0 && aysize > 0 )
     385             :     {
     386           0 :         MutexHolder oHolder( mutex );
     387           0 :         db->ReadBlock( echannel, ablock_x + ablock_y * src_blocks_per_row,
     388           0 :                        temp_buffer, axoff, ayoff, axsize, aysize );
     389             : 
     390           0 :         for( i_line = 0; i_line < aysize; i_line++ )
     391             :         {
     392           0 :             memcpy( ((uint8*) buffer)
     393           0 :                     + (i_line + block1_ysize) * xsize * pixel_size,
     394           0 :                     temp_buffer + i_line * axsize * pixel_size,
     395           0 :                     static_cast<size_t>(axsize) * pixel_size );
     396             :         }
     397             :     }
     398             : 
     399             : /* -------------------------------------------------------------------- */
     400             : /*      read external block for bottom left corner of target block.     */
     401             : /* -------------------------------------------------------------------- */
     402           0 :     ttxoff = txoff + block1_xsize;
     403           0 :     ttyoff = tyoff + block1_ysize;
     404           0 :     ttxsize = txsize - block1_xsize;
     405           0 :     ttysize = tysize - block1_ysize;
     406             : 
     407           0 :     ablock_x = ttxoff / src_block_width;
     408           0 :     ablock_y = ttyoff / src_block_height;
     409             : 
     410           0 :     axoff = ttxoff - ablock_x * src_block_width;
     411           0 :     ayoff = ttyoff - ablock_y * src_block_height;
     412             : 
     413           0 :     if( axoff + ttxsize > src_block_width )
     414           0 :         axsize = src_block_width - axoff;
     415             :     else
     416           0 :         axsize = ttxsize;
     417             : 
     418           0 :     if( ayoff + ttysize > src_block_height )
     419           0 :         aysize = src_block_height - ayoff;
     420             :     else
     421           0 :         aysize = ttysize;
     422             : 
     423           0 :     if( axsize > 0 && aysize > 0 )
     424             :     {
     425           0 :         MutexHolder oHolder( mutex );
     426           0 :         db->ReadBlock( echannel, ablock_x + ablock_y * src_blocks_per_row,
     427           0 :                        temp_buffer, axoff, ayoff, axsize, aysize );
     428             : 
     429           0 :         for( i_line = 0; i_line < aysize; i_line++ )
     430             :         {
     431           0 :             memcpy( ((uint8*) buffer)
     432           0 :                     + (block1_xsize + (i_line + block1_ysize) * xsize) * pixel_size,
     433           0 :                     temp_buffer + i_line * axsize * pixel_size,
     434           0 :                     static_cast<size_t>(axsize) * pixel_size );
     435             :         }
     436             :     }
     437             : 
     438           0 :     return 1;
     439             : }
     440             : 
     441             : /************************************************************************/
     442             : /*                             WriteBlock()                             */
     443             : /************************************************************************/
     444             : 
     445           0 : int CExternalChannel::WriteBlock( int block_index, void *buffer )
     446             : 
     447             : {
     448           0 :     AccessDB();
     449             : 
     450           0 :     if( !file->GetUpdatable() || !writable )
     451           0 :         return ThrowPCIDSKException(0, "File not open for update in WriteBlock()" );
     452             : 
     453             : /* -------------------------------------------------------------------- */
     454             : /*      Pass the request on directly in the simple case.                */
     455             : /* -------------------------------------------------------------------- */
     456           0 :     if( exoff == 0 && eyoff == 0
     457           0 :         && exsize == db->GetWidth()
     458           0 :         && eysize == db->GetHeight() )
     459             :     {
     460           0 :         MutexHolder oHolder( mutex );
     461           0 :         return db->WriteBlock( echannel, block_index, buffer );
     462             :     }
     463             : 
     464             : /* ==================================================================== */
     465             : /*      Otherwise we need to break this down into potentially up to     */
     466             : /*      four requests against the source file.                          */
     467             : /* ==================================================================== */
     468           0 :     int src_block_width  = db->GetBlockWidth( echannel );
     469           0 :     int src_block_height = db->GetBlockHeight( echannel );
     470           0 :     int src_blocks_per_row = (db->GetWidth() + src_block_width - 1)
     471           0 :         / src_block_width;
     472           0 :     int pixel_size = DataTypeSize(GetType());
     473           0 :     uint8 *temp_buffer = (uint8 *) calloc(static_cast<size_t>(src_block_width)*src_block_height,
     474             :                                           pixel_size);
     475             :     int txoff, tyoff, txsize, tysize;
     476             :     int dst_blockx, dst_blocky;
     477             : 
     478           0 :     if( temp_buffer == nullptr )
     479           0 :         return ThrowPCIDSKException(0, "Failed to allocate temporary block buffer." );
     480             : 
     481           0 :     dst_blockx = block_index % blocks_per_row;
     482           0 :     dst_blocky = block_index / blocks_per_row;
     483             : 
     484             :     // what is the region of our desired data on the destination file?
     485             : 
     486           0 :     txoff = dst_blockx * block_width + exoff;
     487           0 :     tyoff = dst_blocky * block_height + eyoff;
     488           0 :     txsize = block_width;
     489           0 :     tysize = block_height;
     490             : 
     491             : /* -------------------------------------------------------------------- */
     492             : /*      process external block for top left corner of target block.     */
     493             : /* -------------------------------------------------------------------- */
     494             :     int ablock_x, ablock_y, i_line;
     495             :     int axoff, ayoff, axsize, aysize;
     496           0 :     int block1_xsize=0, block1_ysize=0;
     497             :     int ttxoff, ttyoff, ttxsize, ttysize;
     498             : 
     499           0 :     ttxoff = txoff;
     500           0 :     ttyoff = tyoff;
     501           0 :     ttxsize = txsize;
     502           0 :     ttysize = tysize;
     503             : 
     504           0 :     ablock_x = ttxoff / src_block_width;
     505           0 :     ablock_y = ttyoff / src_block_height;
     506             : 
     507           0 :     axoff = ttxoff - ablock_x * src_block_width;
     508           0 :     ayoff = ttyoff - ablock_y * src_block_height;
     509             : 
     510           0 :     if( axoff + ttxsize > src_block_width )
     511           0 :         axsize = src_block_width - axoff;
     512             :     else
     513           0 :         axsize = ttxsize;
     514             : 
     515           0 :     if( ayoff + ttysize > src_block_height )
     516           0 :         aysize = src_block_height - ayoff;
     517             :     else
     518           0 :         aysize = ttysize;
     519             : 
     520           0 :     if( axsize > 0 )
     521           0 :         block1_xsize = axsize;
     522             :     else
     523           0 :         block1_xsize = 0;
     524             : 
     525           0 :     if( aysize > 0 )
     526           0 :         block1_ysize = aysize;
     527             :     else
     528           0 :         block1_ysize = 0;
     529             : 
     530           0 :     if( axsize > 0 && aysize > 0 )
     531             :     {
     532           0 :         MutexHolder oHolder( mutex );
     533           0 :         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           0 :             memcpy( temp_buffer
     539           0 :                     + (i_line+ayoff) * src_block_width * pixel_size
     540           0 :                     + axoff * pixel_size,
     541           0 :                     ((uint8*) buffer) + i_line * block_width * pixel_size,
     542           0 :                     static_cast<size_t>(axsize) * pixel_size );
     543             :         }
     544             : 
     545           0 :         db->WriteBlock( echannel, ablock_x + ablock_y * src_blocks_per_row,
     546           0 :                         temp_buffer );
     547             :     }
     548             : 
     549             : /* -------------------------------------------------------------------- */
     550             : /*      read external block for top right corner of target block.       */
     551             : /* -------------------------------------------------------------------- */
     552           0 :     ttxoff = txoff + block1_xsize;
     553           0 :     ttyoff = tyoff;
     554           0 :     ttxsize = txsize - block1_xsize;
     555           0 :     ttysize = tysize;
     556             : 
     557           0 :     ablock_x = ttxoff / src_block_width;
     558           0 :     ablock_y = ttyoff / src_block_height;
     559             : 
     560           0 :     axoff = ttxoff - ablock_x * src_block_width;
     561           0 :     ayoff = ttyoff - ablock_y * src_block_height;
     562             : 
     563           0 :     if( axoff + ttxsize > src_block_width )
     564           0 :         axsize = src_block_width - axoff;
     565             :     else
     566           0 :         axsize = ttxsize;
     567             : 
     568           0 :     if( ayoff + ttysize > src_block_height )
     569           0 :         aysize = src_block_height - ayoff;
     570             :     else
     571           0 :         aysize = ttysize;
     572             : 
     573           0 :     if( axsize > 0 && aysize > 0 )
     574             :     {
     575           0 :         MutexHolder oHolder( mutex );
     576           0 :         db->ReadBlock( echannel, ablock_x + ablock_y * src_blocks_per_row,
     577           0 :                        temp_buffer );
     578             : 
     579           0 :         for( i_line = 0; i_line < aysize; i_line++ )
     580             :         {
     581           0 :             memcpy( temp_buffer
     582           0 :                     + (i_line+ayoff) * src_block_width * pixel_size
     583           0 :                     + axoff * pixel_size,
     584           0 :                     ((uint8*) buffer) + i_line * block_width * pixel_size
     585           0 :                     + block1_xsize * pixel_size,
     586           0 :                     static_cast<size_t>(axsize) * pixel_size );
     587             :         }
     588             : 
     589           0 :         db->WriteBlock( echannel, ablock_x + ablock_y * src_blocks_per_row,
     590           0 :                         temp_buffer );
     591             :     }
     592             : 
     593             : /* -------------------------------------------------------------------- */
     594             : /*      read external block for bottom left corner of target block.     */
     595             : /* -------------------------------------------------------------------- */
     596           0 :     ttxoff = txoff;
     597           0 :     ttyoff = tyoff + block1_ysize;
     598           0 :     ttxsize = txsize;
     599           0 :     ttysize = tysize - block1_ysize;
     600             : 
     601           0 :     ablock_x = ttxoff / src_block_width;
     602           0 :     ablock_y = ttyoff / src_block_height;
     603             : 
     604           0 :     axoff = ttxoff - ablock_x * src_block_width;
     605           0 :     ayoff = ttyoff - ablock_y * src_block_height;
     606             : 
     607           0 :     if( axoff + ttxsize > src_block_width )
     608           0 :         axsize = src_block_width - axoff;
     609             :     else
     610           0 :         axsize = ttxsize;
     611             : 
     612           0 :     if( ayoff + ttysize > src_block_height )
     613           0 :         aysize = src_block_height - ayoff;
     614             :     else
     615           0 :         aysize = ttysize;
     616             : 
     617           0 :     if( axsize > 0 && aysize > 0 )
     618             :     {
     619           0 :         MutexHolder oHolder( mutex );
     620           0 :         db->ReadBlock( echannel, ablock_x + ablock_y * src_blocks_per_row,
     621           0 :                        temp_buffer );
     622             : 
     623           0 :         for( i_line = 0; i_line < aysize; i_line++ )
     624             :         {
     625           0 :             memcpy( temp_buffer
     626           0 :                     + (i_line+ayoff) * src_block_width * pixel_size
     627           0 :                     + axoff * pixel_size,
     628             :                     ((uint8*) buffer)
     629           0 :                     + (i_line+block1_ysize) * block_width * pixel_size,
     630           0 :                     static_cast<size_t>(axsize) * pixel_size );
     631             :         }
     632             : 
     633           0 :         db->WriteBlock( echannel, ablock_x + ablock_y * src_blocks_per_row,
     634           0 :                         temp_buffer );
     635             :     }
     636             : 
     637             : /* -------------------------------------------------------------------- */
     638             : /*      read external block for bottom left corner of target block.     */
     639             : /* -------------------------------------------------------------------- */
     640           0 :     ttxoff = txoff + block1_xsize;
     641           0 :     ttyoff = tyoff + block1_ysize;
     642           0 :     ttxsize = txsize - block1_xsize;
     643           0 :     ttysize = tysize - block1_ysize;
     644             : 
     645           0 :     ablock_x = ttxoff / src_block_width;
     646           0 :     ablock_y = ttyoff / src_block_height;
     647             : 
     648           0 :     axoff = ttxoff - ablock_x * src_block_width;
     649           0 :     ayoff = ttyoff - ablock_y * src_block_height;
     650             : 
     651           0 :     if( axoff + ttxsize > src_block_width )
     652           0 :         axsize = src_block_width - axoff;
     653             :     else
     654           0 :         axsize = ttxsize;
     655             : 
     656           0 :     if( ayoff + ttysize > src_block_height )
     657           0 :         aysize = src_block_height - ayoff;
     658             :     else
     659           0 :         aysize = ttysize;
     660             : 
     661           0 :     if( axsize > 0 && aysize > 0 )
     662             :     {
     663           0 :         MutexHolder oHolder( mutex );
     664           0 :         db->ReadBlock( echannel, ablock_x + ablock_y * src_blocks_per_row,
     665           0 :                        temp_buffer );
     666             : 
     667           0 :         for( i_line = 0; i_line < aysize; i_line++ )
     668             :         {
     669           0 :             memcpy( temp_buffer
     670           0 :                     + (i_line+ayoff) * src_block_width * pixel_size
     671           0 :                     + axoff * pixel_size,
     672             :                     ((uint8*) buffer)
     673           0 :                     + (i_line+block1_ysize) * block_width * pixel_size
     674           0 :                     + block1_xsize * pixel_size,
     675           0 :                     static_cast<size_t>(axsize) * pixel_size );
     676             :         }
     677             : 
     678           0 :         db->WriteBlock( echannel, ablock_x + ablock_y * src_blocks_per_row,
     679           0 :                         temp_buffer );
     680             :     }
     681             : 
     682           0 :     free( temp_buffer );
     683             : 
     684           0 :     return 1;
     685             : }
     686             : 
     687             : /************************************************************************/
     688             : /*                            GetEChanInfo()                            */
     689             : /************************************************************************/
     690           0 : void CExternalChannel::GetEChanInfo( std::string &filenameOut, int &echannelOut,
     691             :                                      int &exoffOut, int &eyoffOut,
     692             :                                      int &exsizeOut, int &eysizeOut ) const
     693             : 
     694             : {
     695           0 :     echannelOut = this->echannel;
     696           0 :     exoffOut = this->exoff;
     697           0 :     eyoffOut = this->eyoff;
     698           0 :     exsizeOut = this->exsize;
     699           0 :     eysizeOut = this->eysize;
     700           0 :     filenameOut = this->filename;
     701           0 : }
     702             : 
     703             : /************************************************************************/
     704             : /*                            SetEChanInfo()                            */
     705             : /************************************************************************/
     706             : 
     707           0 : void CExternalChannel::SetEChanInfo( std::string filenameIn, int echannelIn,
     708             :                                      int exoffIn, int eyoffIn,
     709             :                                      int exsizeIn, int eysizeIn )
     710             : 
     711             : {
     712           0 :     if( ih_offset == 0 )
     713           0 :         return ThrowPCIDSKException( "No Image Header available for this channel." );
     714             : 
     715             : /* -------------------------------------------------------------------- */
     716             : /*      Fetch the existing image header.                                */
     717             : /* -------------------------------------------------------------------- */
     718           0 :     PCIDSKBuffer ih(1024);
     719             : 
     720           0 :     file->ReadFromFile( ih.buffer, ih_offset, 1024 );
     721             : 
     722             : /* -------------------------------------------------------------------- */
     723             : /*      If the linked filename is too long to fit in the 64             */
     724             : /*      character IHi.2 field, then we need to use a link segment to    */
     725             : /*      store the filename.                                             */
     726             : /* -------------------------------------------------------------------- */
     727           0 :     std::string IHi2_filename;
     728             : 
     729           0 :     if( filenameIn.size() > 64 )
     730             :     {
     731             :         int link_segment;
     732             : 
     733           0 :         ih.Get( 64, 64, IHi2_filename );
     734             : 
     735           0 :         if( IHi2_filename.substr(0,3) == "LNK" )
     736             :         {
     737           0 :             link_segment = std::atoi( IHi2_filename.c_str() + 4 );
     738             :         }
     739             :         else
     740             :         {
     741             :             char link_filename[64];
     742             : 
     743             :             link_segment =
     744           0 :                 file->CreateSegment( "Link    ",
     745             :                                      "Long external channel filename link.",
     746             :                                      SEG_SYS, 1 );
     747             : 
     748           0 :             snprintf( link_filename, sizeof(link_filename), "LNK %4d", link_segment );
     749           0 :             IHi2_filename = link_filename;
     750             :         }
     751             : 
     752             :         CLinkSegment *link =
     753           0 :             dynamic_cast<CLinkSegment*>( file->GetSegment( link_segment ) );
     754             : 
     755           0 :         if( link != nullptr )
     756             :         {
     757           0 :             link->SetPath( filenameIn );
     758           0 :             link->Synchronize();
     759             :         }
     760             :     }
     761             : 
     762             : /* -------------------------------------------------------------------- */
     763             : /*      If we used to have a link segment but no longer need it, we     */
     764             : /*      need to delete the link segment.                                */
     765             : /* -------------------------------------------------------------------- */
     766             :     else
     767             :     {
     768           0 :         ih.Get( 64, 64, IHi2_filename );
     769             : 
     770           0 :         if( IHi2_filename.substr(0,3) == "LNK" )
     771             :         {
     772           0 :             int link_segment = std::atoi( IHi2_filename.c_str() + 4 );
     773             : 
     774           0 :             file->DeleteSegment( link_segment );
     775             :         }
     776             : 
     777           0 :         IHi2_filename = filenameIn;
     778             :     }
     779             : 
     780             : /* -------------------------------------------------------------------- */
     781             : /*      Update the image header.                                        */
     782             : /* -------------------------------------------------------------------- */
     783             :     // IHi.2
     784           0 :     ih.Put( IHi2_filename.c_str(), 64, 64 );
     785             : 
     786             :     // IHi.6.1
     787           0 :     ih.Put( "", 168, 16 );
     788             : 
     789             :     // IHi.6.2
     790           0 :     ih.Put( "", 184, 8 );
     791             : 
     792             :     // IHi.6.3
     793           0 :     ih.Put( "", 192, 8 );
     794             : 
     795             :     // IHi.6.5
     796           0 :     ih.Put( "", 201, 1 );
     797             : 
     798             :     // IHi.6.7
     799           0 :     ih.Put( exoffIn, 250, 8 );
     800             : 
     801             :     // IHi.6.8
     802           0 :     ih.Put( eyoffIn, 258, 8 );
     803             : 
     804             :     // IHi.6.9
     805           0 :     ih.Put( exsizeIn, 266, 8 );
     806             : 
     807             :     // IHi.6.10
     808           0 :     ih.Put( eysizeIn, 274, 8 );
     809             : 
     810             :     // IHi.6.11
     811           0 :     ih.Put( echannelIn, 282, 8 );
     812             : 
     813           0 :     file->WriteToFile( ih.buffer, ih_offset, 1024 );
     814             : 
     815             : /* -------------------------------------------------------------------- */
     816             : /*      Update local configuration.                                     */
     817             : /* -------------------------------------------------------------------- */
     818           0 :     this->filename = file->GetInterfaces()->MergeRelativePath( file->GetInterfaces()->io,
     819           0 :                                         file->GetFilename(),
     820           0 :                                         filenameIn );
     821             : 
     822           0 :     this->exoff = exoffIn;
     823           0 :     this->eyoff = eyoffIn;
     824           0 :     this->exsize = exsizeIn;
     825           0 :     this->eysize = eysizeIn;
     826           0 :     this->echannel = echannelIn;
     827             : }

Generated by: LCOV version 1.14