LCOV - code coverage report
Current view: directory - frmts/rik - rikdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 346 278 80.3 %
Date: 2011-12-18 Functions: 18 10 55.6 %

       1                 : /******************************************************************************
       2                 :  * $Id: rikdataset.cpp 23060 2011-09-05 17:58:30Z 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 23060 2011-09-05 17:58:30Z 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               2 : {
     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               2 : RIKRasterBand::RIKRasterBand( RIKDataset *poDS, int nBand )
     171                 : 
     172                 : {
     173               2 :     this->poDS = poDS;
     174               2 :     this->nBand = nBand;
     175                 : 
     176               2 :     eDataType = GDT_Byte;
     177                 : 
     178               2 :     nBlockXSize = poDS->nBlockXSize;
     179               2 :     nBlockYSize = poDS->nBlockYSize;
     180               2 : }
     181                 : 
     182                 : /************************************************************************/
     183                 : /*                             GetNextLZWCode()                         */
     184                 : /************************************************************************/
     185                 : 
     186          240097 : static int GetNextLZWCode( int codeBits,
     187                 :                            GByte *blockData,
     188                 :                            GUInt32 &filePos,
     189                 :                            GUInt32 &fileAlign,
     190                 :                            int &bitsTaken )
     191                 : 
     192                 : {
     193          240097 :     if( filePos == fileAlign )
     194                 :     {
     195           30024 :         fileAlign += codeBits;
     196                 :     }
     197                 : 
     198                 :     const int BitMask[] = {
     199                 :         0x0000, 0x0001, 0x0003, 0x0007,
     200          240097 :         0x000f, 0x001f, 0x003f, 0x007f };
     201                 : 
     202          240097 :     int ret = 0;
     203          240097 :     int bitsLeftToGo = codeBits;
     204                 : 
     205         1041854 :     while( bitsLeftToGo > 0 )
     206                 :     {
     207                 :         int tmp;
     208                 : 
     209          561660 :         tmp = blockData[filePos];
     210          561660 :         tmp = tmp >> bitsTaken;
     211                 : 
     212          561660 :         if( bitsLeftToGo < 8 )
     213          190913 :             tmp &= BitMask[bitsLeftToGo];
     214                 : 
     215          561660 :         tmp = tmp << (codeBits - bitsLeftToGo);
     216                 : 
     217          561660 :         ret |= tmp;
     218                 : 
     219          561660 :         bitsLeftToGo -= (8 - bitsTaken);
     220          561660 :         bitsTaken = 0;
     221                 : 
     222          561660 :         if( bitsLeftToGo < 0 )
     223          190913 :             bitsTaken = 8 + bitsLeftToGo;
     224                 : 
     225          561660 :         if( bitsTaken == 0 )
     226          370747 :             filePos++;
     227                 :     }
     228                 : 
     229                 : #if RIK_PIXEL_DEBUG
     230                 :     printf( "c%03X\n", ret );
     231                 : #endif
     232                 : 
     233          240097 :     return ret;
     234                 : }
     235                 : 
     236                 : /************************************************************************/
     237                 : /*                             OutputPixel()                            */
     238                 : /************************************************************************/
     239                 : 
     240          755976 : static void OutputPixel( GByte pixel,
     241                 :                          void * image,
     242                 :                          GUInt32 imageWidth,
     243                 :                          GUInt32 lineBreak,
     244                 :                          int &imageLine,
     245                 :                          GUInt32 &imagePos )
     246                 : 
     247                 : {
     248          755976 :     if( imagePos < imageWidth && imageLine >= 0)
     249          750000 :         ((GByte *) image)[imagePos + imageLine * imageWidth] = pixel;
     250                 : 
     251          755976 :     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          755976 :     if( imagePos == lineBreak )
     260                 :     {
     261                 : #if RIK_PIXEL_DEBUG
     262                 :         printf( "\n%d\n", imageLine );
     263                 : #endif
     264                 : 
     265            2988 :         imagePos = 0;
     266                 : 
     267            2988 :         imageLine--;
     268                 :     }
     269          755976 : }
     270                 : 
     271                 : /************************************************************************/
     272                 : /*                             IReadBlock()                             */
     273                 : /************************************************************************/
     274                 : 
     275             147 : CPLErr RIKRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
     276                 :                                   void * pImage )
     277                 : 
     278                 : {
     279             147 :     RIKDataset *poRDS = (RIKDataset *) poDS;
     280                 :     GByte *blockData;
     281                 :     GUInt32 blocks;
     282                 :     GUInt32 nBlockIndex;
     283                 :     GUInt32 nBlockOffset;
     284                 :     GUInt32 nBlockSize;
     285                 : 
     286             147 :     blocks = poRDS->nHorBlocks * poRDS->nVertBlocks;
     287             147 :     nBlockIndex = nBlockXOff + nBlockYOff * poRDS->nHorBlocks;
     288             147 :     nBlockOffset = poRDS->pOffsets[nBlockIndex];
     289                 : 
     290             147 :     nBlockSize = poRDS->nFileSize;
     291             147 :     for( GUInt32 bi = nBlockIndex + 1; bi < blocks; bi++ )
     292                 :     {
     293             145 :         if( poRDS->pOffsets[bi] )
     294                 :         {
     295             145 :             nBlockSize = poRDS->pOffsets[bi];
     296             145 :             break;
     297                 :         }
     298                 :     }
     299             147 :     nBlockSize -= nBlockOffset;
     300                 : 
     301                 :     GUInt32 pixels;
     302                 : 
     303             147 :     pixels = poRDS->nBlockXSize * poRDS->nBlockYSize;
     304                 : 
     305             147 :     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             147 :     VSIFSeek( poRDS->fp, nBlockOffset, SEEK_SET );
     317                 : 
     318                 : /* -------------------------------------------------------------------- */
     319                 : /*      Read uncompressed block.                                        */
     320                 : /* -------------------------------------------------------------------- */
     321                 : 
     322             147 :     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             147 :     blockData = (GByte *) CPLMalloc(nBlockSize);
     330             147 :     VSIFRead( blockData, 1, nBlockSize, poRDS->fp );
     331                 : 
     332             147 :     GUInt32 filePos = 0;
     333             147 :     GUInt32 imagePos = 0;
     334                 : 
     335                 : /* -------------------------------------------------------------------- */
     336                 : /*      Read RLE block.                                                 */
     337                 : /* -------------------------------------------------------------------- */
     338                 : 
     339             147 :     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             147 :     else if( poRDS->options == 0x0b )
     356                 :     {
     357              12 :         const bool LZW_HAS_CLEAR_CODE = !!(blockData[4] & 0x80);
     358              12 :         const int LZW_MAX_BITS = blockData[4] & 0x1f; // Max 13
     359              12 :         const int LZW_BITS_PER_PIXEL = 8;
     360              12 :         const int LZW_OFFSET = 5;
     361                 : 
     362              12 :         const int LZW_CLEAR = 1 << LZW_BITS_PER_PIXEL;
     363              12 :         const int LZW_CODES = 1 << LZW_MAX_BITS;
     364              12 :         const int LZW_NO_SUCH_CODE = LZW_CODES + 1;
     365                 : 
     366              12 :         int lastAdded = LZW_HAS_CLEAR_CODE ? LZW_CLEAR : LZW_CLEAR - 1;
     367              12 :         int codeBits = LZW_BITS_PER_PIXEL + 1;
     368                 : 
     369                 :         int code;
     370                 :         int lastCode;
     371                 :         GByte lastOutput;
     372              12 :         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                 : 
     379            3084 :         for( i = 0; i < LZW_CLEAR; i++ )
     380            3072 :             character[i] = (GByte)i;
     381           98316 :         for( i = 0; i < LZW_CODES; i++ )
     382           98304 :             prefix[i] = LZW_NO_SUCH_CODE;
     383                 : 
     384              12 :         filePos = LZW_OFFSET;
     385              12 :         GUInt32 fileAlign = LZW_OFFSET;
     386              12 :         int imageLine = poRDS->nBlockYSize - 1;
     387                 : 
     388              12 :         GUInt32 lineBreak = poRDS->nBlockXSize;
     389                 : 
     390                 :         // 32 bit alignment
     391              12 :         lineBreak += 3;
     392              12 :         lineBreak &= 0xfffffffc;
     393                 : 
     394                 :         code = GetNextLZWCode( codeBits, blockData, filePos,
     395              12 :                                fileAlign, bitsTaken );
     396                 : 
     397                 :         OutputPixel( (GByte)code, pImage, poRDS->nBlockXSize,
     398              12 :                      lineBreak, imageLine, imagePos );
     399              12 :         lastOutput = (GByte)code;
     400                 : 
     401          240097 :         while( imageLine >= 0 &&
     402                 :                (imageLine || imagePos < poRDS->nBlockXSize) &&
     403                 :                filePos < nBlockSize ) try
     404                 :         {
     405          240073 :             lastCode = code;
     406                 :             code = GetNextLZWCode( codeBits, blockData,
     407          240073 :                                    filePos, fileAlign, bitsTaken );
     408          240073 :             if( VSIFEof( poRDS->fp ) )
     409                 :             {
     410               0 :                 CPLFree( blockData );
     411                 :                 CPLError( CE_Failure, CPLE_AppDefined,
     412                 :                           "RIK decompression failed. "
     413               0 :                           "Read past end of file.\n" );
     414               0 :                 return CE_Failure;
     415                 :             }
     416                 : 
     417          240085 :             if( LZW_HAS_CLEAR_CODE && code == LZW_CLEAR )
     418                 :             {
     419                 : #if RIK_CLEAR_DEBUG
     420                 :                 CPLDebug( "RIK",
     421                 :                           "Clearing block %d\n"
     422                 :                           " x=%d y=%d\n"
     423                 :                           " pos=%d size=%d\n",
     424                 :                           nBlockIndex,
     425                 :                           imagePos, imageLine,
     426                 :                           filePos, nBlockSize );
     427                 : #endif
     428                 : 
     429                 :                 // Clear prefix table
     430           95244 :                 for( i = LZW_CLEAR; i < LZW_CODES; i++ )
     431           95232 :                     prefix[i] = LZW_NO_SUCH_CODE;
     432              12 :                 lastAdded = LZW_CLEAR;
     433              12 :                 codeBits = LZW_BITS_PER_PIXEL + 1;
     434                 : 
     435              12 :                 filePos = fileAlign;
     436              12 :                 bitsTaken = 0;
     437                 : 
     438                 :                 code = GetNextLZWCode( codeBits, blockData,
     439              12 :                                        filePos, fileAlign, bitsTaken );
     440                 : 
     441              12 :                 if( code > lastAdded )
     442                 :                 {
     443               0 :                     throw "Clear Error";
     444                 :                 }
     445                 : 
     446                 :                 OutputPixel( (GByte)code, pImage, poRDS->nBlockXSize,
     447              12 :                              lineBreak, imageLine, imagePos );
     448              12 :                 lastOutput = (GByte)code;
     449                 :             }
     450                 :             else
     451                 :             {
     452                 :                 // Set-up decoding
     453                 : 
     454                 :                 GByte stack[8192]; // only need LZW_CODES for size.
     455                 : 
     456          240061 :                 int stackPtr = 0;
     457          240061 :                 int decodeCode = code;
     458                 : 
     459          240061 :                 if( code == lastAdded + 1 )
     460                 :                 {
     461                 :                     // Handle special case
     462            1410 :                     *stack = lastOutput;
     463            1410 :                     stackPtr = 1;
     464            1410 :                     decodeCode = lastCode;
     465                 :                 }
     466          238651 :                 else if( code > lastAdded + 1 )
     467                 :                 {
     468               0 :                     throw "Too high code";
     469                 :                 }
     470                 : 
     471                 :                 // Decode
     472                 : 
     473          240061 :                 i = 0;
     474          994603 :                 while( ++i < LZW_CODES &&
     475                 :                        decodeCode >= LZW_CLEAR &&
     476                 :                        decodeCode < LZW_NO_SUCH_CODE )
     477                 :                 {
     478          514481 :                     stack[stackPtr++] = character[decodeCode];
     479          514481 :                     decodeCode = prefix[decodeCode];
     480                 :                 }
     481          240061 :                 stack[stackPtr++] = (GByte)decodeCode;
     482                 : 
     483          240061 :                 if( i == LZW_CODES || decodeCode >= LZW_NO_SUCH_CODE )
     484                 :                 {
     485               0 :                     throw "Decode error";
     486                 :                 }
     487                 : 
     488                 :                 // Output stack
     489                 : 
     490          240061 :                 lastOutput = stack[stackPtr - 1];
     491                 : 
     492         1236074 :                 while( stackPtr != 0 && imagePos < pixels )
     493                 :                 {
     494          755952 :                     OutputPixel( stack[--stackPtr], pImage, poRDS->nBlockXSize,
     495         1511904 :                                  lineBreak, imageLine, imagePos );
     496                 :                 }
     497                 : 
     498                 :                 // Add code to string table
     499                 : 
     500          240061 :                 if( lastCode != LZW_NO_SUCH_CODE &&
     501                 :                     lastAdded != LZW_CODES - 1 )
     502                 :                 {
     503          173362 :                     prefix[++lastAdded] = lastCode;
     504          173362 :                     character[lastAdded] = lastOutput;
     505                 :                 }
     506                 : 
     507                 :                 // Check if we need to use more bits
     508                 : 
     509          240061 :                 if( lastAdded == (1 << codeBits) - 1 &&
     510                 :                     codeBits != LZW_MAX_BITS )
     511                 :                 {
     512              93 :                      codeBits++;
     513                 : 
     514              93 :                      filePos = fileAlign;
     515              93 :                      bitsTaken = 0;
     516                 :                 }
     517                 :             }
     518                 :         }
     519               0 :         catch (const char *errStr)
     520                 :         {
     521                 : #if RIK_ALLOW_BLOCK_ERRORS
     522                 :                 CPLDebug( "RIK",
     523                 :                           "LZW Decompress Failed: %s\n"
     524                 :                           " blocks: %d\n"
     525                 :                           " blockindex: %d\n"
     526                 :                           " blockoffset: %X\n"
     527                 :                           " blocksize: %d\n",
     528                 :                           errStr, blocks, nBlockIndex,
     529               0 :                           nBlockOffset, nBlockSize );
     530                 :                 break;
     531                 : #else
     532                 :                 CPLFree( blockData );
     533                 :                 CPLError( CE_Failure, CPLE_AppDefined,
     534                 :                           "RIK decompression failed. "
     535                 :                           "Corrupt image block." );
     536                 :                 return CE_Failure;
     537                 : #endif
     538                 :         }
     539                 :     }
     540                 : 
     541                 : /* -------------------------------------------------------------------- */
     542                 : /*      Read ZLIB block.                                                */
     543                 : /* -------------------------------------------------------------------- */
     544                 : 
     545             135 :     else if( poRDS->options == 0x0d )
     546                 :     {
     547             135 :         uLong destLen = pixels;
     548             135 :         Byte *upsideDown = (Byte *) CPLMalloc( pixels );
     549                 : 
     550             135 :         uncompress( upsideDown, &destLen, blockData, nBlockSize );
     551                 : 
     552           33885 :         for (GUInt32 i = 0; i < poRDS->nBlockYSize; i++)
     553                 :         {
     554                 :             memcpy( ((Byte *)pImage) + poRDS->nBlockXSize * i,
     555                 :                     upsideDown + poRDS->nBlockXSize *
     556                 :                                  (poRDS->nBlockYSize - i - 1),
     557           33750 :                     poRDS->nBlockXSize );
     558                 :         }
     559                 : 
     560             135 :         CPLFree( upsideDown );
     561                 :     }
     562                 : 
     563             147 :     CPLFree( blockData );
     564                 : 
     565             147 :     return CE_None;
     566                 : }
     567                 : 
     568                 : /************************************************************************/
     569                 : /*                       GetColorInterpretation()                       */
     570                 : /************************************************************************/
     571                 : 
     572               0 : GDALColorInterp RIKRasterBand::GetColorInterpretation()
     573                 : 
     574                 : {
     575               0 :     return GCI_PaletteIndex;
     576                 : }
     577                 : 
     578                 : /************************************************************************/
     579                 : /*                           GetColorTable()                            */
     580                 : /************************************************************************/
     581                 : 
     582               0 : GDALColorTable *RIKRasterBand::GetColorTable()
     583                 : 
     584                 : {
     585               0 :     RIKDataset *poRDS = (RIKDataset *) poDS;
     586                 : 
     587               0 :     return poRDS->poColorTable;
     588                 : }
     589                 : 
     590                 : /************************************************************************/
     591                 : /* ==================================================================== */
     592                 : /*        RIKDataset        */
     593                 : /* ==================================================================== */
     594                 : /************************************************************************/
     595                 : 
     596                 : /************************************************************************/
     597                 : /*                            ~RIKDataset()                             */
     598                 : /************************************************************************/
     599                 : 
     600               2 : RIKDataset::~RIKDataset()
     601                 : 
     602                 : {
     603               2 :     FlushCache();
     604               2 :     CPLFree( pOffsets );
     605               2 :     if( fp != NULL )
     606               2 :         VSIFClose( fp );
     607               2 :     delete poColorTable;
     608               2 : }
     609                 : 
     610                 : /************************************************************************/
     611                 : /*                          GetGeoTransform()                           */
     612                 : /************************************************************************/
     613                 : 
     614               0 : CPLErr RIKDataset::GetGeoTransform( double * padfTransform )
     615                 : 
     616                 : {
     617               0 :     memcpy( padfTransform, &fTransform, sizeof(double) * 6 );
     618                 : 
     619               0 :     return CE_None;
     620                 : }
     621                 : 
     622                 : /************************************************************************/
     623                 : /*                          GetProjectionRef()                          */
     624                 : /************************************************************************/
     625                 : 
     626               0 : const char *RIKDataset::GetProjectionRef()
     627                 : 
     628                 : {
     629               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\"]]" );
     630                 : }
     631                 : 
     632                 : /************************************************************************/
     633                 : /*                             GetRikString()                           */
     634                 : /************************************************************************/
     635                 : 
     636             336 : static GUInt16 GetRikString( FILE *fp,
     637                 :                              char *str,
     638                 :                              GUInt16 strLength )
     639                 : 
     640                 : {
     641                 :     GUInt16 actLength;
     642                 : 
     643             336 :     VSIFRead( &actLength, 1, sizeof(actLength), fp );
     644                 : #ifdef CPL_MSB
     645                 :     CPL_SWAP16PTR( &actLength );
     646                 : #endif
     647                 : 
     648             336 :     if( actLength + 2 > strLength )
     649                 :     {
     650             233 :         return actLength;
     651                 :     }
     652                 : 
     653             103 :     VSIFRead( str, 1, actLength, fp );
     654                 : 
     655             103 :     str[actLength] = '\0';
     656                 : 
     657             103 :     return actLength;
     658                 : }
     659                 : 
     660                 : /************************************************************************/
     661                 : /*                                Open()                                */
     662                 : /************************************************************************/
     663                 : 
     664           10755 : GDALDataset *RIKDataset::Open( GDALOpenInfo * poOpenInfo )
     665                 : 
     666                 : {
     667           10755 :     if( poOpenInfo->fp == NULL || poOpenInfo->nHeaderBytes < 50 )
     668           10423 :         return NULL;
     669                 : 
     670             332 :     bool rik3header = false;
     671                 : 
     672             332 :     if( EQUALN((const char *) poOpenInfo->pabyHeader, "RIK3", 4) )
     673                 :     {
     674               1 :         rik3header = true;
     675                 :     }
     676                 : 
     677             332 :     if( rik3header )
     678               1 :         VSIFSeek( poOpenInfo->fp, 4, SEEK_SET );
     679                 :     else
     680             331 :         VSIFSeek( poOpenInfo->fp, 0, SEEK_SET );
     681                 : 
     682                 : /* -------------------------------------------------------------------- */
     683                 : /*      Read the map name.                                              */
     684                 : /* -------------------------------------------------------------------- */
     685                 : 
     686                 :     char name[1024];
     687                 : 
     688             332 :     GUInt16 nameLength = GetRikString( poOpenInfo->fp, name, sizeof(name) );
     689                 : 
     690             332 :     if( nameLength > sizeof(name) - 1 )
     691                 :     {
     692             233 :         return NULL;
     693                 :     }
     694                 : 
     695              99 :     if( !rik3header )
     696                 :     {
     697              98 :         if( nameLength == 0 || nameLength != strlen(name) )
     698              97 :             return NULL;
     699                 :     }
     700                 : 
     701                 : /* -------------------------------------------------------------------- */
     702                 : /*      Read the header.                                                */
     703                 : /* -------------------------------------------------------------------- */
     704                 : 
     705                 :     RIKHeader header;
     706                 :     double metersPerPixel;
     707                 : 
     708               2 :     const char *headerType = "RIK3";
     709                 : 
     710               2 :     if( rik3header )
     711                 :     {
     712                 : /* -------------------------------------------------------------------- */
     713                 : /*      RIK3 header.                                                    */
     714                 : /* -------------------------------------------------------------------- */
     715                 : 
     716                 :         // Read projection name
     717                 : 
     718                 :         char projection[1024];
     719                 : 
     720                 :         GUInt16 projLength = GetRikString( poOpenInfo->fp,
     721               1 :                                            projection, sizeof(projection) );
     722                 : 
     723               1 :         if( projLength > sizeof(projection) - 1 )
     724                 :         {
     725                 :             // Unreasonable string length, assume wrong format
     726               0 :             return NULL;
     727                 :         }
     728                 : 
     729                 :         // Read unknown string
     730                 : 
     731               1 :         projLength = GetRikString( poOpenInfo->fp, projection, sizeof(projection) );
     732                 : 
     733                 :         // Read map north edge
     734                 : 
     735                 :         char tmpStr[16];
     736                 : 
     737                 :         GUInt16 tmpLength = GetRikString( poOpenInfo->fp,
     738               1 :                                           tmpStr, sizeof(tmpStr) );
     739                 : 
     740               1 :         if( tmpLength > sizeof(tmpStr) - 1 )
     741                 :         {
     742                 :             // Unreasonable string length, assume wrong format
     743               0 :             return NULL;
     744                 :         }
     745                 : 
     746               1 :         header.fNorth = atof( tmpStr );
     747                 : 
     748                 :         // Read map west edge
     749                 : 
     750                 :         tmpLength = GetRikString( poOpenInfo->fp,
     751               1 :                                   tmpStr, sizeof(tmpStr) );
     752                 : 
     753               1 :         if( tmpLength > sizeof(tmpStr) - 1 )
     754                 :         {
     755                 :             // Unreasonable string length, assume wrong format
     756               0 :             return NULL;
     757                 :         }
     758                 : 
     759               1 :         header.fWest = atof( tmpStr );
     760                 : 
     761                 :         // Read binary values
     762                 : 
     763               1 :         VSIFRead( &header.iScale, 1, sizeof(header.iScale), poOpenInfo->fp );
     764               1 :         VSIFRead( &header.iMPPNum, 1, sizeof(header.iMPPNum), poOpenInfo->fp );
     765               1 :         VSIFRead( &header.iBlockWidth, 1, sizeof(header.iBlockWidth), poOpenInfo->fp );
     766               1 :         VSIFRead( &header.iBlockHeight, 1, sizeof(header.iBlockHeight), poOpenInfo->fp );
     767               1 :         VSIFRead( &header.iHorBlocks, 1, sizeof(header.iHorBlocks), poOpenInfo->fp );
     768               1 :         VSIFRead( &header.iVertBlocks, 1, sizeof(header.iVertBlocks), poOpenInfo->fp );
     769                 : #ifdef CPL_MSB
     770                 :         CPL_SWAP32PTR( &header.iScale );
     771                 :         CPL_SWAP32PTR( &header.iMPPNum );
     772                 :         CPL_SWAP32PTR( &header.iBlockWidth );
     773                 :         CPL_SWAP32PTR( &header.iBlockHeight );
     774                 :         CPL_SWAP32PTR( &header.iHorBlocks );
     775                 :         CPL_SWAP32PTR( &header.iVertBlocks );
     776                 : #endif
     777                 : 
     778               1 :         VSIFRead( &header.iBitsPerPixel, 1, sizeof(header.iBitsPerPixel), poOpenInfo->fp );
     779               1 :         VSIFRead( &header.iOptions, 1, sizeof(header.iOptions), poOpenInfo->fp );
     780               1 :         header.iUnknown = header.iOptions;
     781               1 :         VSIFRead( &header.iOptions, 1, sizeof(header.iOptions), poOpenInfo->fp );
     782                 : 
     783                 :         header.fSouth = header.fNorth -
     784               1 :             header.iVertBlocks * header.iBlockHeight * header.iMPPNum;
     785                 :         header.fEast = header.fWest +
     786               1 :             header.iHorBlocks * header.iBlockWidth * header.iMPPNum;
     787                 : 
     788               1 :         metersPerPixel = header.iMPPNum;
     789                 :     }
     790                 :     else
     791                 :     {
     792                 : /* -------------------------------------------------------------------- */
     793                 : /*      Old RIK header.                                                 */
     794                 : /* -------------------------------------------------------------------- */
     795                 : 
     796               1 :         VSIFRead( &header.iUnknown, 1, sizeof(header.iUnknown), poOpenInfo->fp );
     797               1 :         VSIFRead( &header.fSouth, 1, sizeof(header.fSouth), poOpenInfo->fp );
     798               1 :         VSIFRead( &header.fWest, 1, sizeof(header.fWest), poOpenInfo->fp );
     799               1 :         VSIFRead( &header.fNorth, 1, sizeof(header.fNorth), poOpenInfo->fp );
     800               1 :         VSIFRead( &header.fEast, 1, sizeof(header.fEast), poOpenInfo->fp );
     801               1 :         VSIFRead( &header.iScale, 1, sizeof(header.iScale), poOpenInfo->fp );
     802               1 :         VSIFRead( &header.iMPPNum, 1, sizeof(header.iMPPNum), poOpenInfo->fp );
     803                 : #ifdef CPL_MSB
     804                 :         CPL_SWAP64PTR( &header.fSouth );
     805                 :         CPL_SWAP64PTR( &header.fWest );
     806                 :         CPL_SWAP64PTR( &header.fNorth );
     807                 :         CPL_SWAP64PTR( &header.fEast );
     808                 :         CPL_SWAP32PTR( &header.iScale );
     809                 :         CPL_SWAP32PTR( &header.iMPPNum );
     810                 : #endif
     811                 : 
     812               1 :         if (!CPLIsFinite(header.fSouth) |
     813                 :             !CPLIsFinite(header.fWest) |
     814                 :             !CPLIsFinite(header.fNorth) |
     815                 :             !CPLIsFinite(header.fEast))
     816               0 :             return NULL;
     817                 : 
     818                 :         bool offsetBounds;
     819                 : 
     820               1 :         offsetBounds = header.fSouth < 4000000;
     821                 : 
     822               1 :         header.iMPPDen = 1;
     823                 : 
     824               1 :         if( offsetBounds )
     825                 :         {
     826               0 :             header.fSouth += 4002995;
     827               0 :             header.fNorth += 5004000;
     828               0 :             header.fWest += 201000;
     829               0 :             header.fEast += 302005;
     830                 : 
     831               0 :             VSIFRead( &header.iMPPDen, 1, sizeof(header.iMPPDen), poOpenInfo->fp );
     832                 : #ifdef CPL_MSB
     833                 :             CPL_SWAP32PTR( &header.iMPPDen );
     834                 : #endif
     835                 : 
     836               0 :             headerType = "RIK1";
     837                 :         }
     838                 :         else
     839                 :         {
     840               1 :             headerType = "RIK2";
     841                 :         }
     842                 : 
     843               1 :         metersPerPixel = header.iMPPNum / double(header.iMPPDen);
     844                 : 
     845               1 :         VSIFRead( &header.iBlockWidth, 1, sizeof(header.iBlockWidth), poOpenInfo->fp );
     846               1 :         VSIFRead( &header.iBlockHeight, 1, sizeof(header.iBlockHeight), poOpenInfo->fp );
     847               1 :         VSIFRead( &header.iHorBlocks, 1, sizeof(header.iHorBlocks), poOpenInfo->fp );
     848                 : #ifdef CPL_MSB
     849                 :         CPL_SWAP32PTR( &header.iBlockWidth );
     850                 :         CPL_SWAP32PTR( &header.iBlockHeight );
     851                 :         CPL_SWAP32PTR( &header.iHorBlocks );
     852                 : #endif
     853                 : 
     854               1 :         if(( header.iBlockWidth > 2000 ) || ( header.iBlockWidth < 10 ) ||
     855                 :            ( header.iBlockHeight > 2000 ) || ( header.iBlockHeight < 10 ))
     856               0 :            return NULL;
     857                 : 
     858               1 :         if( !offsetBounds )
     859                 :         {
     860               1 :             VSIFRead( &header.iVertBlocks, 1, sizeof(header.iVertBlocks), poOpenInfo->fp );
     861                 : #ifdef CPL_MSB
     862                 :             CPL_SWAP32PTR( &header.iVertBlocks );
     863                 : #endif
     864                 :         }
     865                 : 
     866               1 :         if( offsetBounds || !header.iVertBlocks )
     867                 :         {
     868                 :             header.iVertBlocks = (GUInt32)
     869                 :                 ceil( (header.fNorth - header.fSouth) /
     870               0 :                       (header.iBlockHeight * metersPerPixel) );
     871                 :         }
     872                 : 
     873                 : #if RIK_HEADER_DEBUG
     874                 :         CPLDebug( "RIK",
     875                 :                   "Original vertical blocks %d\n",
     876                 :                   header.iVertBlocks );
     877                 : #endif
     878                 : 
     879               1 :         VSIFRead( &header.iBitsPerPixel, 1, sizeof(header.iBitsPerPixel), poOpenInfo->fp );
     880                 : 
     881               1 :         if( header.iBitsPerPixel != 8 )
     882                 :         {
     883                 :             CPLError( CE_Failure, CPLE_OpenFailed,
     884                 :                       "File %s has unsupported number of bits per pixel.\n",
     885               0 :                       poOpenInfo->pszFilename );
     886               0 :             return NULL;
     887                 :         }
     888                 : 
     889               1 :         VSIFRead( &header.iOptions, 1, sizeof(header.iOptions), poOpenInfo->fp );
     890                 : 
     891               1 :         if( !header.iHorBlocks || !header.iVertBlocks )
     892               0 :            return NULL;
     893                 : 
     894               1 :         if( header.iOptions != 0x00 && // Uncompressed
     895                 :             header.iOptions != 0x40 && // Uncompressed
     896                 :             header.iOptions != 0x01 && // RLE
     897                 :             header.iOptions != 0x41 && // RLE
     898                 :             header.iOptions != 0x0B && // LZW
     899                 :             header.iOptions != 0x0D )  // ZLIB
     900                 :         {
     901                 :             CPLError( CE_Failure, CPLE_OpenFailed,
     902                 :                       "File %s. Unknown map options.\n",
     903               0 :                       poOpenInfo->pszFilename );
     904               0 :             return NULL;
     905                 :         }
     906                 :     }
     907                 : 
     908                 : /* -------------------------------------------------------------------- */
     909                 : /*      Read the palette.                                               */
     910                 : /* -------------------------------------------------------------------- */
     911                 : 
     912                 :     GByte palette[768];
     913                 : 
     914                 :     GUInt16 i;
     915             514 :     for( i = 0; i < 256; i++ )
     916                 :     {
     917             512 :         VSIFRead( &palette[i * 3 + 2], 1, 1, poOpenInfo->fp );
     918             512 :         VSIFRead( &palette[i * 3 + 1], 1, 1, poOpenInfo->fp );
     919             512 :         VSIFRead( &palette[i * 3 + 0], 1, 1, poOpenInfo->fp );
     920                 :     }
     921                 : 
     922                 : /* -------------------------------------------------------------------- */
     923                 : /*      Find block offsets.                                             */
     924                 : /* -------------------------------------------------------------------- */
     925                 : 
     926                 :     GUInt32 blocks;
     927                 :     GUInt32 *offsets;
     928                 : 
     929               2 :     blocks = header.iHorBlocks * header.iVertBlocks;
     930               2 :     offsets = (GUInt32 *)CPLMalloc( blocks * sizeof(GUInt32) );
     931                 : 
     932               2 :     if( !offsets )
     933                 :     {
     934                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     935                 :                   "File %s. Unable to allocate offset table.\n",
     936               0 :                   poOpenInfo->pszFilename );
     937               0 :         return NULL;
     938                 :     }
     939                 : 
     940               2 :     if( header.iOptions == 0x00 )
     941                 :     {
     942               0 :         offsets[0] = VSIFTell( poOpenInfo->fp );
     943                 : 
     944               0 :         for( GUInt32 i = 1; i < blocks; i++ )
     945                 :         {
     946               0 :             offsets[i] = offsets[i - 1] +
     947               0 :                 header.iBlockWidth * header.iBlockHeight;
     948                 :         }
     949                 :     }
     950                 :     else
     951                 :     {
     952             149 :         for( GUInt32 i = 0; i < blocks; i++ )
     953                 :         {
     954             147 :             VSIFRead( &offsets[i], 1, sizeof(offsets[i]), poOpenInfo->fp );
     955                 : #ifdef CPL_MSB
     956                 :             CPL_SWAP32PTR( &offsets[i] );
     957                 : #endif
     958             147 :             if( rik3header )
     959                 :             {
     960                 :                 GUInt32 blockSize;
     961             135 :                 VSIFRead( &blockSize, 1, sizeof(blockSize), poOpenInfo->fp );
     962                 : #ifdef CPL_MSB
     963                 :                 CPL_SWAP32PTR( &blockSize );
     964                 : #endif
     965                 :             }
     966                 :         }
     967                 :     }
     968                 : 
     969                 : /* -------------------------------------------------------------------- */
     970                 : /*      Final checks.                                                   */
     971                 : /* -------------------------------------------------------------------- */
     972                 : 
     973                 :     // File size
     974                 : 
     975               2 :     if( VSIFEof( poOpenInfo->fp ) )
     976                 :     {
     977                 :         CPLError( CE_Failure, CPLE_OpenFailed,
     978                 :                   "File %s. Read past end of file.\n",
     979               0 :                   poOpenInfo->pszFilename );
     980               0 :         return NULL;
     981                 :     }
     982                 : 
     983               2 :     VSIFSeek( poOpenInfo->fp, 0, SEEK_END );
     984               2 :     GUInt32 fileSize = VSIFTell( poOpenInfo->fp );
     985                 : 
     986                 : #if RIK_HEADER_DEBUG
     987                 :     CPLDebug( "RIK",
     988                 :               "File size %d\n",
     989                 :               fileSize );
     990                 : #endif
     991                 : 
     992                 :     // Make sure the offset table is valid
     993                 : 
     994               2 :     GUInt32 lastoffset = 0;
     995                 : 
     996              20 :     for( GUInt32 y = 0; y < header.iVertBlocks; y++)
     997                 :     {
     998             165 :         for( GUInt32 x = 0; x < header.iHorBlocks; x++)
     999                 :         {
    1000             147 :             if( !offsets[x + y * header.iHorBlocks] )
    1001                 :             {
    1002               0 :                 continue;
    1003                 :             }
    1004                 : 
    1005             147 :             if( offsets[x + y * header.iHorBlocks] >= fileSize )
    1006                 :             {
    1007               0 :                 if( !y )
    1008                 :                 {
    1009                 :                     CPLError( CE_Failure, CPLE_OpenFailed,
    1010                 :                               "File %s too short.\n",
    1011               0 :                               poOpenInfo->pszFilename );
    1012               0 :                     return NULL;
    1013                 :                 }
    1014               0 :                 header.iVertBlocks = y;
    1015               0 :                 break;
    1016                 :             }
    1017                 : 
    1018             147 :             if( offsets[x + y * header.iHorBlocks] < lastoffset )
    1019                 :             {
    1020               0 :                 if( !y )
    1021                 :                 {
    1022                 :                     CPLError( CE_Failure, CPLE_OpenFailed,
    1023                 :                               "File %s. Corrupt offset table.\n",
    1024               0 :                               poOpenInfo->pszFilename );
    1025               0 :                     return NULL;
    1026                 :                 }
    1027               0 :                 header.iVertBlocks = y;
    1028               0 :                 break;
    1029                 :             }
    1030                 : 
    1031             147 :             lastoffset = offsets[x + y * header.iHorBlocks];
    1032                 :         }
    1033                 :     }
    1034                 : 
    1035                 : #if RIK_HEADER_DEBUG
    1036                 :     CPLDebug( "RIK",
    1037                 :               "first offset %d\n"
    1038                 :               "last offset %d\n",
    1039                 :               offsets[0],
    1040                 :               lastoffset );
    1041                 : #endif
    1042                 : 
    1043               2 :     const char *compression = "RLE";
    1044                 : 
    1045               2 :     if( header.iOptions == 0x00 ||
    1046                 :         header.iOptions == 0x40 )
    1047               0 :         compression = "Uncompressed";
    1048               2 :     if( header.iOptions == 0x0b )
    1049               1 :         compression = "LZW";
    1050               2 :     if( header.iOptions == 0x0d )
    1051               1 :         compression = "ZLIB";
    1052                 : 
    1053                 :     CPLDebug( "RIK",
    1054                 :               "RIK file parameters:\n"
    1055                 :               " name: %s\n"
    1056                 :               " header: %s\n"
    1057                 :               " unknown: 0x%X\n"
    1058                 :               " south: %f\n"
    1059                 :               " west: %f\n"
    1060                 :               " north: %f\n"
    1061                 :               " east: %f\n"
    1062                 :               " original scale: %d\n"
    1063                 :               " meters per pixel: %f\n"
    1064                 :               " block width: %d\n"
    1065                 :               " block height: %d\n"
    1066                 :               " horizontal blocks: %d\n"
    1067                 :               " vertical blocks: %d\n"
    1068                 :               " bits per pixel: %d\n"
    1069                 :               " options: 0x%X\n"
    1070                 :               " compression: %s\n",
    1071                 :               name, headerType, header.iUnknown,
    1072                 :               header.fSouth, header.fWest, header.fNorth, header.fEast,
    1073                 :               header.iScale, metersPerPixel,
    1074                 :               header.iBlockWidth, header.iBlockHeight,
    1075                 :               header.iHorBlocks, header.iVertBlocks,
    1076               2 :               header.iBitsPerPixel, header.iOptions, compression);
    1077                 : 
    1078                 : /* -------------------------------------------------------------------- */
    1079                 : /*      Create a corresponding GDALDataset.                             */
    1080                 : /* -------------------------------------------------------------------- */
    1081                 : 
    1082                 :     RIKDataset  *poDS;
    1083                 : 
    1084               2 :     poDS = new RIKDataset();
    1085                 : 
    1086               2 :     poDS->fp = poOpenInfo->fp;
    1087               2 :     poOpenInfo->fp = NULL;
    1088                 : 
    1089               2 :     poDS->fTransform[0] = header.fWest - metersPerPixel / 2.0;
    1090               2 :     poDS->fTransform[1] = metersPerPixel;
    1091               2 :     poDS->fTransform[2] = 0.0;
    1092               2 :     poDS->fTransform[3] = header.fNorth + metersPerPixel / 2.0;
    1093               2 :     poDS->fTransform[4] = 0.0;
    1094               2 :     poDS->fTransform[5] = -metersPerPixel;
    1095                 : 
    1096               2 :     poDS->nBlockXSize = header.iBlockWidth;
    1097               2 :     poDS->nBlockYSize = header.iBlockHeight;
    1098               2 :     poDS->nHorBlocks = header.iHorBlocks;
    1099               2 :     poDS->nVertBlocks = header.iVertBlocks;
    1100               2 :     poDS->pOffsets = offsets;
    1101               2 :     poDS->options = header.iOptions;
    1102               2 :     poDS->nFileSize = fileSize;
    1103                 : 
    1104               2 :     poDS->nRasterXSize = header.iBlockWidth * header.iHorBlocks;
    1105               2 :     poDS->nRasterYSize = header.iBlockHeight * header.iVertBlocks;
    1106                 : 
    1107               2 :     poDS->nBands = 1;
    1108                 : 
    1109                 :     GDALColorEntry oEntry;
    1110               4 :     poDS->poColorTable = new GDALColorTable();
    1111             514 :     for( i = 0; i < 256; i++ )
    1112                 :     {
    1113             512 :         oEntry.c1 = palette[i * 3 + 2]; // Red
    1114             512 :         oEntry.c2 = palette[i * 3 + 1]; // Green
    1115             512 :         oEntry.c3 = palette[i * 3];     // Blue
    1116             512 :         oEntry.c4 = 255;
    1117                 : 
    1118             512 :         poDS->poColorTable->SetColorEntry( i, &oEntry );
    1119                 :     }
    1120                 : 
    1121                 : /* -------------------------------------------------------------------- */
    1122                 : /*      Create band information objects.                                */
    1123                 : /* -------------------------------------------------------------------- */
    1124                 : 
    1125               2 :     poDS->SetBand( 1, new RIKRasterBand( poDS, 1 ));
    1126                 : 
    1127                 : /* -------------------------------------------------------------------- */
    1128                 : /*      Initialize any PAM information.                                 */
    1129                 : /* -------------------------------------------------------------------- */
    1130                 : 
    1131               2 :     poDS->SetDescription( poOpenInfo->pszFilename );
    1132               2 :     poDS->TryLoadXML();
    1133                 : 
    1134                 : /* -------------------------------------------------------------------- */
    1135                 : /*      Check for external overviews.                                   */
    1136                 : /* -------------------------------------------------------------------- */
    1137               2 :     poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles );
    1138                 : 
    1139                 : /* -------------------------------------------------------------------- */
    1140                 : /*      Confirm the requested access is supported.                      */
    1141                 : /* -------------------------------------------------------------------- */
    1142               2 :     if( poOpenInfo->eAccess == GA_Update )
    1143                 :     {
    1144               0 :         delete poDS;
    1145                 :         CPLError( CE_Failure, CPLE_NotSupported, 
    1146                 :                   "The RIK driver does not support update access to existing"
    1147               0 :                   " datasets.\n" );
    1148               0 :         return NULL;
    1149                 :     }
    1150                 :     
    1151               2 :     return( poDS );
    1152                 : }
    1153                 : 
    1154                 : /************************************************************************/
    1155                 : /*                          GDALRegister_RIK()                          */
    1156                 : /************************************************************************/
    1157                 : 
    1158             558 : void GDALRegister_RIK()
    1159                 : 
    1160                 : {
    1161                 :     GDALDriver  *poDriver;
    1162                 : 
    1163             558 :     if( GDALGetDriverByName( "RIK" ) == NULL )
    1164                 :     {
    1165             537 :         poDriver = new GDALDriver();
    1166                 : 
    1167             537 :         poDriver->SetDescription( "RIK" );
    1168                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME,
    1169             537 :                                    "Swedish Grid RIK (.rik)" );
    1170                 :         poDriver->SetMetadataItem( GDAL_DMD_HELPTOPIC,
    1171             537 :                                    "frmt_various.html#RIK" );
    1172             537 :         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "rik" );
    1173                 : 
    1174             537 :         poDriver->pfnOpen = RIKDataset::Open;
    1175                 : 
    1176             537 :         GetGDALDriverManager()->RegisterDriver( poDriver );
    1177                 :     }
    1178             558 : }

Generated by: LCOV version 1.7