LCOV - code coverage report
Current view: top level - frmts/pcidsk/sdk/channel - ctiledchannel.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 217 288 75.3 %
Date: 2024-05-06 22:33:47 Functions: 17 17 100.0 %

          Line data    Source code
       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, 90 Allstate Parkway, Markham, Ontario, Canada.
      12             :  *
      13             :  * Permission is hereby granted, free of charge, to any person obtaining a
      14             :  * copy of this software and associated documentation files (the "Software"),
      15             :  * to deal in the Software without restriction, including without limitation
      16             :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      17             :  * and/or sell copies of the Software, and to permit persons to whom the
      18             :  * Software is furnished to do so, subject to the following conditions:
      19             :  *
      20             :  * The above copyright notice and this permission notice shall be included
      21             :  * in all copies or substantial portions of the Software.
      22             :  *
      23             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      24             :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      25             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      26             :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      27             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      28             :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      29             :  * DEALINGS IN THE SOFTWARE.
      30             :  ****************************************************************************/
      31             : 
      32             : #include "pcidsk_config.h"
      33             : #include "pcidsk_types.h"
      34             : #include "pcidsk_exception.h"
      35             : #include "channel/ctiledchannel.h"
      36             : #include "segment/systiledir.h"
      37             : #include "blockdir/blocktilelayer.h"
      38             : #include "core/cpcidskfile.h"
      39             : #include "core/cpcidskblockfile.h"
      40             : #include "core/pcidsk_raster.h"
      41             : #include "core/pcidsk_utils.h"
      42             : #include <cassert>
      43             : #include <cstdlib>
      44             : #include <cstring>
      45             : 
      46             : namespace PCIDSK
      47             : {
      48             : 
      49             : /************************************************************************/
      50             : /*                           CTiledChannel()                            */
      51             : /************************************************************************/
      52             : 
      53          36 : CTiledChannel::CTiledChannel( PCIDSKBuffer &image_headerIn,
      54             :                               uint64 ih_offsetIn,
      55             :                               CPL_UNUSED PCIDSKBuffer &file_headerIn,
      56             :                               int channelnumIn,
      57             :                               CPCIDSKFile *fileIn,
      58          36 :                               eChanType pixel_typeIn )
      59          36 :         : CPCIDSKChannel( image_headerIn, ih_offsetIn, fileIn, pixel_typeIn, channelnumIn)
      60             : 
      61             : {
      62          36 :     std::string filename;
      63             : 
      64          36 :     image_headerIn.Get(64,64,filename);
      65             : 
      66          36 :     assert( strstr(filename.c_str(),"SIS=") != nullptr );
      67             : 
      68          36 :     image = atoi(strstr(filename.c_str(),"SIS=") + 4);
      69             : 
      70          36 :     mpoTileLayer = nullptr;
      71          36 : }
      72             : 
      73             : /************************************************************************/
      74             : /*                           ~CTiledChannel()                           */
      75             : /************************************************************************/
      76          72 : CTiledChannel::~CTiledChannel()
      77             : {
      78             :     try
      79             :     {
      80          36 :         Synchronize();
      81             :     }
      82           0 :     catch( const PCIDSKException& e )
      83             :     {
      84           0 :         fprintf(stderr, "Exception in ~CTiledChannel(): %s", e.what()); // ok
      85             :     }
      86          72 : }
      87             : 
      88             : /************************************************************************/
      89             : /*                          EstablishAccess()                           */
      90             : /************************************************************************/
      91         232 : void CTiledChannel::EstablishAccess() const
      92             : {
      93         232 :     if (mpoTileLayer)
      94         196 :         return;
      95             : 
      96          36 :     CPCIDSKBlockFile oBlockFile(file);
      97             : 
      98          36 :     SysTileDir * poTileDir = oBlockFile.GetTileDir();
      99             : 
     100          36 :     if (!poTileDir)
     101           0 :         return ThrowPCIDSKException("Unable to find the tile directory segment.");
     102             : 
     103          36 :     mpoTileLayer = poTileDir->GetTileLayer((uint32) image);
     104             : 
     105          36 :     if (!mpoTileLayer)
     106           0 :         return ThrowPCIDSKException("Unable to find the tiled channel: %d", image);
     107             : 
     108          36 :     const char * pszDataType = mpoTileLayer->GetDataType();
     109             : 
     110          36 :     if (GetDataTypeFromName(pszDataType) == CHN_UNKNOWN)
     111           0 :         return ThrowPCIDSKException("Unknown channel type: %s", pszDataType);
     112             : }
     113             : 
     114             : /************************************************************************/
     115             : /*                            Synchronize()                             */
     116             : /*                                                                      */
     117             : /*      Flush updated blockmap to disk if it is dirty.                  */
     118             : /************************************************************************/
     119          50 : void CTiledChannel::Synchronize()
     120             : {
     121          50 :     if (mpoTileLayer)
     122          50 :         mpoTileLayer->Sync();
     123          50 : }
     124             : 
     125             : /************************************************************************/
     126             : /*                                ReadTile()                            */
     127             : /************************************************************************/
     128          29 : void CTiledChannel::ReadTile(void * buffer, uint32 nCol, uint32 nRow)
     129             : {
     130          29 :     int nTileXSize = (int) mpoTileLayer->GetTileXSize();
     131          29 :     int nTileYSize = (int) mpoTileLayer->GetTileYSize();
     132             : 
     133          29 :     eChanType nDataType = GetType();
     134             : 
     135             :     // Check if we can read an sparse tile.
     136          29 :     if (mpoTileLayer->ReadSparseTile(buffer, nCol, nRow))
     137             :     {
     138             :         // Do byte swapping if needed.
     139           0 :         if( needs_swap )
     140             :         {
     141           0 :             SwapPixels( buffer, nDataType, static_cast<size_t>(nTileXSize) * nTileYSize );
     142             :         }
     143             : 
     144          25 :         return;
     145             :     }
     146             : 
     147          29 :     const char * compression = mpoTileLayer->GetCompressType();
     148             : 
     149          29 :     if (strcmp(compression, "NONE") == 0)
     150             :     {
     151          25 :         mpoTileLayer->ReadTile(buffer, nCol, nRow, mpoTileLayer->GetTileSize());
     152             : 
     153             :         // Do byte swapping if needed.
     154          25 :         if( needs_swap )
     155             :         {
     156           7 :             SwapPixels( buffer, nDataType, static_cast<size_t>(nTileXSize) * nTileYSize );
     157             :         }
     158             : 
     159          25 :         return;
     160             :     }
     161             : 
     162           4 :     uint32 nTileDataSize = mpoTileLayer->GetTileDataSize(nCol, nRow);
     163             : 
     164           4 :     PCIDSKBuffer oCompressedData(nTileDataSize);
     165           4 :     PCIDSKBuffer oUncompressedData(mpoTileLayer->GetTileSize());
     166             : 
     167           4 :     mpoTileLayer->ReadTile(oCompressedData.buffer, nCol, nRow, nTileDataSize);
     168             : 
     169           4 :     if (strcmp(compression, "RLE") == 0)
     170             :     {
     171           3 :         RLEDecompressBlock( oCompressedData, oUncompressedData );
     172             :     }
     173           1 :     else if (STARTS_WITH(compression, "JPEG"))
     174             :     {
     175           1 :         JPEGDecompressBlock( oCompressedData, oUncompressedData );
     176             :     }
     177             :     else
     178             :     {
     179           0 :         return ThrowPCIDSKException(
     180             :             "Unable to read tile of unsupported compression type: %s",
     181           0 :             compression);
     182             :     }
     183             : 
     184             : /* -------------------------------------------------------------------- */
     185             : /*      Swap if necessary.  TODO: there is some reason to doubt that    */
     186             : /*      the old implementation properly byte swapped compressed         */
     187             : /*      data.  Perhaps this should be conditional?                      */
     188             : /* -------------------------------------------------------------------- */
     189           4 :     if( needs_swap )
     190           3 :         SwapPixels( oUncompressedData.buffer, nDataType,
     191           3 :                     static_cast<size_t>(nTileXSize) * nTileYSize );
     192             : 
     193           4 :     memcpy(buffer, oUncompressedData.buffer, oUncompressedData.buffer_size);
     194             : }
     195             : 
     196             : /************************************************************************/
     197             : /*                             ReadBlock()                              */
     198             : /************************************************************************/
     199          29 : int CTiledChannel::ReadBlock( int iBlock, void *buffer,
     200             :                               int xoff, int yoff,
     201             :                               int xsize, int ysize )
     202             : {
     203          29 :     EstablishAccess();
     204             : 
     205             :     // Validate the block index.
     206          29 :     int nTileCount = (int) mpoTileLayer->GetTileCount();
     207             : 
     208          29 :     if( iBlock < 0 || iBlock >= nTileCount )
     209             :     {
     210           0 :         return ThrowPCIDSKException(0, "Requested non-existent block (%d)",
     211           0 :                               iBlock );
     212             :     }
     213             : 
     214          29 :     int nTileXSize = (int) mpoTileLayer->GetTileXSize();
     215          29 :     int nTileYSize = (int) mpoTileLayer->GetTileYSize();
     216             : 
     217             :     // Default window.
     218          29 :     if (xoff == -1 && yoff == -1 && xsize == -1 && ysize == -1)
     219             :     {
     220          29 :         xoff = 0;
     221          29 :         yoff = 0;
     222          29 :         xsize = nTileXSize;
     223          29 :         ysize = nTileYSize;
     224             :     }
     225             : 
     226             :     // Validate the requested window.
     227          29 :     if (xoff < 0 || xoff + xsize > nTileXSize ||
     228          29 :         yoff < 0 || yoff + ysize > nTileYSize)
     229             :     {
     230           0 :         return ThrowPCIDSKException(0,
     231             :             "Invalid window in ReadBlock(): xoff=%d,yoff=%d,xsize=%d,ysize=%d",
     232           0 :             xoff, yoff, xsize, ysize );
     233             :     }
     234             : 
     235          29 :     uint32 nTilePerRow = mpoTileLayer->GetTilePerRow();
     236             : 
     237          29 :     if (nTilePerRow == 0)
     238           0 :         return ThrowPCIDSKException(0, "Invalid number of tiles per row.");
     239             : 
     240          29 :     uint32 nCol = iBlock % nTilePerRow;
     241          29 :     uint32 nRow = iBlock / nTilePerRow;
     242             : 
     243             :     // Check if the entire tile was requested.
     244          29 :     if (xoff == 0 && xsize == nTileXSize &&
     245          29 :         yoff == 0 && ysize == nTileYSize)
     246             :     {
     247          29 :         ReadTile(buffer, nCol, nRow);
     248             : 
     249          29 :         return 1;
     250             :     }
     251             : 
     252           0 :     eChanType nDataType = GetType();
     253           0 :     int nPixelSize = DataTypeSize(nDataType);
     254           0 :     int nPixelCount = xsize * ysize;
     255             : 
     256             :     // Check if we can read an sparse tile.
     257           0 :     if (!mpoTileLayer->IsTileValid(nCol, nRow))
     258             :     {
     259           0 :         if (xoff == 0 && xsize == nTileXSize)
     260             :         {
     261           0 :             mpoTileLayer->ReadPartialSparseTile
     262           0 :                 (buffer, nCol, nRow,
     263           0 :                  yoff * nTileXSize * nPixelSize,
     264           0 :                  nPixelCount * nPixelSize);
     265             :         }
     266             :         else
     267             :         {
     268           0 :             for (int iy = 0; iy < ysize; iy++)
     269             :             {
     270           0 :                 mpoTileLayer->ReadPartialSparseTile
     271           0 :                     ((char*) buffer + iy * xsize * nPixelSize, nCol, nRow,
     272           0 :                      ((iy + yoff) * nTileXSize + xoff) * nPixelSize,
     273           0 :                      xsize * nPixelSize);
     274             :             }
     275             :         }
     276             : 
     277             :         // Do byte swapping if needed.
     278           0 :         if( needs_swap )
     279           0 :             SwapPixels( buffer, nDataType, nPixelCount );
     280             : 
     281           0 :         return 1;
     282             :     }
     283             : 
     284           0 :     const char * compression = mpoTileLayer->GetCompressType();
     285             : 
     286             :     // Read the requested window.
     287           0 :     if (strcmp(compression, "NONE") == 0 && xoff == 0 && xsize == nTileXSize)
     288             :     {
     289           0 :         mpoTileLayer->ReadPartialTile(buffer, nCol, nRow,
     290           0 :                                       yoff * nTileXSize * nPixelSize,
     291           0 :                                       nPixelCount * nPixelSize);
     292             : 
     293             :         // Do byte swapping if needed.
     294           0 :         if( needs_swap )
     295           0 :             SwapPixels( buffer, nDataType, nPixelCount );
     296             :     }
     297             :     // Read the requested window line by line.
     298           0 :     else if (strcmp(compression, "NONE") == 0)
     299             :     {
     300           0 :         for (int iy = 0; iy < ysize; iy++)
     301             :         {
     302           0 :             mpoTileLayer->ReadPartialTile
     303           0 :                 ((char*) buffer + iy * xsize * nPixelSize, nCol, nRow,
     304           0 :                  ((iy + yoff) * nTileXSize + xoff) * nPixelSize,
     305           0 :                  xsize * nPixelSize);
     306             :         }
     307             : 
     308             :         // Do byte swapping if needed.
     309           0 :         if( needs_swap )
     310           0 :             SwapPixels( buffer, nDataType, nPixelCount );
     311             :     }
     312             :     // Read the entire tile and copy the requested window.
     313             :     else
     314             :     {
     315           0 :         PCIDSKBuffer oTileData(mpoTileLayer->GetTileSize());
     316             : 
     317           0 :         ReadTile(oTileData.buffer, nCol, nRow);
     318             : 
     319           0 :         for (int iy = 0; iy < ysize; iy++)
     320             :         {
     321           0 :             memcpy((char*) buffer + iy * xsize * nPixelSize,
     322           0 :                    oTileData.buffer + ((iy + yoff) * nTileXSize + xoff) * nPixelSize,
     323           0 :                    static_cast<size_t>(xsize) * nPixelSize);
     324             :         }
     325             :     }
     326             : 
     327           0 :     return 1;
     328             : }
     329             : 
     330             : /************************************************************************/
     331             : /*                             WriteBlock()                             */
     332             : /************************************************************************/
     333           8 : int CTiledChannel::WriteBlock( int iBlock, void *buffer )
     334             : {
     335           8 :     if( !file->GetUpdatable() )
     336           0 :         return ThrowPCIDSKException(0, "File not open for update in WriteBlock()" );
     337             : 
     338           8 :     InvalidateOverviews();
     339             : 
     340           8 :     EstablishAccess();
     341             : 
     342             :     // Validate the block index.
     343           8 :     int nTileCount = (int) mpoTileLayer->GetTileCount();
     344             : 
     345           8 :     if( iBlock < 0 || iBlock >= nTileCount )
     346             :     {
     347           0 :         return ThrowPCIDSKException(0, "Requested non-existent block (%d)",
     348           0 :                               iBlock );
     349             :     }
     350             : 
     351           8 :     int nTileXSize = GetBlockWidth();
     352           8 :     int nTileYSize = GetBlockHeight();
     353             : 
     354           8 :     eChanType nDataType = GetType();
     355           8 :     int nPixelCount = nTileXSize * nTileYSize;
     356             : 
     357           8 :     uint32 nTilePerRow = mpoTileLayer->GetTilePerRow();
     358             : 
     359           8 :     if (nTilePerRow == 0)
     360           0 :         return ThrowPCIDSKException(0, "Invalid number of tiles per row.");
     361             : 
     362           8 :     uint32 nCol = iBlock % nTilePerRow;
     363           8 :     uint32 nRow = iBlock / nTilePerRow;
     364             : 
     365             :     // Do byte swapping if needed.
     366           8 :     if( needs_swap )
     367           7 :         SwapPixels( buffer, nDataType, nPixelCount );
     368             : 
     369             :     // Check if we can write an sparse tile.
     370           8 :     if (mpoTileLayer->WriteSparseTile(buffer, nCol, nRow))
     371             :     {
     372           0 :         if( needs_swap )
     373           0 :             SwapPixels( buffer, nDataType, nPixelCount );
     374             : 
     375           0 :         return 1;
     376             :     }
     377             : 
     378           8 :     const char * compression = mpoTileLayer->GetCompressType();
     379             : 
     380             : /* -------------------------------------------------------------------- */
     381             : /*      The simplest case it an uncompressed direct and complete       */
     382             : /*      tile read into the destination buffer.                          */
     383             : /* -------------------------------------------------------------------- */
     384           8 :     if (strcmp(compression, "NONE") == 0)
     385             :     {
     386           4 :         mpoTileLayer->WriteTile(buffer, nCol, nRow);
     387             : 
     388           4 :         if( needs_swap )
     389           4 :             SwapPixels( buffer, nDataType, nPixelCount );
     390             : 
     391           4 :         return 1;
     392             :     }
     393             : 
     394             : /* -------------------------------------------------------------------- */
     395             : /*      Copy the uncompressed data into a PCIDSKBuffer, and byte        */
     396             : /*      swap if needed.                                                 */
     397             : /* -------------------------------------------------------------------- */
     398           8 :     PCIDSKBuffer oUncompressedData(mpoTileLayer->GetTileSize());
     399             : 
     400           4 :     memcpy(oUncompressedData.buffer, buffer,
     401           4 :            oUncompressedData.buffer_size);
     402             : 
     403           4 :     if( needs_swap )
     404           3 :         SwapPixels( buffer, nDataType, nPixelCount );
     405             : 
     406             : /* -------------------------------------------------------------------- */
     407             : /*      Compress the imagery.                                           */
     408             : /* -------------------------------------------------------------------- */
     409           8 :     PCIDSKBuffer oCompressedData;
     410             : 
     411           4 :     if (strcmp(compression, "NONE") == 0)
     412             :     {
     413           0 :         oCompressedData = oUncompressedData;
     414             :     }
     415           4 :     else if (strcmp(compression, "RLE") == 0)
     416             :     {
     417           3 :         RLECompressBlock( oUncompressedData, oCompressedData );
     418             :     }
     419           1 :     else if (STARTS_WITH(compression, "JPEG"))
     420             :     {
     421           1 :         JPEGCompressBlock( oUncompressedData, oCompressedData );
     422             :     }
     423             :     else
     424             :     {
     425           0 :         return ThrowPCIDSKException(0,
     426             :             "Unable to write tile of unsupported compression type: %s",
     427           0 :             compression);
     428             :     }
     429             : 
     430           4 :     mpoTileLayer->WriteTile(oCompressedData.buffer, nCol, nRow,
     431           4 :                             oCompressedData.buffer_size);
     432             : 
     433           4 :     return 1;
     434             : }
     435             : 
     436             : /************************************************************************/
     437             : /*                           GetBlockWidth()                            */
     438             : /************************************************************************/
     439          71 : int CTiledChannel::GetBlockWidth(void) const
     440             : {
     441          71 :     EstablishAccess();
     442             : 
     443          71 :     return (int) mpoTileLayer->GetTileXSize();
     444             : }
     445             : 
     446             : /************************************************************************/
     447             : /*                           GetBlockHeight()                           */
     448             : /************************************************************************/
     449          71 : int CTiledChannel::GetBlockHeight(void) const
     450             : {
     451          71 :     EstablishAccess();
     452             : 
     453          71 :     return (int) mpoTileLayer->GetTileYSize();
     454             : }
     455             : 
     456             : /************************************************************************/
     457             : /*                              GetWidth()                              */
     458             : /************************************************************************/
     459          11 : int CTiledChannel::GetWidth(void) const
     460             : {
     461          11 :     EstablishAccess();
     462             : 
     463          11 :     return (int) mpoTileLayer->GetXSize();
     464             : }
     465             : 
     466             : /************************************************************************/
     467             : /*                             GetHeight()                              */
     468             : /************************************************************************/
     469          11 : int CTiledChannel::GetHeight(void) const
     470             : {
     471          11 :     EstablishAccess();
     472             : 
     473          11 :     return (int) mpoTileLayer->GetYSize();
     474             : }
     475             : 
     476             : /************************************************************************/
     477             : /*                              GetType()                               */
     478             : /************************************************************************/
     479         163 : eChanType CTiledChannel::GetType(void) const
     480             : {
     481         163 :     eChanType nDataType = CPCIDSKChannel::GetType();
     482             : 
     483         163 :     if (nDataType != CHN_UNKNOWN)
     484         132 :         return nDataType;
     485             : 
     486          31 :     EstablishAccess();
     487             : 
     488          31 :     return GetDataTypeFromName(mpoTileLayer->GetDataType());
     489             : }
     490             : 
     491             : /************************************************************************/
     492             : /*                         RLEDecompressBlock()                         */
     493             : /************************************************************************/
     494             : 
     495           3 : void CTiledChannel::RLEDecompressBlock( PCIDSKBuffer &oCompressedData,
     496             :                                         PCIDSKBuffer &oDecompressedData )
     497             : 
     498             : 
     499             : {
     500           3 :     int    src_offset=0, dst_offset=0;
     501           3 :     uint8  *src = (uint8 *) oCompressedData.buffer;
     502           3 :     uint8  *dst = (uint8 *) oDecompressedData.buffer;
     503           3 :     int    nPixelSize = DataTypeSize(GetType());
     504             : 
     505             : /* -------------------------------------------------------------------- */
     506             : /*      Process till we are out of source data, or our destination      */
     507             : /*      buffer is full.  These conditions should be satisfied at       */
     508             : /*      the same time!                                                  */
     509             : /* -------------------------------------------------------------------- */
     510          27 :     while( src_offset + 1 + nPixelSize <= oCompressedData.buffer_size
     511          30 :            && dst_offset < oDecompressedData.buffer_size )
     512             :     {
     513             : /* -------------------------------------------------------------------- */
     514             : /*      Extract a repeat run                                            */
     515             : /* -------------------------------------------------------------------- */
     516          27 :         if( src[src_offset] > 127 )
     517             :         {
     518          15 :             int count = src[src_offset++] - 128;
     519             :             int i;
     520             : 
     521          15 :             if( dst_offset + count * nPixelSize > oDecompressedData.buffer_size)
     522             :             {
     523           0 :                 return ThrowPCIDSKException( "RLE compressed tile corrupt, overrun avoided." );
     524             :             }
     525             : 
     526        1563 :             while( count-- > 0 )
     527             :             {
     528        4644 :                 for( i = 0; i < nPixelSize; i++ )
     529        3096 :                     dst[dst_offset++] = src[src_offset+i];
     530             :             }
     531          15 :             src_offset += nPixelSize;
     532             :         }
     533             : 
     534             : /* -------------------------------------------------------------------- */
     535             : /*      Extract a literal run.                                          */
     536             : /* -------------------------------------------------------------------- */
     537             :         else
     538             :         {
     539          12 :             int count = src[src_offset++];
     540             : 
     541          12 :             if( dst_offset + count*nPixelSize > oDecompressedData.buffer_size
     542          12 :                 || src_offset + count*nPixelSize > oCompressedData.buffer_size)
     543             :             {
     544           0 :                 return ThrowPCIDSKException( "RLE compressed tile corrupt, overrun avoided." );
     545             :             }
     546             : 
     547          12 :             memcpy( dst + dst_offset, src + src_offset,
     548          12 :                     nPixelSize * count );
     549          12 :             src_offset += nPixelSize * count;
     550          12 :             dst_offset += nPixelSize * count;
     551             :         }
     552             : 
     553             :     }
     554             : 
     555             : /* -------------------------------------------------------------------- */
     556             : /*      Final validation.                                               */
     557             : /* -------------------------------------------------------------------- */
     558           3 :     if( src_offset != oCompressedData.buffer_size
     559           3 :         || dst_offset != oDecompressedData.buffer_size )
     560             :     {
     561           0 :         return ThrowPCIDSKException( "RLE compressed tile corrupt, result incomplete." );
     562             :     }
     563             : }
     564             : 
     565             : /************************************************************************/
     566             : /*                         RLECompressBlock()                           */
     567             : /*                                                                      */
     568             : /*      TODO: There does not seem to be any byte order logic in here!   */
     569             : /************************************************************************/
     570             : 
     571           3 : void CTiledChannel::RLECompressBlock( PCIDSKBuffer &oUncompressedData,
     572             :                                       PCIDSKBuffer &oCompressedData )
     573             : 
     574             : 
     575             : {
     576           3 :     int    src_bytes = oUncompressedData.buffer_size;
     577           3 :     int    nPixelSize = DataTypeSize(GetType());
     578           3 :     int    src_offset = 0, dst_offset = 0;
     579             :     int    i;
     580           3 :     uint8  *src = (uint8 *) oUncompressedData.buffer;
     581             : 
     582             : /* -------------------------------------------------------------------- */
     583             : /*      Loop till input exhausted.                                       */
     584             : /* -------------------------------------------------------------------- */
     585          30 :     while( src_offset < src_bytes )
     586             :     {
     587          27 :         bool    bGotARun = false;
     588             : 
     589             : /* -------------------------------------------------------------------- */
     590             : /*      Establish the run length, and emit if greater than 3.           */
     591             : /* -------------------------------------------------------------------- */
     592          27 :         if( src_offset + 3*nPixelSize < src_bytes )
     593             :         {
     594          27 :             int         count = 1;
     595             : 
     596        1533 :             while( count < 127
     597        1560 :                    && src_offset + count*nPixelSize < src_bytes )
     598             :             {
     599        1548 :                 bool    bWordMatch = true;
     600             : 
     601        4644 :                 for( i = 0; i < nPixelSize; i++ )
     602             :                 {
     603        3096 :                     if( src[src_offset+i]
     604        3096 :                         != src[src_offset+i+count*nPixelSize] )
     605          24 :                         bWordMatch = false;
     606             :                 }
     607             : 
     608        1548 :                 if( !bWordMatch )
     609          15 :                     break;
     610             : 
     611        1533 :                 count++;
     612             :             }
     613             : 
     614          27 :             if( count >= 3 )
     615             :             {
     616          15 :                 if( oCompressedData.buffer_size < dst_offset + nPixelSize+1 )
     617           3 :                     oCompressedData.SetSize( oCompressedData.buffer_size*2+100);
     618             : 
     619          15 :                 oCompressedData.buffer[dst_offset++] = (char) (count+128);
     620             : 
     621          45 :                 for( i = 0; i < nPixelSize; i++ )
     622          30 :                     oCompressedData.buffer[dst_offset++] = src[src_offset+i];
     623             : 
     624          15 :                 src_offset += count * nPixelSize;
     625             : 
     626          15 :                 bGotARun = true;
     627             :             }
     628             :             else
     629          12 :                 bGotARun = false;
     630             :         }
     631             : 
     632             : /* -------------------------------------------------------------------- */
     633             : /*      Otherwise emit a literal till we encounter at least a three     */
     634             : /*      word series.                                                    */
     635             : /* -------------------------------------------------------------------- */
     636          27 :         if( !bGotARun )
     637             :         {
     638          12 :             int         count = 1;
     639          12 :             int         match_count = 0;
     640             : 
     641        1512 :             while( count < 127
     642        1524 :                    && src_offset + count*nPixelSize < src_bytes )
     643             :             {
     644        1512 :                 bool    bWordMatch = true;
     645             : 
     646        4536 :                 for( i = 0; i < nPixelSize; i++ )
     647             :                 {
     648        3024 :                     if( src[src_offset+i]
     649        3024 :                         != src[src_offset+i+count*nPixelSize] )
     650        2172 :                         bWordMatch = false;
     651             :                 }
     652             : 
     653        1512 :                 if( bWordMatch )
     654           0 :                     match_count++;
     655             :                 else
     656        1512 :                     match_count = 0;
     657             : 
     658        1512 :                 if( match_count > 2 )
     659           0 :                     break;
     660             : 
     661        1512 :                 count++;
     662             :             }
     663             : 
     664          12 :             assert( src_offset + count*nPixelSize <= src_bytes );
     665             : 
     666           9 :             while( oCompressedData.buffer_size
     667          21 :                    < dst_offset + count*nPixelSize+1 )
     668           9 :                 oCompressedData.SetSize( oCompressedData.buffer_size*2+100 );
     669             : 
     670          12 :             oCompressedData.buffer[dst_offset++] = (char) count;
     671          12 :             memcpy( oCompressedData.buffer + dst_offset,
     672          12 :                     src + src_offset,
     673          12 :                     cpl::fits_on<int>(count * nPixelSize) );
     674          12 :             src_offset += count * nPixelSize;
     675          12 :             dst_offset += count * nPixelSize;
     676             :         }
     677             :     }
     678             : 
     679           3 :     oCompressedData.buffer_size = dst_offset;
     680           3 : }
     681             : 
     682             : /************************************************************************/
     683             : /*                        JPEGDecompressBlock()                         */
     684             : /************************************************************************/
     685             : 
     686           1 : void CTiledChannel::JPEGDecompressBlock( PCIDSKBuffer &oCompressedData,
     687             :                                          PCIDSKBuffer &oDecompressedData )
     688             : 
     689             : 
     690             : {
     691           1 :     if( file->GetInterfaces()->JPEGDecompressBlock == nullptr )
     692           0 :         return ThrowPCIDSKException( "JPEG decompression not enabled in the PCIDSKInterfaces of this build." );
     693             : 
     694           1 :     file->GetInterfaces()->JPEGDecompressBlock(
     695           1 :         (uint8 *) oCompressedData.buffer, oCompressedData.buffer_size,
     696           1 :         (uint8 *) oDecompressedData.buffer, oDecompressedData.buffer_size,
     697             :         GetBlockWidth(), GetBlockHeight(), GetType() );
     698             : }
     699             : 
     700             : /************************************************************************/
     701             : /*                         JPEGCompressBlock()                          */
     702             : /************************************************************************/
     703             : 
     704           1 : void CTiledChannel::JPEGCompressBlock( PCIDSKBuffer &oDecompressedData,
     705             :                                        PCIDSKBuffer &oCompressedData )
     706             : 
     707             : 
     708             : 
     709             : {
     710           1 :     if( file->GetInterfaces()->JPEGCompressBlock == nullptr )
     711           0 :         return ThrowPCIDSKException( "JPEG compression not enabled in the PCIDSKInterfaces of this build." );
     712             : 
     713             : /* -------------------------------------------------------------------- */
     714             : /*      What quality should we be using?                                */
     715             : /* -------------------------------------------------------------------- */
     716           1 :     int quality = 75;
     717             : 
     718           1 :     const char * compression = mpoTileLayer->GetCompressType();
     719             : 
     720           1 :     if (strlen(compression) > 4 && isdigit(static_cast<unsigned char>(compression[4])))
     721           0 :         quality = atoi(compression + 4);
     722             : 
     723             : /* -------------------------------------------------------------------- */
     724             : /*      Make the output buffer plenty big to hold any conceivable        */
     725             : /*      result.                                                         */
     726             : /* -------------------------------------------------------------------- */
     727           1 :     oCompressedData.SetSize( oDecompressedData.buffer_size * 2 + 1000 );
     728             : 
     729             : /* -------------------------------------------------------------------- */
     730             : /*      invoke.                                                         */
     731             : /* -------------------------------------------------------------------- */
     732           1 :     file->GetInterfaces()->JPEGCompressBlock(
     733           1 :         (uint8 *) oDecompressedData.buffer, oDecompressedData.buffer_size,
     734           1 :         (uint8 *) oCompressedData.buffer, oCompressedData.buffer_size,
     735             :         GetBlockWidth(), GetBlockHeight(), GetType(), quality );
     736             : }
     737             : 
     738             : } // namespace PCIDSK;

Generated by: LCOV version 1.14