LCOV - code coverage report
Current view: directory - frmts/pcidsk/sdk/channel - ctiledchannel.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 257 84 32.7 %
Date: 2010-01-09 Functions: 16 11 68.8 %

       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               3 : CTiledChannel::CTiledChannel( PCIDSKBuffer &image_header, 
      51                 :                               PCIDSKBuffer &file_header,
      52                 :                               int channelnum,
      53                 :                               CPCIDSKFile *file,
      54                 :                               eChanType pixel_type )
      55               3 :         : CPCIDSKChannel( image_header, file, pixel_type, channelnum )
      56                 : 
      57                 : {
      58               3 :     tile_info_dirty = false;
      59                 : 
      60                 : /* -------------------------------------------------------------------- */
      61                 : /*      Establish the virtual file we will be accessing.                */
      62                 : /* -------------------------------------------------------------------- */
      63               3 :     std::string filename;
      64                 : 
      65               3 :     image_header.Get(64,64,filename);
      66                 : 
      67               3 :     assert( strstr(filename.c_str(),"SIS=") != NULL );
      68                 : 
      69               3 :     image = atoi(strstr(filename.c_str(),"SIS=") + 4);
      70                 : 
      71               3 :     vfile = NULL;
      72                 : 
      73                 : /* -------------------------------------------------------------------- */
      74                 : /*      If this is an unassociated channel (ie. an overview), we        */
      75                 : /*      will set the size and blocksize values to someone               */
      76                 : /*      unreasonable and set them properly in EstablishAccess()         */
      77                 : /* -------------------------------------------------------------------- */
      78               3 :     if( channelnum == -1 )
      79                 :     {
      80               3 :         width = -1;
      81               3 :         height = -1;
      82               3 :         block_width = -1;
      83               3 :         block_height = -1;
      84               3 :     }
      85               3 : }
      86                 : 
      87                 : /************************************************************************/
      88                 : /*                           ~CTiledChannel()                           */
      89                 : /************************************************************************/
      90                 : 
      91               6 : CTiledChannel::~CTiledChannel()
      92                 : 
      93                 : {
      94               3 :     Sync();
      95               6 : }
      96                 : 
      97                 : /************************************************************************/
      98                 : /*                          EstablishAccess()                           */
      99                 : /************************************************************************/
     100                 : 
     101              12 : void CTiledChannel::EstablishAccess()
     102                 : 
     103                 : {
     104              12 :     if( vfile != NULL )
     105               9 :         return;
     106                 :     
     107                 : /* -------------------------------------------------------------------- */
     108                 : /*      Establish the virtual file to access this image.                */
     109                 : /* -------------------------------------------------------------------- */
     110                 :     SysBlockMap *bmap = dynamic_cast<SysBlockMap*>(
     111               3 :         file->GetSegment( SEG_SYS, "SysBMDir" ));
     112                 : 
     113               3 :     if( bmap == NULL )
     114               0 :         ThrowPCIDSKException( "Unable to find SysBMDir segment." );
     115                 : 
     116               3 :     vfile = bmap->GetVirtualFile( image );
     117                 : 
     118                 : /* -------------------------------------------------------------------- */
     119                 : /*      Parse the header.                                               */
     120                 : /* -------------------------------------------------------------------- */
     121               3 :     PCIDSKBuffer theader(128);
     122               3 :     std::string data_type;
     123                 : 
     124               3 :     vfile->ReadFromFile( theader.buffer, 0, 128 );
     125                 : 
     126               3 :     width = theader.GetInt(0,8);
     127               3 :     height = theader.GetInt(8,8);
     128               3 :     block_width = theader.GetInt(16,8);
     129               3 :     block_height = theader.GetInt(24,8);
     130                 : 
     131               3 :     theader.Get(32,4,data_type);
     132               3 :     theader.Get(54, 8, compression);
     133                 :     
     134               3 :     if( data_type == "8U" )
     135               3 :         pixel_type = CHN_8U;
     136               0 :     else if( data_type == "16S" )
     137               0 :         pixel_type = CHN_16S;
     138               0 :     else if( data_type == "16U" )
     139               0 :         pixel_type = CHN_16U;
     140               0 :     else if( data_type == "32R" )
     141               0 :         pixel_type = CHN_32R;
     142                 :     else
     143                 :     {
     144                 :         ThrowPCIDSKException( "Unknown channel type: %s", 
     145               0 :                               data_type.c_str() );
     146                 :     }
     147                 : 
     148                 : /* -------------------------------------------------------------------- */
     149                 : /*      Extract the tile map                                            */
     150                 : /* -------------------------------------------------------------------- */
     151               3 :     int tiles_per_row = (width + block_width - 1) / block_width;
     152               3 :     int tiles_per_col = (height + block_height - 1) / block_height;
     153               3 :     int tile_count = tiles_per_row * tiles_per_col;
     154                 :     int i;
     155                 : 
     156               3 :     tile_offsets.resize( tile_count );
     157               3 :     tile_sizes.resize( tile_count );
     158                 : 
     159               3 :     PCIDSKBuffer tmap( tile_count * 20 );
     160                 : 
     161               3 :     vfile->ReadFromFile( tmap.buffer, 128, tile_count*20 );
     162                 :     
     163               6 :     for( i = 0; i < tile_count; i++ )
     164                 :     {
     165               3 :         tile_offsets[i] = tmap.GetUInt64( i*12 + 0, 12 );
     166               3 :         tile_sizes[i] = tmap.GetInt( tile_count*12 + i*8, 8 );
     167                 :     }
     168                 : 
     169               3 :     tile_info_dirty = false;
     170                 : 
     171                 : /* -------------------------------------------------------------------- */
     172                 : /*      Establish byte swapping.  Tiled data files are always big       */
     173                 : /*      endian, regardless of what the headers might imply.             */
     174                 : /* -------------------------------------------------------------------- */
     175               3 :     unsigned short test_value = 1;
     176                 :     
     177               3 :     if( ((uint8 *) &test_value)[0] == 1 )
     178               3 :         needs_swap = pixel_type != CHN_8U;
     179                 :     else
     180               0 :         needs_swap = false;
     181                 : }
     182                 : 
     183                 : /************************************************************************/
     184                 : /*                                Sync()                                */
     185                 : /*                                                                      */
     186                 : /*      Flush updated blockmap to disk if it is dirty.                  */
     187                 : /************************************************************************/
     188                 : 
     189               3 : void CTiledChannel::Sync()
     190                 : 
     191                 : {
     192               3 :     if( !tile_info_dirty )
     193               3 :         return;
     194                 : 
     195               0 :     int tiles_per_row = (width + block_width - 1) / block_width;
     196               0 :     int tiles_per_col = (height + block_height - 1) / block_height;
     197               0 :     int tile_count = tiles_per_row * tiles_per_col;
     198                 :     int i;
     199                 : 
     200               0 :     PCIDSKBuffer tmap( tile_count * 20 );
     201                 : 
     202               0 :     for( i = 0; i < tile_count; i++ )
     203                 :     {
     204               0 :         if( tile_offsets[i] == (uint64) -1 || tile_offsets[i] == 0 )
     205               0 :             tmap.Put( -1, i*12 + 0, 12 );
     206                 :         else
     207               0 :             tmap.Put( tile_offsets[i], i*12 + 0, 12 );
     208               0 :         tmap.Put( tile_sizes[i], tile_count*12 + i*8, 8 );
     209                 :     }
     210                 : 
     211               0 :     vfile->WriteToFile( tmap.buffer, 128, tile_count*20 );
     212                 : }
     213                 : 
     214                 : /************************************************************************/
     215                 : /*                             ReadBlock()                              */
     216                 : /************************************************************************/
     217                 : 
     218               1 : int CTiledChannel::ReadBlock( int block_index, void *buffer,
     219                 :                               int xoff, int yoff, 
     220                 :                               int xsize, int ysize )
     221                 : 
     222                 : {
     223               1 :     if( !vfile )
     224               0 :         EstablishAccess();
     225                 : 
     226               1 :     int pixel_size = DataTypeSize(GetType());
     227                 : 
     228                 : /* -------------------------------------------------------------------- */
     229                 : /*      Default window if needed.                                       */
     230                 : /* -------------------------------------------------------------------- */
     231               1 :     if( xoff == -1 && yoff == -1 && xsize == -1 && ysize == -1 )
     232                 :     {
     233               1 :         xoff = 0;
     234               1 :         yoff = 0;
     235               1 :         xsize = GetBlockWidth();
     236               1 :         ysize = GetBlockHeight();
     237                 :     }
     238                 : 
     239                 : /* -------------------------------------------------------------------- */
     240                 : /*      Validate Window                                                 */
     241                 : /* -------------------------------------------------------------------- */
     242               2 :     if( xoff < 0 || xoff + xsize > GetBlockWidth()
     243               1 :         || yoff < 0 || yoff + ysize > GetBlockHeight() )
     244                 :     {
     245                 :         ThrowPCIDSKException( 
     246                 :             "Invalid window in ReadBloc(): xoff=%d,yoff=%d,xsize=%d,ysize=%d",
     247               0 :             xoff, yoff, xsize, ysize );
     248                 :     }
     249                 : 
     250               1 :     if( block_index < 0 || block_index >= (int) tile_offsets.size() )
     251                 :     {
     252                 :         ThrowPCIDSKException( "Requested non-existant block (%d)", 
     253               0 :                               block_index );
     254                 :     }
     255                 : 
     256                 : /* -------------------------------------------------------------------- */
     257                 : /*      Does this tile exist?  If not return a zeroed buffer.           */
     258                 : /* -------------------------------------------------------------------- */
     259               1 :     if( tile_sizes[block_index] == 0 )
     260                 :     {
     261               0 :         memset( buffer, 0, GetBlockWidth() * GetBlockHeight() * pixel_size );
     262               0 :         return 1;
     263                 :     }
     264                 : 
     265                 : /* -------------------------------------------------------------------- */
     266                 : /*      The simpliest case it an uncompressed direct and complete       */
     267                 : /*      tile read into the destination buffer.                          */
     268                 : /* -------------------------------------------------------------------- */
     269               2 :     if( xoff == 0 && xsize == GetBlockWidth() 
     270               1 :         && yoff == 0 && ysize == GetBlockHeight() 
     271                 :         && tile_sizes[block_index] == xsize * ysize * pixel_size 
     272                 :         && compression == "NONE" )
     273                 :     {
     274                 :         vfile->ReadFromFile( buffer, 
     275                 :                              tile_offsets[block_index], 
     276               1 :                              tile_sizes[block_index] );
     277                 :         // Do byte swapping if needed.
     278               1 :         if( needs_swap )
     279               0 :             SwapData( buffer, pixel_size, xsize * ysize );
     280                 : 
     281               1 :         return 1;
     282                 :     }
     283                 : 
     284                 : /* -------------------------------------------------------------------- */
     285                 : /*      Load uncompressed data, one scanline at a time, into the        */
     286                 : /*      target buffer.                                                  */
     287                 : /* -------------------------------------------------------------------- */
     288               0 :     if( compression == "NONE" )
     289                 :     {
     290                 :         int iy;
     291                 : 
     292               0 :         for( iy = 0; iy < ysize; iy++ )
     293                 :         {
     294                 :             vfile->ReadFromFile( ((uint8 *) buffer) 
     295                 :                                  + iy * xsize * pixel_size,
     296                 :                                  tile_offsets[block_index] 
     297                 :                                  + ((iy+yoff)*block_width + xoff) * pixel_size,
     298               0 :                                  xsize * pixel_size );
     299                 :         }
     300                 :         
     301                 :         // Do byte swapping if needed.
     302               0 :         if( needs_swap )
     303               0 :             SwapData( buffer, pixel_size, xsize * ysize );
     304                 :         
     305               0 :         return 1;
     306                 :     }
     307                 : 
     308                 : /* -------------------------------------------------------------------- */
     309                 : /*      Load the whole compressed data into a working buffer.           */
     310                 : /* -------------------------------------------------------------------- */
     311               0 :     PCIDSKBuffer oCompressedData( tile_sizes[block_index] );
     312               0 :     PCIDSKBuffer oUncompressedData( pixel_size * block_width * block_height );
     313                 : 
     314                 :     vfile->ReadFromFile( oCompressedData.buffer, 
     315                 :                          tile_offsets[block_index], 
     316               0 :                          tile_sizes[block_index] );
     317                 :     
     318                 : /* -------------------------------------------------------------------- */
     319                 : /*      Handle decompression.                                           */
     320                 : /* -------------------------------------------------------------------- */
     321               0 :     if( compression == "RLE" )
     322                 :     {
     323               0 :         RLEDecompressBlock( oCompressedData, oUncompressedData );
     324                 :     }
     325               0 :     else if( strncmp(compression.c_str(),"JPEG",4) == 0 )
     326                 :     {
     327               0 :         JPEGDecompressBlock( oCompressedData, oUncompressedData );
     328                 :     }
     329                 :     else
     330                 :     {
     331                 :         ThrowPCIDSKException( 
     332                 :             "Unable to read tile of unsupported compression type: %s",
     333               0 :             compression.c_str() );
     334                 :     }
     335                 : 
     336                 : /* -------------------------------------------------------------------- */
     337                 : /*      Swap if necessary.  TODO: there is some reason to doubt that    */
     338                 : /*      the old implementation properly byte swapped compressed         */
     339                 : /*      data.  Perhaps this should be conditional?                      */
     340                 : /* -------------------------------------------------------------------- */
     341               0 :     if( needs_swap )
     342                 :         SwapData( oUncompressedData.buffer, pixel_size, 
     343               0 :                   GetBlockWidth() * GetBlockHeight() );
     344                 : 
     345                 : /* -------------------------------------------------------------------- */
     346                 : /*      Copy out the desired subwindow.                                 */
     347                 : /* -------------------------------------------------------------------- */
     348                 :     int iy;
     349                 :     
     350               0 :     for( iy = 0; iy < ysize; iy++ )
     351                 :     {
     352                 :         memcpy( ((uint8 *) buffer) + iy * xsize * pixel_size,
     353                 :                 oUncompressedData.buffer 
     354                 :                 + ((iy+yoff)*block_width + xoff) * pixel_size,
     355               0 :                 xsize * pixel_size );
     356                 :     }
     357                 : 
     358               0 :     return 1;
     359                 : }
     360                 : 
     361                 : /************************************************************************/
     362                 : /*                             WriteBlock()                             */
     363                 : /************************************************************************/
     364                 : 
     365               0 : int CTiledChannel::WriteBlock( int block_index, void *buffer )
     366                 : 
     367                 : {
     368               0 :     if( !vfile )
     369               0 :         EstablishAccess();
     370                 : 
     371               0 :     int pixel_size = DataTypeSize(GetType());
     372               0 :     int pixel_count = GetBlockWidth() * GetBlockHeight();
     373                 : 
     374               0 :     if( block_index < 0 || block_index >= (int) tile_offsets.size() )
     375                 :     {
     376                 :         ThrowPCIDSKException( "Requested non-existant block (%d)", 
     377               0 :                               block_index );
     378                 :     }
     379                 : 
     380                 : /* -------------------------------------------------------------------- */
     381                 : /*      The simpliest case it an uncompressed direct and complete       */
     382                 : /*      tile read into the destination buffer.                          */
     383                 : /* -------------------------------------------------------------------- */
     384               0 :     if( compression == "NONE" 
     385                 :         && tile_sizes[block_index] == pixel_count * pixel_size )
     386                 :     {
     387                 :         // Do byte swapping if needed.
     388               0 :         if( needs_swap )
     389               0 :             SwapData( buffer, pixel_size, pixel_count );
     390                 : 
     391                 :         vfile->WriteToFile( buffer, 
     392                 :                             tile_offsets[block_index], 
     393               0 :                             tile_sizes[block_index] );
     394                 : 
     395               0 :         if( needs_swap )
     396               0 :             SwapData( buffer, pixel_size, pixel_count );
     397                 : 
     398               0 :         return 1;
     399                 :     }
     400                 : 
     401                 : /* -------------------------------------------------------------------- */
     402                 : /*      Copy the uncompressed data into a PCIDSKBuffer, and byte        */
     403                 : /*      swap if needed.                                                 */
     404                 : /* -------------------------------------------------------------------- */
     405               0 :     PCIDSKBuffer oUncompressedData( pixel_size * block_width * block_height );
     406                 : 
     407                 :     memcpy( oUncompressedData.buffer, buffer, 
     408               0 :             oUncompressedData.buffer_size );
     409                 : 
     410               0 :     if( needs_swap )
     411               0 :         SwapData( oUncompressedData.buffer, pixel_size, pixel_count );
     412                 : 
     413                 : /* -------------------------------------------------------------------- */
     414                 : /*      Compress the imagery.                                           */
     415                 : /* -------------------------------------------------------------------- */
     416               0 :     PCIDSKBuffer oCompressedData;
     417                 : 
     418               0 :     if( compression == "NONE" )
     419                 :     {
     420               0 :         oCompressedData = oUncompressedData;
     421                 :     }
     422               0 :     else if( compression == "RLE" )
     423                 :     {
     424               0 :         RLECompressBlock( oUncompressedData, oCompressedData );
     425                 :     }
     426               0 :     else if( strncmp(compression.c_str(),"JPEG",4) == 0 )
     427                 :     {
     428               0 :         JPEGCompressBlock( oUncompressedData, oCompressedData );
     429                 :     }
     430                 :     else
     431                 :     {
     432                 :         ThrowPCIDSKException( 
     433                 :             "Unable to write tile of unsupported compression type: %s",
     434               0 :             compression.c_str() );
     435                 :     }
     436                 : 
     437                 : /* -------------------------------------------------------------------- */
     438                 : /*      If this fits in the existing space, just write it directly.     */
     439                 : /* -------------------------------------------------------------------- */
     440               0 :     if( oCompressedData.buffer_size <= tile_sizes[block_index] )
     441                 :     {
     442                 :         vfile->WriteToFile( oCompressedData.buffer,
     443                 :                             tile_offsets[block_index], 
     444               0 :                             oCompressedData.buffer_size );
     445               0 :         tile_sizes[block_index] = oCompressedData.buffer_size;
     446                 :     }
     447                 : 
     448                 : /* -------------------------------------------------------------------- */
     449                 : /*      Otherwise we try and write it at the end of the virtual file.   */
     450                 : /* -------------------------------------------------------------------- */
     451                 :     else
     452                 :     {
     453               0 :         uint64 new_offset = vfile->GetLength();
     454                 :         
     455                 :         vfile->WriteToFile( oCompressedData.buffer, 
     456               0 :                             new_offset, oCompressedData.buffer_size );
     457                 : 
     458               0 :         tile_offsets[block_index] = new_offset;
     459               0 :         tile_sizes[block_index] = oCompressedData.buffer_size;
     460                 : 
     461                 :     }
     462                 : 
     463               0 :     tile_info_dirty = true;
     464                 : 
     465               0 :     return 1;
     466                 : }
     467                 : 
     468                 : /************************************************************************/
     469                 : /*                           GetBlockWidth()                            */
     470                 : /************************************************************************/
     471                 : 
     472               6 : int CTiledChannel::GetBlockWidth()
     473                 : 
     474                 : {
     475               6 :     EstablishAccess();
     476               6 :     return CPCIDSKChannel::GetBlockWidth();
     477                 : }
     478                 : 
     479                 : /************************************************************************/
     480                 : /*                           GetBlockHeight()                           */
     481                 : /************************************************************************/
     482                 : 
     483               6 : int CTiledChannel::GetBlockHeight()
     484                 : 
     485                 : {
     486               6 :     EstablishAccess();
     487               6 :     return CPCIDSKChannel::GetBlockHeight();
     488                 : }
     489                 : 
     490                 : /************************************************************************/
     491                 : /*                              GetWidth()                              */
     492                 : /************************************************************************/
     493                 : 
     494               3 : int CTiledChannel::GetWidth()
     495                 : 
     496                 : {
     497               3 :     if( width == -1 )
     498               0 :         EstablishAccess();
     499                 : 
     500               3 :     return CPCIDSKChannel::GetWidth();
     501                 : }
     502                 : 
     503                 : /************************************************************************/
     504                 : /*                             GetHeight()                              */
     505                 : /************************************************************************/
     506                 : 
     507               3 : int CTiledChannel::GetHeight()
     508                 : 
     509                 : {
     510               3 :     if( height == -1 )
     511               0 :         EstablishAccess();
     512                 : 
     513               3 :     return CPCIDSKChannel::GetHeight();
     514                 : }
     515                 : 
     516                 : /************************************************************************/
     517                 : /*                              GetType()                               */
     518                 : /************************************************************************/
     519                 : 
     520               4 : eChanType CTiledChannel::GetType()
     521                 : 
     522                 : {
     523               4 :     if( pixel_type == CHN_UNKNOWN )
     524               0 :         EstablishAccess();
     525                 : 
     526               4 :     return CPCIDSKChannel::GetType();
     527                 : }
     528                 : 
     529                 : /************************************************************************/
     530                 : /*                         RLEDecompressBlock()                         */
     531                 : /************************************************************************/
     532                 : 
     533               0 : void CTiledChannel::RLEDecompressBlock( PCIDSKBuffer &oCompressedData,
     534                 :                                         PCIDSKBuffer &oDecompressedData )
     535                 : 
     536                 :                                
     537                 : {
     538               0 :     int    src_offset=0, dst_offset=0;
     539               0 :     uint8  *src = (uint8 *) oCompressedData.buffer;
     540               0 :     uint8  *dst = (uint8 *) oDecompressedData.buffer;
     541               0 :     int    pixel_size = DataTypeSize(GetType());
     542                 : 
     543                 : /* -------------------------------------------------------------------- */
     544                 : /*      Process till we are out of source data, or our destination      */
     545                 : /*      buffer is full.  These conditions should be satisified at       */
     546                 : /*      the same time!                                                  */
     547                 : /* -------------------------------------------------------------------- */
     548               0 :     while( src_offset + 1 + pixel_size <= oCompressedData.buffer_size
     549                 :            && dst_offset < oDecompressedData.buffer_size )
     550                 :     {
     551                 : /* -------------------------------------------------------------------- */
     552                 : /*      Extract a repeat run                                            */
     553                 : /* -------------------------------------------------------------------- */
     554               0 :         if( src[src_offset] > 127 )
     555                 :         {
     556               0 :             int count = src[src_offset++] - 128;
     557                 :             int i;
     558                 : 
     559               0 :             if( dst_offset + count * pixel_size > oDecompressedData.buffer_size)
     560                 :             {
     561               0 :                 ThrowPCIDSKException( "RLE compressed tile corrupt, overrun avoided." );
     562                 :             }
     563                 : 
     564               0 :             while( count-- > 0 )
     565                 :             {
     566               0 :                 for( i = 0; i < pixel_size; i++ )
     567               0 :                     dst[dst_offset++] = src[src_offset+i];
     568                 :             }
     569               0 :             src_offset += pixel_size;
     570                 :         }
     571                 : 
     572                 : /* -------------------------------------------------------------------- */
     573                 : /*      Extract a literal run.                                          */
     574                 : /* -------------------------------------------------------------------- */
     575                 :         else 
     576                 :         {
     577               0 :             int count = src[src_offset++];
     578                 : 
     579               0 :             if( dst_offset + count*pixel_size > oDecompressedData.buffer_size
     580                 :                 || src_offset + count*pixel_size > oCompressedData.buffer_size)
     581                 :             {
     582               0 :                 ThrowPCIDSKException( "RLE compressed tile corrupt, overrun avoided." );
     583                 :             }
     584                 : 
     585                 :             memcpy( dst + dst_offset, src + src_offset, 
     586               0 :                     pixel_size * count );
     587               0 :             src_offset += pixel_size * count;
     588               0 :             dst_offset += pixel_size * count;
     589                 :         }
     590                 : 
     591                 :     }
     592                 : 
     593                 : /* -------------------------------------------------------------------- */
     594                 : /*      Final validation.                                               */
     595                 : /* -------------------------------------------------------------------- */
     596               0 :     if( src_offset != oCompressedData.buffer_size 
     597                 :         || dst_offset != oDecompressedData.buffer_size ) 
     598                 :     {
     599               0 :         ThrowPCIDSKException( "RLE compressed tile corrupt, result incomplete." );
     600                 :     }
     601               0 : }
     602                 : 
     603                 : /************************************************************************/
     604                 : /*                         RLECompressBlock()                           */
     605                 : /*                                                                      */
     606                 : /*      TODO: There does not seem to be any byte order logic in here!   */
     607                 : /************************************************************************/
     608                 : 
     609               0 : void CTiledChannel::RLECompressBlock( PCIDSKBuffer &oUncompressedData,
     610                 :                                       PCIDSKBuffer &oCompressedData )
     611                 : 
     612                 :                                
     613                 : {
     614               0 :     int    src_bytes = oUncompressedData.buffer_size;
     615               0 :     int    pixel_size = DataTypeSize(GetType());
     616               0 :     int    src_offset = 0, dst_offset = 0;
     617                 :     int    i;
     618               0 :     uint8  *src = (uint8 *) oUncompressedData.buffer;
     619                 : 
     620                 : /* -------------------------------------------------------------------- */
     621                 : /*      Loop till input exausted.                                       */
     622                 : /* -------------------------------------------------------------------- */
     623               0 :     while( src_offset < src_bytes )
     624                 :     {
     625               0 :         bool  bGotARun = false;
     626                 :         
     627                 : /* -------------------------------------------------------------------- */
     628                 : /*  Establish the run length, and emit if greater than 3.     */
     629                 : /* -------------------------------------------------------------------- */
     630               0 :         if( src_offset + 3*pixel_size < src_bytes )
     631                 :         {
     632               0 :             int   count = 1;
     633                 : 
     634               0 :             while( count < 127
     635                 :                    && src_offset + count*pixel_size < src_bytes )
     636                 :             {
     637               0 :                 bool  bWordMatch = true;
     638                 : 
     639               0 :                 for( i = 0; i < pixel_size; i++ )
     640                 :                 {
     641               0 :                     if( src[src_offset+i] 
     642               0 :                         != src[src_offset+i+count*pixel_size] )
     643               0 :                         bWordMatch = false;
     644                 :                 }
     645                 : 
     646               0 :                 if( !bWordMatch )
     647               0 :                     break;
     648                 : 
     649               0 :                 count++;
     650                 :             }
     651                 : 
     652               0 :             if( count >= 3 )
     653                 :             {
     654               0 :                 if( oCompressedData.buffer_size < dst_offset + pixel_size+1 )
     655               0 :                     oCompressedData.SetSize( oCompressedData.buffer_size*2+100);
     656                 : 
     657               0 :                 oCompressedData.buffer[dst_offset++] = count+128;
     658                 : 
     659               0 :                 for( i = 0; i < pixel_size; i++ )
     660               0 :                     oCompressedData.buffer[dst_offset++] = src[src_offset+i];
     661                 : 
     662               0 :                 src_offset += count * pixel_size;
     663                 : 
     664               0 :                 bGotARun = true;
     665                 :             }
     666                 :             else
     667               0 :                 bGotARun = false;
     668                 :         }
     669                 :         
     670                 : /* -------------------------------------------------------------------- */
     671                 : /*      Otherwise emit a literal till we encounter at least a three */
     672                 : /*  word series.              */
     673                 : /* -------------------------------------------------------------------- */
     674               0 :         if( !bGotARun )
     675                 :         {
     676               0 :             int   count = 1;
     677               0 :             int   match_count = 0;
     678                 : 
     679               0 :             while( count < 127
     680                 :                    && src_offset + count*pixel_size < src_bytes )
     681                 :             {
     682               0 :                 bool  bWordMatch = true;
     683                 : 
     684               0 :                 for( i = 0; i < pixel_size; i++ )
     685                 :                 {
     686               0 :                     if( src[src_offset+i]
     687               0 :                         != src[src_offset+i+count*pixel_size] )
     688               0 :                         bWordMatch = false;
     689                 :                 }
     690                 : 
     691               0 :                 if( bWordMatch )
     692               0 :                     match_count++;
     693                 :                 else
     694               0 :                     match_count = 0;
     695                 : 
     696               0 :                 if( match_count > 2 )
     697               0 :                     break;
     698                 : 
     699               0 :                 count++;
     700                 :             }
     701                 :             
     702               0 :             assert( src_offset + count*pixel_size <= src_bytes );
     703                 : 
     704               0 :             while( oCompressedData.buffer_size 
     705                 :                    < dst_offset + count*pixel_size+1 )
     706               0 :                 oCompressedData.SetSize( oCompressedData.buffer_size*2+100 );
     707                 : 
     708               0 :             oCompressedData.buffer[dst_offset++] = count;
     709                 :             memcpy( oCompressedData.buffer + dst_offset, 
     710                 :                     src + src_offset, 
     711               0 :                     count * pixel_size );
     712               0 :             src_offset += count * pixel_size;
     713               0 :             dst_offset += count * pixel_size;
     714                 :         }
     715                 :     }
     716                 : 
     717               0 :     oCompressedData.buffer_size = dst_offset;
     718               0 : }
     719                 : 
     720                 : /************************************************************************/
     721                 : /*                        JPEGDecompressBlock()                         */
     722                 : /************************************************************************/
     723                 : 
     724               0 : void CTiledChannel::JPEGDecompressBlock( PCIDSKBuffer &oCompressedData,
     725                 :                                          PCIDSKBuffer &oDecompressedData )
     726                 : 
     727                 :                                
     728                 : {
     729               0 :     if( file->GetInterfaces()->JPEGDecompressBlock == NULL )
     730               0 :         ThrowPCIDSKException( "JPEG decompression not enabled in the PCIDSKInterfaces of this build." );
     731                 : 
     732               0 :     file->GetInterfaces()->JPEGDecompressBlock( 
     733                 :         (uint8 *) oCompressedData.buffer, oCompressedData.buffer_size,
     734                 :         (uint8 *) oDecompressedData.buffer, oDecompressedData.buffer_size,
     735               0 :         GetBlockWidth(), GetBlockHeight(), GetType() );
     736               0 : }
     737                 : 
     738                 : /************************************************************************/
     739                 : /*                         JPEGCompressBlock()                          */
     740                 : /************************************************************************/
     741                 : 
     742               0 : void CTiledChannel::JPEGCompressBlock( PCIDSKBuffer &oDecompressedData,
     743                 :                                        PCIDSKBuffer &oCompressedData )
     744                 :                                        
     745                 : 
     746                 :                                
     747                 : {
     748               0 :     if( file->GetInterfaces()->JPEGCompressBlock == NULL )
     749               0 :         ThrowPCIDSKException( "JPEG compression not enabled in the PCIDSKInterfaces of this build." );
     750                 : 
     751                 : /* -------------------------------------------------------------------- */
     752                 : /*      What quality should we be using?                                */
     753                 : /* -------------------------------------------------------------------- */
     754               0 :     int quality = 75;
     755                 : 
     756               0 :     if( compression.c_str()[4] >= '1' 
     757               0 :         && compression.c_str()[4] <= '0' )
     758               0 :         quality = atoi(compression.c_str() + 4);
     759                 : 
     760                 : /* -------------------------------------------------------------------- */
     761                 : /*      Make the output buffer plent big to hold any conceivable        */
     762                 : /*      result.                                                         */
     763                 : /* -------------------------------------------------------------------- */
     764               0 :     oCompressedData.SetSize( oDecompressedData.buffer_size * 2 + 1000 );
     765                 : 
     766                 : /* -------------------------------------------------------------------- */
     767                 : /*      invoke.                                                         */
     768                 : /* -------------------------------------------------------------------- */
     769               0 :     file->GetInterfaces()->JPEGCompressBlock( 
     770                 :         (uint8 *) oDecompressedData.buffer, oDecompressedData.buffer_size,
     771                 :         (uint8 *) oCompressedData.buffer, oCompressedData.buffer_size,
     772               0 :         GetBlockWidth(), GetBlockHeight(), GetType(), 75 );
     773               0 : }
     774                 : 

Generated by: LCOV version 1.7