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

Generated by: LCOV version 1.14