LCOV - code coverage report
Current view: directory - frmts/rik - rikdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 287 161 56.1 %
Date: 2010-01-09 Functions: 16 10 62.5 %

       1                 : /******************************************************************************
       2                 :  * $Id: rikdataset.cpp 18348 2009-12-19 14:32:39Z rouault $
       3                 :  *
       4                 :  * Project:  RIK Reader
       5                 :  * Purpose:  All code for RIK Reader
       6                 :  * Author:   Daniel Wallner, daniel.wallner@bredband.net
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2005, Daniel Wallner <daniel.wallner@bredband.net>
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include <float.h>
      31                 : #include <zlib.h>
      32                 : #include "gdal_pam.h"
      33                 : 
      34                 : CPL_CVSID("$Id: rikdataset.cpp 18348 2009-12-19 14:32:39Z rouault $");
      35                 : 
      36                 : CPL_C_START
      37                 : void  GDALRegister_RIK(void);
      38                 : CPL_C_END
      39                 : 
      40                 : #define RIK_HEADER_DEBUG 0
      41                 : #define RIK_CLEAR_DEBUG 0
      42                 : #define RIK_PIXEL_DEBUG 0
      43                 : 
      44                 : //#define RIK_SINGLE_BLOCK 0
      45                 : 
      46                 : #define RIK_ALLOW_BLOCK_ERRORS 1
      47                 : 
      48                 : //
      49                 : // The RIK file format information was extracted from the trikpanel project:
      50                 : // http://sourceforge.net/projects/trikpanel/
      51                 : //
      52                 : // A RIK file consists of the following elements:
      53                 : //
      54                 : // +--------------------+
      55                 : // | Magic "RIK3"       | (Only in RIK version 3)
      56                 : // +--------------------+
      57                 : // | Map name           | (The first two bytes is the string length)
      58                 : // +--------------------+
      59                 : // | Header             | (Three different formats exists)
      60                 : // +--------------------+
      61                 : // | Color palette      |
      62                 : // +--------------------+
      63                 : // | Block offset array | (Only in compressed formats)
      64                 : // +--------------------+
      65                 : // | Image blocks       |
      66                 : // +--------------------+
      67                 : //
      68                 : // All numbers are stored in little endian.
      69                 : //
      70                 : // There are four different image block formats:
      71                 : //
      72                 : // 1. Uncompressed image block
      73                 : //
      74                 : //   A stream of palette indexes.
      75                 : //
      76                 : // 2. RLE image block
      77                 : //
      78                 : //   The RLE image block is a stream of byte pairs:
      79                 : //   |  Run length - 1 (byte)  |  Pixel value (byte)  |  Run length - 1 ...
      80                 : //
      81                 : // 3. LZW image block
      82                 : //
      83                 : //   The LZW image block uses the same LZW encoding as a GIF file
      84                 : //   except that there is no EOF code and maximum code length is 13 bits.
      85                 : //   These blocks are upside down compared to GDAL.
      86                 : //
      87                 : // 4. ZLIB image block
      88                 : //
      89                 : //   These blocks are upside down compared to GDAL.
      90                 : //
      91                 : 
      92                 : typedef struct
      93                 : {
      94                 :     GUInt16     iUnknown;
      95                 :     double      fSouth;         // Map bounds
      96                 :     double      fWest;
      97                 :     double      fNorth;
      98                 :     double      fEast;
      99                 :     GUInt32     iScale;         // Source map scale
     100                 :     float       iMPPNum;        // Meters per pixel numerator
     101                 :     GUInt32     iMPPDen;        // Meters per pixel denominator
     102                 :                                 // Only used if fSouth < 4000000
     103                 :     GUInt32     iBlockWidth;
     104                 :     GUInt32     iBlockHeight;
     105                 :     GUInt32     iHorBlocks;     // Number of horizontal blocks
     106                 :     GUInt32     iVertBlocks;    // Number of vertical blocks
     107                 :                                 // Only used if fSouth >= 4000000
     108                 :     GByte       iBitsPerPixel;
     109                 :     GByte       iOptions;
     110                 : } RIKHeader;
     111                 : 
     112                 : /************************************************************************/
     113                 : /* ==================================================================== */
     114                 : /*        RIKDataset        */
     115                 : /* ==================================================================== */
     116                 : /************************************************************************/
     117                 : 
     118                 : class RIKRasterBand;
     119                 : 
     120                 : class RIKDataset : public GDALPamDataset
     121               1 : {
     122                 :     friend class RIKRasterBand;
     123                 : 
     124                 :     FILE        *fp;
     125                 : 
     126                 :     double      fTransform[6];
     127                 : 
     128                 :     GUInt32     nBlockXSize;
     129                 :     GUInt32     nBlockYSize;
     130                 :     GUInt32     nHorBlocks;
     131                 :     GUInt32     nVertBlocks;
     132                 :     GUInt32     nFileSize;
     133                 :     GUInt32     *pOffsets;
     134                 :     GByte       options;
     135                 : 
     136                 :     GDALColorTable *poColorTable;
     137                 : 
     138                 :   public:
     139                 :     ~RIKDataset();
     140                 : 
     141                 :     static GDALDataset *Open( GDALOpenInfo * );
     142                 : 
     143                 :     CPLErr  GetGeoTransform( double * padfTransform );
     144                 :     const char *GetProjectionRef();
     145                 : };
     146                 : 
     147                 : /************************************************************************/
     148                 : /* ==================================================================== */
     149                 : /*                            RIKRasterBand                             */
     150                 : /* ==================================================================== */
     151                 : /************************************************************************/
     152                 : 
     153                 : class RIKRasterBand : public GDALPamRasterBand
     154               2 : {
     155                 :     friend class RIKDataset;
     156                 : 
     157                 :   public:
     158                 : 
     159                 :     RIKRasterBand( RIKDataset *, int );
     160                 : 
     161                 :     virtual CPLErr IReadBlock( int, int, void * );
     162                 :     virtual GDALColorInterp GetColorInterpretation();
     163                 :     virtual GDALColorTable *GetColorTable();
     164                 : };
     165                 : 
     166                 : /************************************************************************/
     167                 : /*                           RIKRasterBand()                            */
     168                 : /************************************************************************/
     169                 : 
     170               1 : RIKRasterBand::RIKRasterBand( RIKDataset *poDS, int nBand )
     171                 : 
     172                 : {
     173               1 :     this->poDS = poDS;
     174               1 :     this->nBand = nBand;
     175                 : 
     176               1 :     eDataType = GDT_Byte;
     177                 : 
     178               1 :     nBlockXSize = poDS->nBlockXSize;
     179               1 :     nBlockYSize = poDS->nBlockYSize;
     180               1 : }
     181                 : 
     182                 : /************************************************************************/
     183                 : /*                             GetNextLZWCode()                         */
     184                 : /************************************************************************/
     185                 : 
     186               0 : static int GetNextLZWCode( int codeBits,
     187                 :                            GByte *blockData,
     188                 :                            GUInt32 &filePos,
     189                 :                            GUInt32 &fileAlign,
     190                 :                            int &bitsTaken )
     191                 : 
     192                 : {
     193               0 :     if( filePos == fileAlign )
     194                 :     {
     195               0 :         fileAlign += codeBits;
     196                 :     }
     197                 : 
     198                 :     const int BitMask[] = {
     199                 :         0x0000, 0x0001, 0x0003, 0x0007,
     200               0 :         0x000f, 0x001f, 0x003f, 0x007f };
     201                 : 
     202               0 :     int ret = 0;
     203               0 :     int bitsLeftToGo = codeBits;
     204                 : 
     205               0 :     while( bitsLeftToGo > 0 )
     206                 :     {
     207                 :         int tmp;
     208                 : 
     209               0 :         tmp = blockData[filePos];
     210               0 :         tmp = tmp >> bitsTaken;
     211                 : 
     212               0 :         if( bitsLeftToGo < 8 )
     213               0 :             tmp &= BitMask[bitsLeftToGo];
     214                 : 
     215               0 :         tmp = tmp << (codeBits - bitsLeftToGo);
     216                 : 
     217               0 :         ret |= tmp;
     218                 : 
     219               0 :         bitsLeftToGo -= (8 - bitsTaken);
     220               0 :         bitsTaken = 0;
     221                 : 
     222               0 :         if( bitsLeftToGo < 0 )
     223               0 :             bitsTaken = 8 + bitsLeftToGo;
     224                 : 
     225               0 :         if( bitsTaken == 0 )
     226               0 :             filePos++;
     227                 :     }
     228                 : 
     229                 : #if RIK_PIXEL_DEBUG
     230                 :     printf( "c%03X\n", ret );
     231                 : #endif
     232                 : 
     233               0 :     return ret;
     234                 : }
     235                 : 
     236                 : /************************************************************************/
     237                 : /*                             OutputPixel()                            */
     238                 : /************************************************************************/
     239                 : 
     240               0 : static void OutputPixel( GByte pixel,
     241                 :                          void * image,
     242                 :                          GUInt32 imageWidth,
     243                 :                          GUInt32 lineBreak,
     244                 :                          int &imageLine,
     245                 :                          GUInt32 &imagePos )
     246                 : 
     247                 : {
     248               0 :     if( imagePos < imageWidth && imageLine >= 0)
     249               0 :         ((GByte *) image)[imagePos + imageLine * imageWidth] = pixel;
     250                 : 
     251               0 :     imagePos++;
     252                 : 
     253                 : #if RIK_PIXEL_DEBUG
     254                 :     printf( "_%02X %d\n", pixel, imagePos );
     255                 : #endif
     256                 : 
     257                 :     // Check if we need to change line
     258                 : 
     259               0 :     if( imagePos == lineBreak )
     260                 :     {
     261                 : #if RIK_PIXEL_DEBUG
     262                 :         printf( "\n%d\n", imageLine );
     263                 : #endif
     264                 : 
     265               0 :         imagePos = 0;
     266                 : 
     267               0 :         imageLine--;
     268                 :     }
     269               0 : }
     270                 : 
     271                 : /************************************************************************/
     272                 : /*                             IReadBlock()                             */
     273                 : /************************************************************************/
     274                 : 
     275             135 : CPLErr RIKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     276                 :                                   void * pImage )
     277                 : 
     278                 : {
     279             135 :     RIKDataset *poRDS = (RIKDataset *) poDS;
     280                 :     GByte *blockData;
     281                 :     GUInt32 blocks;
     282                 :     GUInt32 nBlockIndex;
     283                 :     GUInt32 nBlockOffset;
     284                 :     GUInt32 nBlockSize;
     285                 : 
     286             135 :     blocks = poRDS->nHorBlocks * poRDS->nVertBlocks;
     287             135 :     nBlockIndex = nBlockXOff + nBlockYOff * poRDS->nHorBlocks;
     288             135 :     nBlockOffset = poRDS->pOffsets[nBlockIndex];
     289                 : 
     290             135 :     nBlockSize = poRDS->nFileSize;
     291             135 :     for( GUInt32 bi = nBlockIndex + 1; bi < blocks; bi++ )
     292                 :     {
     293             134 :         if( poRDS->pOffsets[bi] )
     294                 :         {
     295             134 :             nBlockSize = poRDS->pOffsets[bi];
     296             134 :             break;
     297                 :         }
     298                 :     }
     299             135 :     nBlockSize -= nBlockOffset;
     300                 : 
     301                 :     GUInt32 pixels;
     302                 : 
     303             135 :     pixels = poRDS->nBlockXSize * poRDS->nBlockYSize;
     304                 : 
     305             135 :     if( !nBlockOffset || !nBlockSize
     306                 : #ifdef RIK_SINGLE_BLOCK
     307                 :         || nBlockIndex != RIK_SINGLE_BLOCK
     308                 : #endif
     309                 :         )
     310                 :     {
     311               0 :         for( GUInt32 i = 0; i < pixels; i++ )
     312               0 :         ((GByte *) pImage)[i] = 0;
     313               0 :         return CE_None;
     314                 :     }
     315                 : 
     316             135 :     VSIFSeek( poRDS->fp, nBlockOffset, SEEK_SET );
     317                 : 
     318                 : /* -------------------------------------------------------------------- */
     319                 : /*      Read uncompressed block.                                        */
     320                 : /* -------------------------------------------------------------------- */
     321                 : 
     322             135 :     if( poRDS->options == 0x00 || poRDS->options == 0x40 )
     323                 :     {
     324               0 :         VSIFRead( pImage, 1, nBlockSize, poRDS->fp );
     325               0 :         return CE_None;
     326                 :     }
     327                 : 
     328                 :     // Read block to memory
     329             135 :     blockData = (GByte *) CPLMalloc(nBlockSize);
     330             135 :     VSIFRead( blockData, 1, nBlockSize, poRDS->fp );
     331                 : 
     332             135 :     GUInt32 filePos = 0;
     333             135 :     GUInt32 imagePos = 0;
     334                 : 
     335                 : /* -------------------------------------------------------------------- */
     336                 : /*      Read RLE block.                                                 */
     337                 : /* -------------------------------------------------------------------- */
     338                 : 
     339             135 :     if( poRDS->options == 0x01 ||
     340               0 :         poRDS->options == 0x41 ) do
     341                 :     {
     342               0 :         GByte count = blockData[filePos++];
     343               0 :         GByte color = blockData[filePos++];
     344                 : 
     345               0 :         for (GByte i = 0; i <= count; i++)
     346                 :         {
     347               0 :             ((GByte *) pImage)[imagePos++] = color;
     348                 :         }
     349                 :     } while( filePos < nBlockSize && imagePos < pixels );
     350                 : 
     351                 : /* -------------------------------------------------------------------- */
     352                 : /*      Read LZW block.                                                 */
     353                 : /* -------------------------------------------------------------------- */
     354                 : 
     355             135 :     else if( poRDS->options == 0x0b )
     356                 :     {
     357               0 :         const bool LZW_HAS_CLEAR_CODE = !!(blockData[4] & 0x80);
     358               0 :         const int LZW_MAX_BITS = blockData[4] & 0x1f; // Max 13
     359               0 :         const int LZW_BITS_PER_PIXEL = 8;
     360               0 :         const int LZW_OFFSET = 5;
     361                 : 
     362               0 :         const int LZW_CLEAR = 1 << LZW_BITS_PER_PIXEL;
     363               0 :         const int LZW_CODES = 1 << LZW_MAX_BITS;
     364               0 :         const int LZW_NO_SUCH_CODE = LZW_CODES + 1;
     365                 : 
     366               0 :         int lastAdded = LZW_HAS_CLEAR_CODE ? LZW_CLEAR : LZW_CLEAR - 1;
     367               0 :         int codeBits = LZW_BITS_PER_PIXEL + 1;
     368                 : 
     369                 :         int code;
     370                 :         int lastCode;
     371                 :         GByte lastOutput;
     372               0 :         int bitsTaken = 0;
     373                 : 
     374                 :         int prefix[8192];      // only need LZW_CODES for size.
     375                 :         GByte character[8192]; // only need LZW_CODES for size.
     376                 : 
     377                 :         int i;
     378                 :         GByte j;
     379                 : 
     380               0 :         for( j = 0; j < LZW_CLEAR; j++ )
     381               0 :             character[j] = j;
     382                 :         for( i = 0; i < LZW_CODES; i++ )
     383                 :             prefix[i] = LZW_NO_SUCH_CODE;
     384                 : 
     385                 :         filePos = LZW_OFFSET;
     386                 :         GUInt32 fileAlign = LZW_OFFSET;
     387                 :         int imageLine = poRDS->nBlockYSize - 1;
     388                 : 
     389                 :         GUInt32 lineBreak = poRDS->nBlockXSize;
     390                 : 
     391                 :         // 32 bit alignment
     392                 :         lineBreak += 3;
     393                 :         lineBreak &= 0xfffffffc;
     394                 : 
     395                 :         code = GetNextLZWCode( codeBits, blockData, filePos,
     396                 :                                fileAlign, bitsTaken );
     397                 : 
     398                 :         OutputPixel( (GByte)code, pImage, poRDS->nBlockXSize,
     399                 :                      lineBreak, imageLine, imagePos );
     400                 :         lastOutput = (GByte)code;
     401                 : 
     402                 :         while( imageLine >= 0 &&
     403                 :                (imageLine || imagePos < poRDS->nBlockXSize - 1) &&
     404                 :                filePos < nBlockSize ) try
     405                 :         {
     406                 :             lastCode = code;
     407                 :             code = GetNextLZWCode( codeBits, blockData,
     408                 :                                    filePos, fileAlign, bitsTaken );
     409                 :             if( VSIFEof( poRDS->fp ) )
     410                 :             {
     411                 :                 CPLFree( blockData );
     412                 :                 CPLError( CE_Failure, CPLE_AppDefined,
     413                 :                           "RIK decompression failed. "
     414                 :                           "Read past end of file.\n" );
     415                 :                 return CE_Failure;
     416                 :             }
     417                 : 
     418                 :             if( LZW_HAS_CLEAR_CODE && code == LZW_CLEAR )
     419                 :             {
     420                 : #if RIK_CLEAR_DEBUG
     421                 :                 CPLDebug( "RIK",
     422                 :                           "Clearing block %d\n"
     423                 :                           " x=%d y=%d\n"
     424                 :                           " pos=%d size=%d\n",
     425                 :                           nBlockIndex,
     426                 :                           imagePos, imageLine,
     427                 :                           filePos, nBlockSize );
     428                 : #endif
     429                 : 
     430                 :                 // Clear prefix table
     431                 :                 for( i = LZW_CLEAR; i < LZW_CODES; i++ )
     432                 :                     prefix[i] = LZW_NO_SUCH_CODE;
     433                 :                 lastAdded = LZW_CLEAR;
     434                 :                 codeBits = LZW_BITS_PER_PIXEL + 1;
     435                 : 
     436                 :                 filePos = fileAlign;
     437                 :                 bitsTaken = 0;
     438                 : 
     439                 :                 code = GetNextLZWCode( codeBits, blockData,
     440                 :                                        filePos, fileAlign, bitsTaken );
     441                 : 
     442                 :                 if( code > lastAdded )
     443                 :                 {
     444                 :                     throw "Clear Error";
     445                 :                 }
     446                 : 
     447                 :                 OutputPixel( (GByte)code, pImage, poRDS->nBlockXSize,
     448                 :                              lineBreak, imageLine, imagePos );
     449                 :                 lastOutput = (GByte)code;
     450                 :             }
     451                 :             else
     452                 :             {
     453                 :                 // Set-up decoding
     454                 : 
     455                 :                 GByte stack[8192]; // only need LZW_CODES for size.
     456                 : 
     457                 :                 int stackPtr = 0;
     458                 :                 int decodeCode = code;
     459                 : 
     460                 :                 if( code == lastAdded + 1 )
     461                 :                 {
     462                 :                     // Handle special case
     463                 :                     *stack = lastOutput;
     464                 :                     stackPtr = 1;
     465                 :                     decodeCode = lastCode;
     466                 :                 }
     467                 :                 else if( code > lastAdded + 1 )
     468                 :                 {
     469                 :                     throw "Too high code";
     470                 :                 }
     471                 : 
     472                 :                 // Decode
     473                 : 
     474                 :                 i = 0;
     475                 :                 while( ++i < LZW_CODES &&
     476                 :                        decodeCode >= LZW_CLEAR &&
     477                 :                        decodeCode < LZW_NO_SUCH_CODE )
     478                 :                 {
     479                 :                     stack[stackPtr++] = character[decodeCode];
     480                 :                     decodeCode = prefix[decodeCode];
     481                 :                 }
     482                 :                 stack[stackPtr++] = (GByte)decodeCode;
     483                 : 
     484                 :                 if( i == LZW_CODES || decodeCode >= LZW_NO_SUCH_CODE )
     485                 :                 {
     486                 :                     throw "Decode error";
     487                 :                 }
     488                 : 
     489                 :                 // Output stack
     490                 : 
     491                 :                 lastOutput = stack[stackPtr - 1];
     492                 : 
     493                 :                 while( stackPtr != 0 && imagePos < pixels )
     494                 :                 {
     495                 :                     OutputPixel( stack[--stackPtr], pImage, poRDS->nBlockXSize,
     496                 :                                  lineBreak, imageLine, imagePos );
     497                 :                 }
     498                 : 
     499                 :                 // Add code to string table
     500                 : 
     501                 :                 if( lastCode != LZW_NO_SUCH_CODE &&
     502                 :                     lastAdded != LZW_CODES - 1 )
     503                 :                 {
     504                 :                     prefix[++lastAdded] = lastCode;
     505                 :                     character[lastAdded] = lastOutput;
     506                 :                 }
     507                 : 
     508                 :                 // Check if we need to use more bits
     509                 : 
     510                 :                 if( lastAdded == (1 << codeBits) - 1 &&
     511                 :                     codeBits != LZW_MAX_BITS )
     512                 :                 {
     513                 :                      codeBits++;
     514                 : 
     515                 :                      filePos = fileAlign;
     516                 :                      bitsTaken = 0;
     517                 :                 }
     518                 :             }
     519                 :         }
     520                 :         catch (const char *errStr)
     521                 :         {
     522                 : #if RIK_ALLOW_BLOCK_ERRORS
     523                 :                 CPLDebug( "RIK",
     524                 :                           "LZW Decompress Failed: %s\n"
     525                 :                           " blocks: %d\n"
     526                 :                           " blockindex: %d\n"
     527                 :                           " blockoffset: %X\n"
     528                 :                           " blocksize: %d\n",
     529                 :                           errStr, blocks, nBlockIndex,
     530                 :                           nBlockOffset, nBlockSize );
     531                 :                 break;
     532                 : #else
     533                 :                 CPLFree( blockData );
     534                 :                 CPLError( CE_Failure, CPLE_AppDefined,
     535                 :                           "RIK decompression failed. "
     536                 :                           "Corrupt image block." );
     537                 :                 return CE_Failure;
     538                 : #endif
     539                 :         }
     540                 :     }
     541                 : 
     542                 : /* -------------------------------------------------------------------- */
     543                 : /*      Read ZLIB block.                                                */
     544                 : /* -------------------------------------------------------------------- */
     545                 : 
     546             135 :     else if( poRDS->options == 0x0d )
     547                 :     {
     548             135 :         uLong destLen = pixels;
     549             135 :         Byte *upsideDown = (Byte *) CPLMalloc( pixels );
     550                 : 
     551             135 :         uncompress( upsideDown, &destLen, blockData, nBlockSize );
     552                 : 
     553           33885 :         for (GUInt32 i = 0; i < poRDS->nBlockYSize; i++)
     554                 :         {
     555                 :             memcpy( ((Byte *)pImage) + poRDS->nBlockXSize * i,
     556                 :                     upsideDown + poRDS->nBlockXSize *
     557                 :                                  (poRDS->nBlockYSize - i - 1),
     558           33750 :                     poRDS->nBlockXSize );
     559                 :         }
     560                 : 
     561             135 :         CPLFree( upsideDown );
     562                 :     }
     563                 : 
     564             135 :     CPLFree( blockData );
     565                 : 
     566             135 :     return CE_None;
     567                 : }
     568                 : 
     569                 : /************************************************************************/
     570                 : /*                       GetColorInterpretation()                       */
     571                 : /************************************************************************/
     572                 : 
     573               0 : GDALColorInterp RIKRasterBand::GetColorInterpretation()
     574                 : 
     575                 : {
     576               0 :     return GCI_PaletteIndex;
     577                 : }
     578                 : 
     579                 : /************************************************************************/
     580                 : /*                           GetColorTable()                            */
     581                 : /************************************************************************/
     582                 : 
     583               0 : GDALColorTable *RIKRasterBand::GetColorTable()
     584                 : 
     585                 : {
     586               0 :     RIKDataset *poRDS = (RIKDataset *) poDS;
     587                 : 
     588               0 :     return poRDS->poColorTable;
     589                 : }
     590                 : 
     591                 : /************************************************************************/
     592                 : /* ==================================================================== */
     593                 : /*        RIKDataset        */
     594                 : /* ==================================================================== */
     595                 : /************************************************************************/
     596                 : 
     597                 : /************************************************************************/
     598                 : /*                            ~RIKDataset()                             */
     599                 : /************************************************************************/
     600                 : 
     601               2 : RIKDataset::~RIKDataset()
     602                 : 
     603                 : {
     604               1 :     FlushCache();
     605               1 :     CPLFree( pOffsets );
     606               1 :     if( fp != NULL )
     607               1 :         VSIFClose( fp );
     608               1 :     delete poColorTable;
     609               2 : }
     610                 : 
     611                 : /************************************************************************/
     612                 : /*                          GetGeoTransform()                           */
     613                 : /************************************************************************/
     614                 : 
     615               0 : CPLErr RIKDataset::GetGeoTransform( double * padfTransform )
     616                 : 
     617                 : {
     618               0 :     memcpy( padfTransform, &fTransform, sizeof(double) * 6 );
     619                 : 
     620               0 :     return CE_None;
     621                 : }
     622                 : 
     623                 : /************************************************************************/
     624                 : /*                          GetProjectionRef()                          */
     625                 : /************************************************************************/
     626                 : 
     627               0 : const char *RIKDataset::GetProjectionRef()
     628                 : 
     629                 : {
     630               0 :   return( "PROJCS[\"RT90 2.5 gon V\",GEOGCS[\"RT90\",DATUM[\"Rikets_koordinatsystem_1990\",SPHEROID[\"Bessel 1841\",6377397.155,299.1528128,AUTHORITY[\"EPSG\",\"7004\"]],TOWGS84[414.1055246174,41.3265500042,603.0582474221,-0.8551163377,2.1413174055,-7.0227298286,0],AUTHORITY[\"EPSG\",\"6124\"]],PRIMEM[\"Greenwich\",0,AUTHORITY[\"EPSG\",\"8901\"]],UNIT[\"degree\",0.01745329251994328,AUTHORITY[\"EPSG\",\"9122\"]],AUTHORITY[\"EPSG\",\"4124\"]],PROJECTION[\"Transverse_Mercator\"],PARAMETER[\"latitude_of_origin\",0],PARAMETER[\"central_meridian\",15.80827777777778],PARAMETER[\"scale_factor\",1],PARAMETER[\"false_easting\",1500000],PARAMETER[\"false_northing\",0],UNIT[\"metre\",1,AUTHORITY[\"EPSG\",\"9001\"]],AUTHORITY[\"EPSG\",\"3021\"]]" );
     631                 : }
     632                 : 
     633                 : /************************************************************************/
     634                 : /*                             GetRikString()                           */
     635                 : /************************************************************************/
     636                 : 
     637             170 : static GUInt16 GetRikString( FILE *fp,
     638                 :                              char *str,
     639                 :                              GUInt16 strLength )
     640                 : 
     641                 : {
     642                 :     GUInt16 actLength;
     643                 : 
     644             170 :     VSIFRead( &actLength, 1, sizeof(actLength), fp );
     645                 : #ifdef CPL_MSB
     646                 :     CPL_SWAP16PTR( &actLength );
     647                 : #endif
     648                 : 
     649             170 :     if( actLength + 2 > strLength )
     650                 :     {
     651             111 :         return actLength;
     652                 :     }
     653                 : 
     654              59 :     VSIFRead( str, 1, actLength, fp );
     655                 : 
     656              59 :     str[actLength] = '\0';
     657                 : 
     658              59 :     return actLength;
     659                 : }
     660                 : 
     661                 : /************************************************************************/
     662                 : /*                                Open()                                */
     663                 : /************************************************************************/
     664                 : 
     665            8491 : GDALDataset *RIKDataset::Open( GDALOpenInfo * poOpenInfo )
     666                 : 
     667                 : {
     668            8491 :     if( poOpenInfo->fp == NULL || poOpenInfo->nHeaderBytes < 50 )
     669            8325 :         return NULL;
     670                 : 
     671             166 :     bool rik3header = false;
     672                 : 
     673             166 :     if( EQUALN((const char *) poOpenInfo->pabyHeader, "RIK3", 4) )
     674                 :     {
     675               1 :         rik3header = true;
     676                 :     }
     677                 : 
     678             166 :     if( rik3header )
     679               1 :         VSIFSeek( poOpenInfo->fp, 4, SEEK_SET );
     680                 :     else
     681             165 :         VSIFSeek( poOpenInfo->fp, 0, SEEK_SET );
     682                 : 
     683                 : /* -------------------------------------------------------------------- */
     684                 : /*      Read the map name.                                              */
     685                 : /* -------------------------------------------------------------------- */
     686                 : 
     687                 :     char name[1024];
     688                 : 
     689             166 :     GUInt16 nameLength = GetRikString( poOpenInfo->fp, name, sizeof(name) );
     690                 : 
     691             166 :     if( nameLength > sizeof(name) - 1 )
     692                 :     {
     693             111 :         return NULL;
     694                 :     }
     695                 : 
     696              55 :     if( !rik3header )
     697                 :     {
     698              54 :         if( nameLength == 0 || nameLength != strlen(name) )
     699              54 :             return NULL;
     700                 :     }
     701                 : 
     702                 : /* -------------------------------------------------------------------- */
     703                 : /*      Read the header.                                                */
     704                 : /* -------------------------------------------------------------------- */
     705                 : 
     706                 :     RIKHeader header;
     707                 :     double metersPerPixel;
     708                 : 
     709               1 :     const char *headerType = "RIK3";
     710                 : 
     711               1 :     if( rik3header )
     712                 :     {
     713                 : /* -------------------------------------------------------------------- */
     714                 : /*      RIK3 header.                                                    */
     715                 : /* -------------------------------------------------------------------- */
     716                 : 
     717                 :         // Read projection name
     718                 : 
     719                 :         char projection[1024];
     720                 : 
     721                 :         GUInt16 projLength = GetRikString( poOpenInfo->fp,
     722               1 :                                            projection, sizeof(projection) );
     723                 : 
     724               1 :         if( projLength > sizeof(projection) - 1 )
     725                 :         {
     726                 :             // Unreasonable string length, assume wrong format
     727               0 :             return NULL;
     728                 :         }
     729                 : 
     730                 :         // Read unknown string
     731                 : 
     732               1 :         projLength = GetRikString( poOpenInfo->fp, projection, sizeof(projection) );
     733                 : 
     734                 :         // Read map north edge
     735                 : 
     736                 :         char tmpStr[16];
     737                 : 
     738                 :         GUInt16 tmpLength = GetRikString( poOpenInfo->fp,
     739               1 :                                           tmpStr, sizeof(tmpStr) );
     740                 : 
     741               1 :         if( tmpLength > sizeof(tmpStr) - 1 )
     742                 :         {
     743                 :             // Unreasonable string length, assume wrong format
     744               0 :             return NULL;
     745                 :         }
     746                 : 
     747               1 :         header.fNorth = atof( tmpStr );
     748                 : 
     749                 :         // Read map west edge
     750                 : 
     751                 :         tmpLength = GetRikString( poOpenInfo->fp,
     752               1 :                                   tmpStr, sizeof(tmpStr) );
     753                 : 
     754               1 :         if( tmpLength > sizeof(tmpStr) - 1 )
     755                 :         {
     756                 :             // Unreasonable string length, assume wrong format
     757               0 :             return NULL;
     758                 :         }
     759                 : 
     760               1 :         header.fWest = atof( tmpStr );
     761                 : 
     762                 :         // Read binary values
     763                 : 
     764               1 :         VSIFRead( &header.iScale, 1, sizeof(header.iScale), poOpenInfo->fp );
     765               1 :         VSIFRead( &header.iMPPNum, 1, sizeof(header.iMPPNum), poOpenInfo->fp );
     766               1 :         VSIFRead( &header.iBlockWidth, 1, sizeof(header.iBlockWidth), poOpenInfo->fp );
     767               1 :         VSIFRead( &header.iBlockHeight, 1, sizeof(header.iBlockHeight), poOpenInfo->fp );
     768               1 :         VSIFRead( &header.iHorBlocks, 1, sizeof(header.iHorBlocks), poOpenInfo->fp );
     769               1 :         VSIFRead( &header.iVertBlocks, 1, sizeof(header.iVertBlocks), poOpenInfo->fp );
     770                 : #ifdef CPL_MSB
     771                 :         CPL_SWAP32PTR( &header.iScale );
     772                 :         CPL_SWAP32PTR( &header.iMPPNum );
     773                 :         CPL_SWAP32PTR( &header.iBlockWidth );
     774                 :         CPL_SWAP32PTR( &header.iBlockHeight );
     775                 :         CPL_SWAP32PTR( &header.iHorBlocks );
     776                 :         CPL_SWAP32PTR( &header.iVertBlocks );
     777                 : #endif
     778                 : 
     779               1 :         VSIFRead( &header.iBitsPerPixel, 1, sizeof(header.iBitsPerPixel), poOpenInfo->fp );
     780               1 :         VSIFRead( &header.iOptions, 1, sizeof(header.iOptions), poOpenInfo->fp );
     781               1 :         header.iUnknown = header.iOptions;
     782               1 :         VSIFRead( &header.iOptions, 1, sizeof(header.iOptions), poOpenInfo->fp );
     783                 : 
     784                 :         header.fSouth = header.fNorth -
     785               1 :             header.iVertBlocks * header.iBlockHeight * header.iMPPNum;
     786                 :         header.fEast = header.fWest +
     787               1 :             header.iHorBlocks * header.iBlockWidth * header.iMPPNum;
     788                 : 
     789               1 :         metersPerPixel = header.iMPPNum;
     790                 :     }
     791                 :     else
     792                 :     {
     793                 : /* -------------------------------------------------------------------- */
     794                 : /*      Old RIK header.                                                 */
     795                 : /* -------------------------------------------------------------------- */
     796                 : 
     797               0 :         VSIFRead( &header.iUnknown, 1, sizeof(header.iUnknown), poOpenInfo->fp );
     798               0 :         VSIFRead( &header.fSouth, 1, sizeof(header.fSouth), poOpenInfo->fp );
     799               0 :         VSIFRead( &header.fWest, 1, sizeof(header.fWest), poOpenInfo->fp );
     800               0 :         VSIFRead( &header.fNorth, 1, sizeof(header.fNorth), poOpenInfo->fp );
     801               0 :         VSIFRead( &header.fEast, 1, sizeof(header.fEast), poOpenInfo->fp );
     802               0 :         VSIFRead( &header.iScale, 1, sizeof(header.iScale), poOpenInfo->fp );
     803               0 :         VSIFRead( &header.iMPPNum, 1, sizeof(header.iMPPNum), poOpenInfo->fp );
     804                 : #ifdef CPL_MSB
     805                 :         CPL_SWAP64PTR( &header.fSouth );
     806                 :         CPL_SWAP64PTR( &header.fWest );
     807                 :         CPL_SWAP64PTR( &header.fNorth );
     808                 :         CPL_SWAP64PTR( &header.fEast );
     809                 :         CPL_SWAP32PTR( &header.iScale );
     810                 :         CPL_SWAP32PTR( &header.iMPPNum );
     811                 : #endif
     812                 : 
     813               0 :         if (!CPLIsFinite(header.fSouth) |
     814                 :             !CPLIsFinite(header.fWest) |
     815                 :             !CPLIsFinite(header.fNorth) |
     816                 :             !CPLIsFinite(header.fEast))
     817               0 :             return NULL;
     818                 : 
     819                 :         bool offsetBounds;
     820                 : 
     821               0 :         offsetBounds = header.fSouth < 4000000;
     822                 : 
     823               0 :         header.iMPPDen = 1;
     824                 : 
     825               0 :         if( offsetBounds )
     826                 :         {
     827               0 :             header.fSouth += 4002995;
     828               0 :             header.fNorth += 5004000;
     829               0 :             header.fWest += 201000;
     830               0 :             header.fEast += 302005;
     831                 : 
     832               0 :             VSIFRead( &header.iMPPDen, 1, sizeof(header.iMPPDen), poOpenInfo->fp );
     833                 : #ifdef CPL_MSB
     834                 :             CPL_SWAP32PTR( &header.iMPPDen );
     835                 : #endif
     836                 : 
     837               0 :             headerType = "RIK1";
     838                 :         }
     839                 :         else
     840                 :         {
     841               0 :             headerType = "RIK2";
     842                 :         }
     843                 : 
     844               0 :         metersPerPixel = header.iMPPNum / double(header.iMPPDen);
     845                 : 
     846               0 :         VSIFRead( &header.iBlockWidth, 1, sizeof(header.iBlockWidth), poOpenInfo->fp );
     847               0 :         VSIFRead( &header.iBlockHeight, 1, sizeof(header.iBlockHeight), poOpenInfo->fp );
     848               0 :         VSIFRead( &header.iHorBlocks, 1, sizeof(header.iHorBlocks), poOpenInfo->fp );
     849                 : #ifdef CPL_MSB
     850                 :         CPL_SWAP32PTR( &header.iBlockWidth );
     851                 :         CPL_SWAP32PTR( &header.iBlockHeight );
     852                 :         CPL_SWAP32PTR( &header.iHorBlocks );
     853                 : #endif
     854                 : 
     855               0 :         if(( header.iBlockWidth > 2000 ) || ( header.iBlockWidth < 10 ) ||
     856                 :            ( header.iBlockHeight > 2000 ) || ( header.iBlockHeight < 10 ))
     857               0 :            return NULL;
     858                 : 
     859               0 :         if( !offsetBounds )
     860                 :         {
     861               0 :             VSIFRead( &header.iVertBlocks, 1, sizeof(header.iVertBlocks), poOpenInfo->fp );
     862                 : #ifdef CPL_MSB
     863                 :             CPL_SWAP32PTR( &header.iVertBlocks );
     864                 : #endif
     865                 :         }
     866                 : 
     867               0 :         if( offsetBounds || !header.iVertBlocks )
     868                 :         {
     869                 :             header.iVertBlocks = (GUInt32)
     870                 :                 ceil( (header.fNorth - header.fSouth) /
     871               0 :                       (header.iBlockHeight * metersPerPixel) );
     872                 :         }
     873                 : 
     874                 : #if RIK_HEADER_DEBUG
     875                 :         CPLDebug( "RIK",
     876                 :                   "Original vertical blocks %d\n",
     877                 :                   header.iVertBlocks );
     878                 : #endif
     879                 : 
     880               0 :         VSIFRead( &header.iBitsPerPixel, 1, sizeof(header.iBitsPerPixel), poOpenInfo->fp );
     881                 : 
     882               0 :         if( header.iBitsPerPixel != 8 )
     883                 :         {
     884                 :             CPLError( CE_Failure, CPLE_OpenFailed,
     885                 :                       "File %s has unsupported number of bits per pixel.\n",
     886               0 :                       poOpenInfo->pszFilename );
     887               0 :             return NULL;
     888                 :         }
     889                 : 
     890               0 :         VSIFRead( &header.iOptions, 1, sizeof(header.iOptions), poOpenInfo->fp );
     891                 : 
     892               0 :         if( !header.iHorBlocks || !header.iVertBlocks )
     893               0 :            return NULL;
     894                 : 
     895               0 :         if( header.iOptions != 0x00 && // Uncompressed
     896                 :             header.iOptions != 0x40 && // Uncompressed
     897                 :             header.iOptions != 0x01 && // RLE
     898                 :             header.iOptions != 0x41 && // RLE
     899                 :             header.iOptions != 0x0B && // LZW
     900                 :             header.iOptions != 0x0D )  // ZLIB
     901                 :         {
     902                 :             CPLError( CE_Failure, CPLE_OpenFailed,
     903                 :                       "File %s. Unknown map options.\n",
     904               0 :                       poOpenInfo->pszFilename );
     905               0 :             return NULL;
     906                 :         }
     907                 :     }
     908                 : 
     909                 : /* -------------------------------------------------------------------- */
     910                 : /*      Read the palette.                                               */
     911                 : /* -------------------------------------------------------------------- */
     912                 : 
     913                 :     GByte palette[768];
     914                 : 
     915                 :     GUInt16 i;
     916             257 :     for( i = 0; i < 256; i++ )
     917                 :     {
     918             256 :         VSIFRead( &palette[i * 3 + 2], 1, 1, poOpenInfo->fp );
     919             256 :         VSIFRead( &palette[i * 3 + 1], 1, 1, poOpenInfo->fp );
     920             256 :         VSIFRead( &palette[i * 3 + 0], 1, 1, poOpenInfo->fp );
     921                 :     }
     922                 : 
     923                 : /* -------------------------------------------------------------------- */
     924                 : /*      Find block offsets.                                             */
     925                 : /* -------------------------------------------------------------------- */
     926                 : 
     927                 :     GUInt32 blocks;
     928                 :     GUInt32 *offsets;
     929                 : 
     930               1 :     blocks = header.iHorBlocks * header.iVertBlocks;
     931               1 :     offsets = (GUInt32 *)CPLMalloc( blocks * sizeof(GUInt32) );
     932                 : 
     933               1 :     if( !offsets )
     934                 :     {
     935                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     936                 :                   "File %s. Unable to allocate offset table.\n",
     937               0 :                   poOpenInfo->pszFilename );
     938               0 :         return NULL;
     939                 :     }
     940                 : 
     941               1 :     if( header.iOptions == 0x00 )
     942                 :     {
     943               0 :         offsets[0] = VSIFTell( poOpenInfo->fp );
     944                 : 
     945               0 :         for( GUInt32 i = 1; i < blocks; i++ )
     946                 :         {
     947               0 :             offsets[i] = offsets[i - 1] +
     948               0 :                 header.iBlockWidth * header.iBlockHeight;
     949                 :         }
     950                 :     }
     951                 :     else
     952                 :     {
     953             136 :         for( GUInt32 i = 0; i < blocks; i++ )
     954                 :         {
     955             135 :             VSIFRead( &offsets[i], 1, sizeof(offsets[i]), poOpenInfo->fp );
     956                 : #ifdef CPL_MSB
     957                 :             CPL_SWAP32PTR( &offsets[i] );
     958                 : #endif
     959             135 :             if( rik3header )
     960                 :             {
     961                 :                 GUInt32 blockSize;
     962             135 :                 VSIFRead( &blockSize, 1, sizeof(blockSize), poOpenInfo->fp );
     963                 : #ifdef CPL_MSB
     964                 :                 CPL_SWAP32PTR( &blockSize );
     965                 : #endif
     966                 :             }
     967                 :         }
     968                 :     }
     969                 : 
     970                 : /* -------------------------------------------------------------------- */
     971                 : /*      Final checks.                                                   */
     972                 : /* -------------------------------------------------------------------- */
     973                 : 
     974                 :     // File size
     975                 : 
     976               1 :     if( VSIFEof( poOpenInfo->fp ) )
     977                 :     {
     978                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     979                 :                   "File %s. Read past end of file.\n",
     980               0 :                   poOpenInfo->pszFilename );
     981               0 :         return NULL;
     982                 :     }
     983                 : 
     984               1 :     VSIFSeek( poOpenInfo->fp, 0, SEEK_END );
     985               1 :     GUInt32 fileSize = VSIFTell( poOpenInfo->fp );
     986                 : 
     987                 : #if RIK_HEADER_DEBUG
     988                 :     CPLDebug( "RIK",
     989                 :               "File size %d\n",
     990                 :               fileSize );
     991                 : #endif
     992                 : 
     993                 :     // Make sure the offset table is valid
     994                 : 
     995               1 :     GUInt32 lastoffset = 0;
     996                 : 
     997              16 :     for( GUInt32 y = 0; y < header.iVertBlocks; y++)
     998                 :     {
     999             150 :         for( GUInt32 x = 0; x < header.iHorBlocks; x++)
    1000                 :         {
    1001             135 :             if( !offsets[x + y * header.iHorBlocks] )
    1002                 :             {
    1003               0 :                 continue;
    1004                 :             }
    1005                 : 
    1006             135 :             if( offsets[x + y * header.iHorBlocks] >= fileSize )
    1007                 :             {
    1008               0 :                 if( !y )
    1009                 :                 {
    1010                 :                     CPLError( CE_Failure, CPLE_OpenFailed,
    1011                 :                               "File %s too short.\n",
    1012               0 :                               poOpenInfo->pszFilename );
    1013               0 :                     return NULL;
    1014                 :                 }
    1015               0 :                 header.iVertBlocks = y;
    1016               0 :                 break;
    1017                 :             }
    1018                 : 
    1019             135 :             if( offsets[x + y * header.iHorBlocks] < lastoffset )
    1020                 :             {
    1021               0 :                 if( !y )
    1022                 :                 {
    1023                 :                     CPLError( CE_Failure, CPLE_OpenFailed,
    1024                 :                               "File %s. Corrupt offset table.\n",
    1025               0 :                               poOpenInfo->pszFilename );
    1026               0 :                     return NULL;
    1027                 :                 }
    1028               0 :                 header.iVertBlocks = y;
    1029               0 :                 break;
    1030                 :             }
    1031                 : 
    1032             135 :             lastoffset = offsets[x + y * header.iHorBlocks];
    1033                 :         }
    1034                 :     }
    1035                 : 
    1036                 : #if RIK_HEADER_DEBUG
    1037                 :     CPLDebug( "RIK",
    1038                 :               "first offset %d\n"
    1039                 :               "last offset %d\n",
    1040                 :               offsets[0],
    1041                 :               lastoffset );
    1042                 : #endif
    1043                 : 
    1044               1 :     const char *compression = "RLE";
    1045                 : 
    1046               1 :     if( header.iOptions == 0x00 ||
    1047                 :         header.iOptions == 0x40 )
    1048               0 :         compression = "Uncompressed";
    1049               1 :     if( header.iOptions == 0x0b )
    1050               0 :         compression = "LZW";
    1051               1 :     if( header.iOptions == 0x0d )
    1052               1 :         compression = "ZLIB";
    1053                 : 
    1054                 :     CPLDebug( "RIK",
    1055                 :               "RIK file parameters:\n"
    1056                 :               " name: %s\n"
    1057                 :               " header: %s\n"
    1058                 :               " unknown: 0x%X\n"
    1059                 :               " south: %lf\n"
    1060                 :               " west: %lf\n"
    1061                 :               " north: %lf\n"
    1062                 :               " east: %lf\n"
    1063                 :               " original scale: %d\n"
    1064                 :               " meters per pixel: %lf\n"
    1065                 :               " block width: %d\n"
    1066                 :               " block height: %d\n"
    1067                 :               " horizontal blocks: %d\n"
    1068                 :               " vertical blocks: %d\n"
    1069                 :               " bits per pixel: %d\n"
    1070                 :               " options: 0x%X\n"
    1071                 :               " compression: %s\n",
    1072                 :               name, headerType, header.iUnknown,
    1073                 :               header.fSouth, header.fWest, header.fNorth, header.fEast,
    1074                 :               header.iScale, metersPerPixel,
    1075                 :               header.iBlockWidth, header.iBlockHeight,
    1076                 :               header.iHorBlocks, header.iVertBlocks,
    1077               1 :               header.iBitsPerPixel, header.iOptions, compression);
    1078                 : 
    1079                 : /* -------------------------------------------------------------------- */
    1080                 : /*      Create a corresponding GDALDataset.                             */
    1081                 : /* -------------------------------------------------------------------- */
    1082                 : 
    1083                 :     RIKDataset  *poDS;
    1084                 : 
    1085               1 :     poDS = new RIKDataset();
    1086                 : 
    1087               1 :     poDS->fp = poOpenInfo->fp;
    1088               1 :     poOpenInfo->fp = NULL;
    1089                 : 
    1090               1 :     poDS->fTransform[0] = header.fWest - metersPerPixel / 2.0;
    1091               1 :     poDS->fTransform[1] = metersPerPixel;
    1092               1 :     poDS->fTransform[2] = 0.0;
    1093               1 :     poDS->fTransform[3] = header.fNorth + metersPerPixel / 2.0;
    1094               1 :     poDS->fTransform[4] = 0.0;
    1095               1 :     poDS->fTransform[5] = -metersPerPixel;
    1096                 : 
    1097               1 :     poDS->nBlockXSize = header.iBlockWidth;
    1098               1 :     poDS->nBlockYSize = header.iBlockHeight;
    1099               1 :     poDS->nHorBlocks = header.iHorBlocks;
    1100               1 :     poDS->nVertBlocks = header.iVertBlocks;
    1101               1 :     poDS->pOffsets = offsets;
    1102               1 :     poDS->options = header.iOptions;
    1103               1 :     poDS->nFileSize = fileSize;
    1104                 : 
    1105               1 :     poDS->nRasterXSize = header.iBlockWidth * header.iHorBlocks;
    1106               1 :     poDS->nRasterYSize = header.iBlockHeight * header.iVertBlocks;
    1107                 : 
    1108               1 :     poDS->nBands = 1;
    1109                 : 
    1110                 :     GDALColorEntry oEntry;
    1111               2 :     poDS->poColorTable = new GDALColorTable();
    1112             257 :     for( i = 0; i < 256; i++ )
    1113                 :     {
    1114             256 :         oEntry.c1 = palette[i * 3 + 2]; // Red
    1115             256 :         oEntry.c2 = palette[i * 3 + 1]; // Green
    1116             256 :         oEntry.c3 = palette[i * 3];     // Blue
    1117             256 :         oEntry.c4 = 255;
    1118                 : 
    1119             256 :         poDS->poColorTable->SetColorEntry( i, &oEntry );
    1120                 :     }
    1121                 : 
    1122                 : /* -------------------------------------------------------------------- */
    1123                 : /*      Create band information objects.                                */
    1124                 : /* -------------------------------------------------------------------- */
    1125                 : 
    1126               1 :     poDS->SetBand( 1, new RIKRasterBand( poDS, 1 ));
    1127                 : 
    1128                 : /* -------------------------------------------------------------------- */
    1129                 : /*      Initialize any PAM information.                                 */
    1130                 : /* -------------------------------------------------------------------- */
    1131                 : 
    1132               1 :     poDS->SetDescription( poOpenInfo->pszFilename );
    1133               1 :     poDS->TryLoadXML();
    1134                 :     
    1135                 : /* -------------------------------------------------------------------- */
    1136                 : /*      Confirm the requested access is supported.                      */
    1137                 : /* -------------------------------------------------------------------- */
    1138               1 :     if( poOpenInfo->eAccess == GA_Update )
    1139                 :     {
    1140               0 :         delete poDS;
    1141                 :         CPLError( CE_Failure, CPLE_NotSupported, 
    1142                 :                   "The RIK driver does not support update access to existing"
    1143               0 :                   " datasets.\n" );
    1144               0 :         return NULL;
    1145                 :     }
    1146                 :     
    1147               1 :     return( poDS );
    1148                 : }
    1149                 : 
    1150                 : /************************************************************************/
    1151                 : /*                          GDALRegister_RIK()                          */
    1152                 : /************************************************************************/
    1153                 : 
    1154             338 : void GDALRegister_RIK()
    1155                 : 
    1156                 : {
    1157                 :     GDALDriver  *poDriver;
    1158                 : 
    1159             338 :     if( GDALGetDriverByName( "RIK" ) == NULL )
    1160                 :     {
    1161             336 :         poDriver = new GDALDriver();
    1162                 : 
    1163             336 :         poDriver->SetDescription( "RIK" );
    1164                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
    1165             336 :                                    "Swedish Grid RIK (.rik)" );
    1166                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
    1167             336 :                                    "frmt_various.html#RIK" );
    1168             336 :         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "rik" );
    1169                 : 
    1170             336 :         poDriver->pfnOpen = RIKDataset::Open;
    1171                 : 
    1172             336 :         GetGDALDriverManager()->RegisterDriver( poDriver );
    1173                 :     }
    1174             338 : }

Generated by: LCOV version 1.7