LTP GCOV extension - code coverage report
Current view: directory - frmts/pcidsk/sdk/channel - ctiledchannel.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 263
Code covered: 31.2 % Executed lines: 82

       1                 : /******************************************************************************
       2                 :  *
       3                 :  * Purpose:  Implementation of the CTiledChannel class.
       4                 :  *
       5                 :  * This class is used to implement band interleaved channels within a 
       6                 :  * PCIDSK file (which are always packed, and FILE interleaved data from
       7                 :  * external raw files which may not be packed. 
       8                 :  * 
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 2009
      11                 :  * PCI Geomatics, 50 West Wilmot Street, Richmond Hill, Ont, Canada
      12                 :  *
      13                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      14                 :  * copy of this software and associated documentation files (the "Software"),
      15                 :  * to deal in the Software without restriction, including without limitation
      16                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      17                 :  * and/or sell copies of the Software, and to permit persons to whom the
      18                 :  * Software is furnished to do so, subject to the following conditions:
      19                 :  *
      20                 :  * The above copyright notice and this permission notice shall be included
      21                 :  * in all copies or substantial portions of the Software.
      22                 :  *
      23                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      24                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      25                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      26                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      27                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      28                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      29                 :  * DEALINGS IN THE SOFTWARE.
      30                 :  ****************************************************************************/
      31                 : 
      32                 : #include "pcidsk_config.h"
      33                 : #include "pcidsk_types.h"
      34                 : #include "pcidsk_exception.h"
      35                 : #include "channel/ctiledchannel.h"
      36                 : #include "segment/sysblockmap.h"
      37                 : #include "core/sysvirtualfile.h"
      38                 : #include "core/cpcidskfile.h"
      39                 : #include "core/pcidsk_utils.h"
      40                 : #include <cassert>
      41                 : #include <cstdlib>
      42                 : #include <cstring>
      43                 : 
      44                 : using namespace PCIDSK;
      45                 : 
      46                 : /************************************************************************/
      47                 : /*                           CTiledChannel()                            */
      48                 : /************************************************************************/
      49                 : 
      50                 : CTiledChannel::CTiledChannel( PCIDSKBuffer &image_header, 
      51                 :                               uint64 ih_offset,
      52                 :                               PCIDSKBuffer &file_header,
      53                 :                               int channelnum,
      54                 :                               CPCIDSKFile *file,
      55               3 :                               eChanType pixel_type )

      56               3 :         : CPCIDSKChannel( image_header, ih_offset, file, pixel_type, channelnum)

      57                 : 
      58                 : {
      59               3 :     tile_info_dirty = false;

      60                 : 
      61                 : /* -------------------------------------------------------------------- */
      62                 : /*      Establish the virtual file we will be accessing.                */
      63                 : /* -------------------------------------------------------------------- */
      64               3 :     std::string filename;

      65                 : 
      66               3 :     image_header.Get(64,64,filename);

      67                 : 
      68               3 :     assert( strstr(filename.c_str(),"SIS=") != NULL );

      69                 : 
      70               3 :     image = atoi(strstr(filename.c_str(),"SIS=") + 4);

      71                 : 
      72               3 :     vfile = NULL;

      73                 : 
      74                 : /* -------------------------------------------------------------------- */
      75                 : /*      If this is an unassociated channel (ie. an overview), we        */
      76                 : /*      will set the size and blocksize values to someone               */
      77                 : /*      unreasonable and set them properly in EstablishAccess()         */
      78                 : /* -------------------------------------------------------------------- */
      79               3 :     if( channelnum == -1 )

      80                 :     {
      81               3 :         width = -1;

      82               3 :         height = -1;

      83               3 :         block_width = -1;

      84               3 :         block_height = -1;

      85               3 :     }

      86               3 : }

      87                 : 
      88                 : /************************************************************************/
      89                 : /*                           ~CTiledChannel()                           */
      90                 : /************************************************************************/
      91                 : 
      92               3 : CTiledChannel::~CTiledChannel()

      93                 : 
      94                 : {
      95               3 :     Synchronize();

      96               3 : }

      97                 : 
      98                 : /************************************************************************/
      99                 : /*                          EstablishAccess()                           */
     100                 : /************************************************************************/
     101                 : 
     102              12 : void CTiledChannel::EstablishAccess() const

     103                 : 
     104                 : {
     105              12 :     if( vfile != NULL )

     106               9 :         return;

     107                 :     
     108                 : /* -------------------------------------------------------------------- */
     109                 : /*      Establish the virtual file to access this image.                */
     110                 : /* -------------------------------------------------------------------- */
     111                 :     SysBlockMap *bmap = dynamic_cast<SysBlockMap*>(
     112               3 :         file->GetSegment( SEG_SYS, "SysBMDir" ));

     113                 : 
     114               3 :     if( bmap == NULL )

     115               0 :         ThrowPCIDSKException( "Unable to find SysBMDir segment." );

     116                 : 
     117               3 :     vfile = bmap->GetVirtualFile( image );

     118                 : 
     119                 : /* -------------------------------------------------------------------- */
     120                 : /*      Parse the header.                                               */
     121                 : /* -------------------------------------------------------------------- */
     122               3 :     PCIDSKBuffer theader(128);

     123               3 :     std::string data_type;

     124                 : 
     125               3 :     vfile->ReadFromFile( theader.buffer, 0, 128 );

     126                 : 
     127               3 :     width = theader.GetInt(0,8);

     128               3 :     height = theader.GetInt(8,8);

     129               3 :     block_width = theader.GetInt(16,8);

     130               3 :     block_height = theader.GetInt(24,8);

     131                 : 
     132               3 :     theader.Get(32,4,data_type);

     133               3 :     theader.Get(54, 8, compression);

     134                 :     
     135               3 :     pixel_type = GetDataTypeFromName(data_type);

     136               3 :     if (pixel_type == CHN_UNKNOWN)

     137                 :     {
     138                 :         ThrowPCIDSKException( "Unknown channel type: %s", 
     139               0 :                               data_type.c_str() );

     140                 :     }
     141                 : 
     142                 : /* -------------------------------------------------------------------- */
     143                 : /*      Extract the tile map                                            */
     144                 : /* -------------------------------------------------------------------- */
     145               3 :     int tiles_per_row = (width + block_width - 1) / block_width;

     146               3 :     int tiles_per_col = (height + block_height - 1) / block_height;

     147               3 :     int tile_count = tiles_per_row * tiles_per_col;

     148                 :     int i;
     149                 : 
     150               3 :     tile_offsets.resize( tile_count );

     151               3 :     tile_sizes.resize( tile_count );

     152                 : 
     153               3 :     PCIDSKBuffer tmap( tile_count * 20 );

     154                 : 
     155               3 :     vfile->ReadFromFile( tmap.buffer, 128, tile_count*20 );

     156                 :     
     157               6 :     for( i = 0; i < tile_count; i++ )

     158                 :     {
     159               3 :         tile_offsets[i] = tmap.GetUInt64( i*12 + 0, 12 );

     160               3 :         tile_sizes[i] = tmap.GetInt( tile_count*12 + i*8, 8 );

     161                 :     }
     162                 : 
     163               3 :     tile_info_dirty = false;

     164                 : 
     165                 : /* -------------------------------------------------------------------- */
     166                 : /*      Establish byte swapping.  Tiled data files are always big       */
     167                 : /*      endian, regardless of what the headers might imply.             */
     168                 : /* -------------------------------------------------------------------- */
     169               3 :     unsigned short test_value = 1;

     170                 :     
     171               3 :     if( ((uint8 *) &test_value)[0] == 1 )

     172               3 :         needs_swap = pixel_type != CHN_8U;

     173                 :     else
     174               0 :         needs_swap = false;

     175                 : }
     176                 : 
     177                 : /************************************************************************/
     178                 : /*                            Synchronize()                             */
     179                 : /*                                                                      */
     180                 : /*      Flush updated blockmap to disk if it is dirty.                  */
     181                 : /************************************************************************/
     182                 : 
     183               3 : void CTiledChannel::Synchronize()

     184                 : 
     185                 : {
     186               3 :     if( !tile_info_dirty )

     187               3 :         return;

     188                 : 
     189               0 :     int tiles_per_row = (width + block_width - 1) / block_width;

     190               0 :     int tiles_per_col = (height + block_height - 1) / block_height;

     191               0 :     int tile_count = tiles_per_row * tiles_per_col;

     192                 :     int i;
     193                 : 
     194               0 :     PCIDSKBuffer tmap( tile_count * 20 );

     195                 : 
     196               0 :     for( i = 0; i < tile_count; i++ )

     197                 :     {
     198               0 :         if( tile_offsets[i] == (uint64) -1 || tile_offsets[i] == 0 )

     199               0 :             tmap.Put( -1, i*12 + 0, 12 );

     200                 :         else
     201               0 :             tmap.Put( tile_offsets[i], i*12 + 0, 12 );

     202               0 :         tmap.Put( tile_sizes[i], tile_count*12 + i*8, 8 );

     203                 :     }
     204                 : 
     205               0 :     vfile->WriteToFile( tmap.buffer, 128, tile_count*20 );

     206               0 :     vfile->Synchronize();

     207                 : }
     208                 : 
     209                 : /************************************************************************/
     210                 : /*                             ReadBlock()                              */
     211                 : /************************************************************************/
     212                 : 
     213                 : int CTiledChannel::ReadBlock( int block_index, void *buffer,
     214                 :                               int xoff, int yoff, 
     215               1 :                               int xsize, int ysize )

     216                 : 
     217                 : {
     218               1 :     if( !vfile )

     219               0 :         EstablishAccess();

     220                 : 
     221               1 :     int pixel_size = DataTypeSize(GetType());

     222                 : 
     223                 : /* -------------------------------------------------------------------- */
     224                 : /*      Default window if needed.                                       */
     225                 : /* -------------------------------------------------------------------- */
     226               1 :     if( xoff == -1 && yoff == -1 && xsize == -1 && ysize == -1 )

     227                 :     {
     228               1 :         xoff = 0;

     229               1 :         yoff = 0;

     230               1 :         xsize = GetBlockWidth();

     231               1 :         ysize = GetBlockHeight();

     232                 :     }
     233                 : 
     234                 : /* -------------------------------------------------------------------- */
     235                 : /*      Validate Window                                                 */
     236                 : /* -------------------------------------------------------------------- */
     237               1 :     if( xoff < 0 || xoff + xsize > GetBlockWidth()

     238                 :         || yoff < 0 || yoff + ysize > GetBlockHeight() )
     239                 :     {
     240                 :         ThrowPCIDSKException( 
     241                 :             "Invalid window in ReadBloc(): xoff=%d,yoff=%d,xsize=%d,ysize=%d",
     242               0 :             xoff, yoff, xsize, ysize );

     243                 :     }
     244                 : 
     245               1 :     if( block_index < 0 || block_index >= (int) tile_offsets.size() )

     246                 :     {
     247                 :         ThrowPCIDSKException( "Requested non-existant block (%d)", 
     248               0 :                               block_index );

     249                 :     }
     250                 : 
     251                 : /* -------------------------------------------------------------------- */
     252                 : /*      Does this tile exist?  If not return a zeroed buffer.           */
     253                 : /* -------------------------------------------------------------------- */
     254               1 :     if( tile_sizes[block_index] == 0 )

     255                 :     {
     256               0 :         memset( buffer, 0, GetBlockWidth() * GetBlockHeight() * pixel_size );

     257               0 :         return 1;

     258                 :     }
     259                 : 
     260                 : /* -------------------------------------------------------------------- */
     261                 : /*      The simpliest case it an uncompressed direct and complete       */
     262                 : /*      tile read into the destination buffer.                          */
     263                 : /* -------------------------------------------------------------------- */
     264               1 :     if( xoff == 0 && xsize == GetBlockWidth() 

     265                 :         && yoff == 0 && ysize == GetBlockHeight() 
     266                 :         && tile_sizes[block_index] == xsize * ysize * pixel_size 
     267                 :         && compression == "NONE" )
     268                 :     {
     269                 :         vfile->ReadFromFile( buffer, 
     270                 :                              tile_offsets[block_index], 
     271               1 :                              tile_sizes[block_index] );

     272                 :         // Do byte swapping if needed.
     273               1 :         if( needs_swap )

     274               0 :             SwapPixels( buffer, pixel_type, xsize * ysize );

     275                 : 
     276               1 :         return 1;

     277                 :     }
     278                 : 
     279                 : /* -------------------------------------------------------------------- */
     280                 : /*      Load uncompressed data, one scanline at a time, into the        */
     281                 : /*      target buffer.                                                  */
     282                 : /* -------------------------------------------------------------------- */
     283               0 :     if( compression == "NONE" )

     284                 :     {
     285                 :         int iy;
     286                 : 
     287               0 :         for( iy = 0; iy < ysize; iy++ )

     288                 :         {
     289                 :             vfile->ReadFromFile( ((uint8 *) buffer) 
     290                 :                                  + iy * xsize * pixel_size,
     291                 :                                  tile_offsets[block_index] 
     292                 :                                  + ((iy+yoff)*block_width + xoff) * pixel_size,
     293               0 :                                  xsize * pixel_size );

     294                 :         }
     295                 :         
     296                 :         // Do byte swapping if needed.
     297               0 :         if( needs_swap )

     298               0 :             SwapPixels( buffer, pixel_type, xsize * ysize );

     299                 :         
     300               0 :         return 1;

     301                 :     }
     302                 : 
     303                 : /* -------------------------------------------------------------------- */
     304                 : /*      Load the whole compressed data into a working buffer.           */
     305                 : /* -------------------------------------------------------------------- */
     306               0 :     PCIDSKBuffer oCompressedData( tile_sizes[block_index] );

     307               0 :     PCIDSKBuffer oUncompressedData( pixel_size * block_width * block_height );

     308                 : 
     309                 :     vfile->ReadFromFile( oCompressedData.buffer, 
     310                 :                          tile_offsets[block_index], 
     311               0 :                          tile_sizes[block_index] );

     312                 :     
     313                 : /* -------------------------------------------------------------------- */
     314                 : /*      Handle decompression.                                           */
     315                 : /* -------------------------------------------------------------------- */
     316               0 :     if( compression == "RLE" )

     317                 :     {
     318               0 :         RLEDecompressBlock( oCompressedData, oUncompressedData );

     319                 :     }
     320               0 :     else if( strncmp(compression.c_str(),"JPEG",4) == 0 )

     321                 :     {
     322               0 :         JPEGDecompressBlock( oCompressedData, oUncompressedData );

     323                 :     }
     324                 :     else
     325                 :     {
     326                 :         ThrowPCIDSKException( 
     327                 :             "Unable to read tile of unsupported compression type: %s",
     328               0 :             compression.c_str() );

     329                 :     }
     330                 : 
     331                 : /* -------------------------------------------------------------------- */
     332                 : /*      Swap if necessary.  TODO: there is some reason to doubt that    */
     333                 : /*      the old implementation properly byte swapped compressed         */
     334                 : /*      data.  Perhaps this should be conditional?                      */
     335                 : /* -------------------------------------------------------------------- */
     336               0 :     if( needs_swap )

     337                 :         SwapPixels( oUncompressedData.buffer, pixel_type, 
     338               0 :                   GetBlockWidth() * GetBlockHeight() );

     339                 : 
     340                 : /* -------------------------------------------------------------------- */
     341                 : /*      Copy out the desired subwindow.                                 */
     342                 : /* -------------------------------------------------------------------- */
     343                 :     int iy;
     344                 :     
     345               0 :     for( iy = 0; iy < ysize; iy++ )

     346                 :     {
     347                 :         memcpy( ((uint8 *) buffer) + iy * xsize * pixel_size,
     348                 :                 oUncompressedData.buffer 
     349                 :                 + ((iy+yoff)*block_width + xoff) * pixel_size,
     350               0 :                 xsize * pixel_size );

     351                 :     }
     352                 : 
     353               0 :     return 1;

     354                 : }
     355                 : 
     356                 : /************************************************************************/
     357                 : /*                            IsTileEmpty()                             */
     358                 : /************************************************************************/
     359               0 : bool CTiledChannel::IsTileEmpty(void *buffer) const
     360                 : {
     361                 :     assert(sizeof(int32) == 4); // just to be on the safe side...
     362                 : 
     363                 :     unsigned int num_dword = 
     364               0 :         (block_width * block_height * DataTypeSize(pixel_type)) / 4;
     365                 :     unsigned int rem = 
     366               0 :         (block_width * block_height * DataTypeSize(pixel_type)) % 4;
     367                 : 
     368               0 :     int32* int_buf = reinterpret_cast<int32*>(buffer);
     369                 : 
     370               0 :     if (num_dword > 0) {
     371               0 :         for (unsigned int n = 0; n < num_dword; n++) {
     372               0 :             if (int_buf[n]) return false;
     373                 :         }
     374                 :     }
     375                 : 
     376               0 :     char* char_buf = reinterpret_cast<char*>(int_buf + num_dword);
     377               0 :     if (rem > 0) {
     378               0 :         for (unsigned int n = 0; n < rem; n++) {
     379               0 :             if (char_buf[n]) return false;
     380                 :         }
     381                 :     }
     382                 : 
     383               0 :     return true;
     384                 : }
     385                 : 
     386                 : /************************************************************************/
     387                 : /*                             WriteBlock()                             */
     388                 : /************************************************************************/
     389                 : 
     390               0 : int CTiledChannel::WriteBlock( int block_index, void *buffer )

     391                 : 
     392                 : {
     393               0 :     if( !vfile )

     394               0 :         EstablishAccess();

     395                 : 
     396               0 :     if( !file->GetUpdatable() )
     397               0 :         throw PCIDSKException( "File not open for update in WriteBlock()" );
     398                 : 
     399               0 :     InvalidateOverviews();
     400                 : 
     401               0 :     int pixel_size = DataTypeSize(GetType());

     402               0 :     int pixel_count = GetBlockWidth() * GetBlockHeight();

     403                 : 
     404               0 :     if( block_index < 0 || block_index >= (int) tile_offsets.size() )

     405                 :     {
     406                 :         ThrowPCIDSKException( "Requested non-existant block (%d)", 
     407               0 :                               block_index );

     408                 :     }
     409                 : 
     410                 : 
     411                 : /* -------------------------------------------------------------------- */
     412                 : /*      The simpliest case it an uncompressed direct and complete       */
     413                 : /*      tile read into the destination buffer.                          */
     414                 : /* -------------------------------------------------------------------- */
     415               0 :     if( compression == "NONE" 

     416                 :         && tile_sizes[block_index] == pixel_count * pixel_size )
     417                 :     {
     418                 :         // Do byte swapping if needed.
     419               0 :         if( needs_swap )

     420               0 :             SwapPixels( buffer, pixel_type, pixel_count );

     421                 : 
     422                 :         vfile->WriteToFile( buffer, 
     423                 :                             tile_offsets[block_index], 
     424               0 :                             tile_sizes[block_index] );

     425                 : 
     426               0 :         if( needs_swap )

     427               0 :             SwapPixels( buffer, pixel_type, pixel_count );

     428                 : 
     429               0 :         return 1;

     430                 :     }
     431                 : 
     432               0 :     if ((int)tile_offsets[block_index] == -1)
     433                 :     {
     434                 :         // Check if the tile is empty. If it is, we can skip writing it,
     435                 :         // unless the tile is already dirty.
     436               0 :         bool is_empty = IsTileEmpty(buffer);
     437                 : 
     438               0 :         if (is_empty) return 1; // we don't need to do anything else
     439                 :     }
     440                 : 
     441                 : /* -------------------------------------------------------------------- */
     442                 : /*      Copy the uncompressed data into a PCIDSKBuffer, and byte        */
     443                 : /*      swap if needed.                                                 */
     444                 : /* -------------------------------------------------------------------- */
     445               0 :     PCIDSKBuffer oUncompressedData( pixel_size * block_width * block_height );

     446                 : 
     447                 :     memcpy( oUncompressedData.buffer, buffer, 
     448               0 :             oUncompressedData.buffer_size );

     449                 : 
     450               0 :     if( needs_swap )

     451               0 :         SwapPixels( oUncompressedData.buffer, pixel_type, pixel_count );

     452                 : 
     453                 : /* -------------------------------------------------------------------- */
     454                 : /*      Compress the imagery.                                           */
     455                 : /* -------------------------------------------------------------------- */
     456               0 :     PCIDSKBuffer oCompressedData;

     457                 : 
     458               0 :     if( compression == "NONE" )

     459                 :     {
     460               0 :         oCompressedData = oUncompressedData;

     461                 :     }
     462               0 :     else if( compression == "RLE" )

     463                 :     {
     464               0 :         RLECompressBlock( oUncompressedData, oCompressedData );

     465                 :     }
     466               0 :     else if( strncmp(compression.c_str(),"JPEG",4) == 0 )

     467                 :     {
     468               0 :         JPEGCompressBlock( oUncompressedData, oCompressedData );

     469                 :     }
     470                 :     else
     471                 :     {
     472                 :         ThrowPCIDSKException( 
     473                 :             "Unable to write tile of unsupported compression type: %s",
     474               0 :             compression.c_str() );

     475                 :     }
     476                 : 
     477                 : /* -------------------------------------------------------------------- */
     478                 : /*      If this fits in the existing space, just write it directly.     */
     479                 : /* -------------------------------------------------------------------- */
     480               0 :     if( oCompressedData.buffer_size <= tile_sizes[block_index] )

     481                 :     {
     482                 :         vfile->WriteToFile( oCompressedData.buffer,
     483                 :                             tile_offsets[block_index], 
     484               0 :                             oCompressedData.buffer_size );

     485               0 :         tile_sizes[block_index] = oCompressedData.buffer_size;

     486                 :     }
     487                 : 
     488                 : /* -------------------------------------------------------------------- */
     489                 : /*      Otherwise we try and write it at the end of the virtual file.   */
     490                 : /* -------------------------------------------------------------------- */
     491                 :     else
     492                 :     {
     493               0 :         uint64 new_offset = vfile->GetLength();

     494                 :         
     495                 :         vfile->WriteToFile( oCompressedData.buffer, 
     496               0 :                             new_offset, oCompressedData.buffer_size );

     497                 : 
     498               0 :         tile_offsets[block_index] = new_offset;

     499               0 :         tile_sizes[block_index] = oCompressedData.buffer_size;

     500                 : 
     501                 :     }
     502                 : 
     503               0 :     tile_info_dirty = true;

     504                 : 
     505               0 :     return 1;

     506                 : }
     507                 : 
     508                 : /************************************************************************/
     509                 : /*                           GetBlockWidth()                            */
     510                 : /************************************************************************/
     511                 : 
     512               6 : int CTiledChannel::GetBlockWidth() const

     513                 : 
     514                 : {
     515               6 :     EstablishAccess();

     516               6 :     return CPCIDSKChannel::GetBlockWidth();

     517                 : }
     518                 : 
     519                 : /************************************************************************/
     520                 : /*                           GetBlockHeight()                           */
     521                 : /************************************************************************/
     522                 : 
     523               6 : int CTiledChannel::GetBlockHeight() const

     524                 : 
     525                 : {
     526               6 :     EstablishAccess();

     527               6 :     return CPCIDSKChannel::GetBlockHeight();

     528                 : }
     529                 : 
     530                 : /************************************************************************/
     531                 : /*                              GetWidth()                              */
     532                 : /************************************************************************/
     533                 : 
     534               3 : int CTiledChannel::GetWidth() const

     535                 : 
     536                 : {
     537               3 :     if( width == -1 )

     538               0 :         EstablishAccess();

     539                 : 
     540               3 :     return CPCIDSKChannel::GetWidth();

     541                 : }
     542                 : 
     543                 : /************************************************************************/
     544                 : /*                             GetHeight()                              */
     545                 : /************************************************************************/
     546                 : 
     547               3 : int CTiledChannel::GetHeight() const

     548                 : 
     549                 : {
     550               3 :     if( height == -1 )

     551               0 :         EstablishAccess();

     552                 : 
     553               3 :     return CPCIDSKChannel::GetHeight();

     554                 : }
     555                 : 
     556                 : /************************************************************************/
     557                 : /*                              GetType()                               */
     558                 : /************************************************************************/
     559                 : 
     560               8 : eChanType CTiledChannel::GetType() const

     561                 : 
     562                 : {
     563               8 :     if( pixel_type == CHN_UNKNOWN )

     564               0 :         EstablishAccess();

     565                 : 
     566               8 :     return CPCIDSKChannel::GetType();

     567                 : }
     568                 : 
     569                 : /************************************************************************/
     570                 : /*                         RLEDecompressBlock()                         */
     571                 : /************************************************************************/
     572                 : 
     573                 : void CTiledChannel::RLEDecompressBlock( PCIDSKBuffer &oCompressedData,
     574               0 :                                         PCIDSKBuffer &oDecompressedData )

     575                 : 
     576                 :                                
     577                 : {
     578               0 :     int    src_offset=0, dst_offset=0;

     579               0 :     uint8  *src = (uint8 *) oCompressedData.buffer;

     580               0 :     uint8  *dst = (uint8 *) oDecompressedData.buffer;

     581               0 :     int    pixel_size = DataTypeSize(GetType());

     582                 : 
     583                 : /* -------------------------------------------------------------------- */
     584                 : /*      Process till we are out of source data, or our destination      */
     585                 : /*      buffer is full.  These conditions should be satisified at       */
     586                 : /*      the same time!                                                  */
     587                 : /* -------------------------------------------------------------------- */
     588               0 :     while( src_offset + 1 + pixel_size <= oCompressedData.buffer_size

     589                 :            && dst_offset < oDecompressedData.buffer_size )
     590                 :     {
     591                 : /* -------------------------------------------------------------------- */
     592                 : /*      Extract a repeat run                                            */
     593                 : /* -------------------------------------------------------------------- */
     594               0 :         if( src[src_offset] > 127 )

     595                 :         {
     596               0 :             int count = src[src_offset++] - 128;

     597                 :             int i;
     598                 : 
     599               0 :             if( dst_offset + count * pixel_size > oDecompressedData.buffer_size)

     600                 :             {
     601               0 :                 ThrowPCIDSKException( "RLE compressed tile corrupt, overrun avoided." );

     602                 :             }
     603                 : 
     604               0 :             while( count-- > 0 )

     605                 :             {
     606               0 :                 for( i = 0; i < pixel_size; i++ )

     607               0 :                     dst[dst_offset++] = src[src_offset+i];

     608                 :             }
     609               0 :             src_offset += pixel_size;

     610                 :         }
     611                 : 
     612                 : /* -------------------------------------------------------------------- */
     613                 : /*      Extract a literal run.                                          */
     614                 : /* -------------------------------------------------------------------- */
     615                 :         else 
     616                 :         {
     617               0 :             int count = src[src_offset++];

     618                 : 
     619               0 :             if( dst_offset + count*pixel_size > oDecompressedData.buffer_size

     620                 :                 || src_offset + count*pixel_size > oCompressedData.buffer_size)
     621                 :             {
     622               0 :                 ThrowPCIDSKException( "RLE compressed tile corrupt, overrun avoided." );

     623                 :             }
     624                 : 
     625                 :             memcpy( dst + dst_offset, src + src_offset, 
     626               0 :                     pixel_size * count );

     627               0 :             src_offset += pixel_size * count;

     628               0 :             dst_offset += pixel_size * count;

     629                 :         }
     630                 : 
     631                 :     }
     632                 : 
     633                 : /* -------------------------------------------------------------------- */
     634                 : /*      Final validation.                                               */
     635                 : /* -------------------------------------------------------------------- */
     636               0 :     if( src_offset != oCompressedData.buffer_size 

     637                 :         || dst_offset != oDecompressedData.buffer_size ) 
     638                 :     {
     639               0 :         ThrowPCIDSKException( "RLE compressed tile corrupt, result incomplete." );

     640                 :     }
     641               0 : }

     642                 : 
     643                 : /************************************************************************/
     644                 : /*                         RLECompressBlock()                           */
     645                 : /*                                                                      */
     646                 : /*      TODO: There does not seem to be any byte order logic in here!   */
     647                 : /************************************************************************/
     648                 : 
     649                 : void CTiledChannel::RLECompressBlock( PCIDSKBuffer &oUncompressedData,
     650               0 :                                       PCIDSKBuffer &oCompressedData )

     651                 : 
     652                 :                                
     653                 : {
     654               0 :     int    src_bytes = oUncompressedData.buffer_size;

     655               0 :     int    pixel_size = DataTypeSize(GetType());

     656               0 :     int    src_offset = 0, dst_offset = 0;

     657                 :     int    i;
     658               0 :     uint8  *src = (uint8 *) oUncompressedData.buffer;

     659                 : 
     660                 : /* -------------------------------------------------------------------- */
     661                 : /*      Loop till input exausted.                                       */
     662                 : /* -------------------------------------------------------------------- */
     663               0 :     while( src_offset < src_bytes )

     664                 :     {
     665               0 :         bool  bGotARun = false;

     666                 :         
     667                 : /* -------------------------------------------------------------------- */
     668                 : /*  Establish the run length, and emit if greater than 3.     */
     669                 : /* -------------------------------------------------------------------- */
     670               0 :         if( src_offset + 3*pixel_size < src_bytes )

     671                 :         {
     672               0 :             int   count = 1;

     673                 : 
     674               0 :             while( count < 127

     675                 :                    && src_offset + count*pixel_size < src_bytes )
     676                 :             {
     677               0 :                 bool  bWordMatch = true;

     678                 : 
     679               0 :                 for( i = 0; i < pixel_size; i++ )

     680                 :                 {
     681               0 :                     if( src[src_offset+i] 

     682                 :                         != src[src_offset+i+count*pixel_size] )
     683               0 :                         bWordMatch = false;

     684                 :                 }
     685                 : 
     686               0 :                 if( !bWordMatch )

     687               0 :                     break;

     688                 : 
     689               0 :                 count++;

     690                 :             }
     691                 : 
     692               0 :             if( count >= 3 )

     693                 :             {
     694               0 :                 if( oCompressedData.buffer_size < dst_offset + pixel_size+1 )

     695               0 :                     oCompressedData.SetSize( oCompressedData.buffer_size*2+100);

     696                 : 
     697               0 :                 oCompressedData.buffer[dst_offset++] = count+128;

     698                 : 
     699               0 :                 for( i = 0; i < pixel_size; i++ )

     700               0 :                     oCompressedData.buffer[dst_offset++] = src[src_offset+i];

     701                 : 
     702               0 :                 src_offset += count * pixel_size;

     703                 : 
     704               0 :                 bGotARun = true;

     705                 :             }
     706                 :             else
     707               0 :                 bGotARun = false;

     708                 :         }
     709                 :         
     710                 : /* -------------------------------------------------------------------- */
     711                 : /*      Otherwise emit a literal till we encounter at least a three */
     712                 : /*  word series.              */
     713                 : /* -------------------------------------------------------------------- */
     714               0 :         if( !bGotARun )

     715                 :         {
     716               0 :             int   count = 1;

     717               0 :             int   match_count = 0;

     718                 : 
     719               0 :             while( count < 127

     720                 :                    && src_offset + count*pixel_size < src_bytes )
     721                 :             {
     722               0 :                 bool  bWordMatch = true;

     723                 : 
     724               0 :                 for( i = 0; i < pixel_size; i++ )

     725                 :                 {
     726               0 :                     if( src[src_offset+i]

     727                 :                         != src[src_offset+i+count*pixel_size] )
     728               0 :                         bWordMatch = false;

     729                 :                 }
     730                 : 
     731               0 :                 if( bWordMatch )

     732               0 :                     match_count++;

     733                 :                 else
     734               0 :                     match_count = 0;

     735                 : 
     736               0 :                 if( match_count > 2 )

     737               0 :                     break;

     738                 : 
     739               0 :                 count++;

     740                 :             }
     741                 :             
     742               0 :             assert( src_offset + count*pixel_size <= src_bytes );

     743                 : 
     744               0 :             while( oCompressedData.buffer_size 

     745                 :                    < dst_offset + count*pixel_size+1 )
     746               0 :                 oCompressedData.SetSize( oCompressedData.buffer_size*2+100 );

     747                 : 
     748               0 :             oCompressedData.buffer[dst_offset++] = count;

     749                 :             memcpy( oCompressedData.buffer + dst_offset, 
     750                 :                     src + src_offset, 
     751               0 :                     count * pixel_size );

     752               0 :             src_offset += count * pixel_size;

     753               0 :             dst_offset += count * pixel_size;

     754                 :         }
     755                 :     }
     756                 : 
     757               0 :     oCompressedData.buffer_size = dst_offset;

     758               0 : }

     759                 : 
     760                 : /************************************************************************/
     761                 : /*                        JPEGDecompressBlock()                         */
     762                 : /************************************************************************/
     763                 : 
     764                 : void CTiledChannel::JPEGDecompressBlock( PCIDSKBuffer &oCompressedData,
     765               0 :                                          PCIDSKBuffer &oDecompressedData )

     766                 : 
     767                 :                                
     768                 : {
     769               0 :     if( file->GetInterfaces()->JPEGDecompressBlock == NULL )

     770               0 :         ThrowPCIDSKException( "JPEG decompression not enabled in the PCIDSKInterfaces of this build." );

     771                 : 
     772                 :     file->GetInterfaces()->JPEGDecompressBlock( 
     773                 :         (uint8 *) oCompressedData.buffer, oCompressedData.buffer_size,
     774                 :         (uint8 *) oDecompressedData.buffer, oDecompressedData.buffer_size,
     775               0 :         GetBlockWidth(), GetBlockHeight(), GetType() );

     776               0 : }

     777                 : 
     778                 : /************************************************************************/
     779                 : /*                         JPEGCompressBlock()                          */
     780                 : /************************************************************************/
     781                 : 
     782                 : void CTiledChannel::JPEGCompressBlock( PCIDSKBuffer &oDecompressedData,
     783               0 :                                        PCIDSKBuffer &oCompressedData )

     784                 :                                        
     785                 : 
     786                 :                                
     787                 : {
     788               0 :     if( file->GetInterfaces()->JPEGCompressBlock == NULL )

     789               0 :         ThrowPCIDSKException( "JPEG compression not enabled in the PCIDSKInterfaces of this build." );

     790                 : 
     791                 : /* -------------------------------------------------------------------- */
     792                 : /*      What quality should we be using?                                */
     793                 : /* -------------------------------------------------------------------- */
     794               0 :     int quality = 75;

     795                 : 
     796               0 :     if( compression.c_str()[4] >= '1' 

     797                 :         && compression.c_str()[4] <= '0' )
     798               0 :         quality = atoi(compression.c_str() + 4);

     799                 : 
     800                 : /* -------------------------------------------------------------------- */
     801                 : /*      Make the output buffer plent big to hold any conceivable        */
     802                 : /*      result.                                                         */
     803                 : /* -------------------------------------------------------------------- */
     804               0 :     oCompressedData.SetSize( oDecompressedData.buffer_size * 2 + 1000 );

     805                 : 
     806                 : /* -------------------------------------------------------------------- */
     807                 : /*      invoke.                                                         */
     808                 : /* -------------------------------------------------------------------- */
     809                 :     file->GetInterfaces()->JPEGCompressBlock( 
     810                 :         (uint8 *) oDecompressedData.buffer, oDecompressedData.buffer_size,
     811                 :         (uint8 *) oCompressedData.buffer, oCompressedData.buffer_size,
     812               0 :         GetBlockWidth(), GetBlockHeight(), GetType(), 75 );

     813               0 : }

     814                 : 

Generated by: LTP GCOV extension version 1.5