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

Generated by: LCOV version 1.14