LCOV - code coverage report
Current view: directory - frmts/ilwis - ilwisdataset.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 976 714 73.2 %
Date: 2010-01-09 Functions: 59 49 83.1 %

       1                 : /******************************************************************************
       2                 :  *
       3                 :  * Project:  ILWIS Driver
       4                 :  * Purpose:  GDALDataset driver for ILWIS translator for read/write support.
       5                 :  * Author:   Lichun Wang, lichun@itc.nl
       6                 :  *
       7                 :  ******************************************************************************
       8                 :  * Copyright (c) 2004, ITC
       9                 :  *
      10                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      11                 :  * copy of this software and associated documentation files (the "Software"),
      12                 :  * to deal in the Software without restriction, including without limitation
      13                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      14                 :  * and/or sell copies of the Software, and to permit persons to whom the
      15                 :  * Software is furnished to do so, subject to the following conditions:
      16                 :  *
      17                 :  * The above copyright notice and this permission notice shall be included
      18                 :  * in all copies or substantial portions of the Software.
      19                 :  *
      20                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      21                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      22                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      23                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      24                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      25                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      26                 :  * DEALINGS IN THE SOFTWARE.
      27                 :  ****************************************************************************/
      28                 : 
      29                 : 
      30                 : #include "ilwisdataset.h"
      31                 : #include <float.h>
      32                 : #include <limits.h>
      33                 : 
      34                 : // IniFile.cpp: implementation of the IniFile class.
      35                 : //
      36                 : //////////////////////////////////////////////////////////////////////
      37               0 : bool CompareAsNum::operator() (const string& s1, const string& s2) const
      38                 : {
      39               0 :     long Num1 = atoi(s1.c_str());
      40               0 :     long Num2 = atoi(s2.c_str());
      41               0 :     return Num1 < Num2;
      42                 : }
      43                 : 
      44            4811 : static string TrimSpaces(const string& input)
      45                 : {
      46                 :     // find first non space
      47            4811 :     if ( input.empty()) 
      48               0 :         return string();
      49                 : 
      50            4811 :     size_t iFirstNonSpace = input.find_first_not_of(' ');
      51            4811 :     size_t iFindLastSpace = input.find_last_not_of(' ');
      52            4811 :     if (iFirstNonSpace == string::npos || iFindLastSpace == string::npos)
      53               0 :         return string();
      54                 : 
      55            4811 :     return input.substr(iFirstNonSpace, iFindLastSpace - iFirstNonSpace + 1);
      56                 : }
      57                 : 
      58           14528 : static string GetLine(FILE* fil)
      59                 : {
      60           14528 :     const char *p = CPLReadLineL( fil );
      61           14528 :     if (p == NULL)
      62              34 :         return string();
      63                 : 
      64           14494 :     CPLString osWrk = p;
      65           14494 :     osWrk.Trim();
      66           14494 :     return string(osWrk);
      67                 : }
      68                 : 
      69                 : //////////////////////////////////////////////////////////////////////
      70                 : // Construction/Destruction
      71                 : //////////////////////////////////////////////////////////////////////
      72            1195 : IniFile::IniFile(const string& filenam)
      73                 : {
      74            1195 :     filename = filenam;
      75            1195 :     Load();
      76            1195 :     bChanged = false; // Start tracking changes
      77            1195 : }
      78                 : 
      79            1195 : IniFile::~IniFile()
      80                 : {
      81            1195 :     if (bChanged)
      82                 :     {
      83             859 :         Store();
      84             859 :         bChanged = false;
      85                 :     }
      86                 : 
      87            4961 :     for (Sections::iterator iter = sections.begin(); iter != sections.end(); ++iter)
      88                 :     {
      89            3766 :         (*(*iter).second).clear();
      90            3766 :         delete (*iter).second;
      91                 :     }
      92                 : 
      93            1195 :     sections.clear();
      94            1195 : }
      95                 : 
      96            8447 : void IniFile::SetKeyValue(const string& section, const string& key, const string& value)
      97                 : {
      98            8447 :     Sections::iterator iterSect = sections.find(section);
      99            8447 :     if (iterSect == sections.end())
     100                 :     {
     101                 :         // Add a new section, with one new key/value entry
     102            3766 :         SectionEntries *entries = new SectionEntries;
     103            3766 :         (*entries)[key] = value;
     104            3766 :         sections[section] = entries;
     105                 :     }
     106                 :     else
     107                 :     {
     108                 :         // Add one new key/value entry in an existing section
     109            4681 :         SectionEntries *entries = (*iterSect).second;
     110            4681 :         (*entries)[key] = value;
     111                 :     }
     112            8447 :     bChanged = true;
     113            8447 : }
     114                 : 
     115             336 : string IniFile::GetKeyValue(const string& section, const string& key)
     116                 : {
     117             336 :   Sections::iterator iterSect = sections.find(section);
     118             336 :   if (iterSect != sections.end())
     119                 :   {
     120             323 :     SectionEntries *entries = (*iterSect).second;
     121             323 :     SectionEntries::iterator iterEntry = (*entries).find(key);
     122             323 :     if (iterEntry != (*entries).end())
     123             276 :       return (*iterEntry).second;
     124                 :   }
     125                 : 
     126              60 :   return string();
     127                 : }
     128                 : 
     129               0 : void IniFile::RemoveKeyValue(const string& section, const string& key)
     130                 : {
     131               0 :     Sections::iterator iterSect = sections.find(section);
     132               0 :     if (iterSect != sections.end())
     133                 :     {
     134                 :         // The section exists, now erase entry "key"
     135               0 :         SectionEntries *entries = (*iterSect).second;
     136               0 :         (*entries).erase(key);
     137               0 :         bChanged = true;
     138                 :     }
     139               0 : }
     140                 : 
     141               0 : void IniFile::RemoveSection(const string& section)
     142                 : {
     143               0 :     Sections::iterator iterSect = sections.find(section);
     144               0 :     if (iterSect != sections.end())
     145                 :     {
     146                 :         // The section exists, so remove it and all its entries.
     147               0 :         SectionEntries *entries = (*iterSect).second;
     148               0 :         (*entries).clear();
     149               0 :         sections.erase(iterSect);
     150               0 :         bChanged = true;
     151                 :     }
     152               0 : }
     153                 : 
     154            1195 : void IniFile::Load()
     155                 : {
     156                 :     enum ParseState { FindSection, FindKey, ReadFindKey, StoreKey, None } state;
     157            1195 :     FILE *filIni = VSIFOpenL(filename.c_str(), "r");
     158            1195 :     if (filIni == NULL)
     159              96 :         return;
     160                 : 
     161            1099 :     string section, key, value;
     162            1099 :     state = FindSection;
     163            1099 :     string s;
     164           28432 :     while (!VSIFEofL(filIni) || !s.empty() )
     165                 :     {
     166           26234 :         switch (state)
     167                 :         {
     168                 :           case FindSection:
     169           11058 :             s = GetLine(filIni);
     170           11058 :             if (s.empty())
     171            3470 :                 continue;
     172                 : 
     173            7588 :             if (s[0] == '[')
     174                 :             {
     175            3470 :                 size_t iLast = s.find_first_of(']');
     176            3470 :                 if (iLast != string::npos)
     177                 :                 {
     178            3470 :                     section = s.substr(1, iLast - 1);
     179            3470 :                     state = ReadFindKey;
     180                 :                 }
     181                 :             }
     182                 :             else
     183            4118 :                 state = FindKey;
     184            7588 :             break;
     185                 :           case ReadFindKey:
     186            3470 :             s = GetLine(filIni); // fall through (no break)
     187                 :           case FindKey:
     188                 :           {
     189            7588 :               size_t iEqu = s.find_first_of('=');
     190            7588 :               if (iEqu != string::npos)
     191                 :               {
     192            7588 :                   key = s.substr(0, iEqu);
     193            7588 :                   value = s.substr(iEqu + 1);
     194            7588 :                   state = StoreKey;
     195                 :               }
     196                 :               else
     197               0 :                   state = ReadFindKey;
     198                 :           }
     199            7588 :           break;
     200                 :           case StoreKey:
     201            7588 :             SetKeyValue(section, key, value);
     202            7588 :             state = FindSection;
     203                 :             break;
     204                 :             
     205                 :           case None:
     206                 :             // Do we need to do anything?  Perhaps this never occurs.
     207                 :             break;
     208                 :         }
     209                 :     }
     210                 : 
     211            1099 :     VSIFCloseL(filIni);
     212                 : }
     213                 : 
     214             859 : void IniFile::Store()
     215                 : {
     216             859 :     FILE *filIni = VSIFOpenL(filename.c_str(), "w+");
     217             859 :     if (filIni == NULL)
     218               0 :         return;
     219                 : 
     220             859 :     Sections::iterator iterSect;
     221            3428 :     for (iterSect = sections.begin(); iterSect != sections.end(); ++iterSect)
     222                 :     {
     223            2569 :         CPLString osLine;
     224                 : 
     225                 :         // write the section name
     226            2569 :         osLine.Printf( "[%s]\r\n", (*iterSect).first.c_str());
     227            2569 :         VSIFWriteL( osLine.c_str(), 1, strlen(osLine), filIni );
     228            2569 :         SectionEntries *entries = (*iterSect).second;
     229            2569 :         SectionEntries::iterator iterEntry;
     230            7380 :         for (iterEntry = (*entries).begin(); iterEntry != (*entries).end(); ++iterEntry)
     231                 :         {
     232            4811 :             string key = (*iterEntry).first;
     233                 :             osLine.Printf( "%s=%s\r\n", 
     234            4811 :                            TrimSpaces(key).c_str(), (*iterEntry).second.c_str());
     235            4811 :             VSIFWriteL( osLine.c_str(), 1, strlen(osLine), filIni );
     236                 :         }
     237                 : 
     238            2569 :         VSIFWriteL( "\r\n", 1, 2, filIni );
     239                 :     }
     240                 : 
     241             859 :     VSIFCloseL( filIni );
     242                 : }
     243                 : 
     244                 : // End of the implementation of IniFile class. ///////////////////////
     245                 : //////////////////////////////////////////////////////////////////////
     246                 : 
     247               0 : static long longConv(double x) {
     248               0 :     if ((x == rUNDEF) || (x > LONG_MAX) || (x < LONG_MIN))
     249               0 :         return iUNDEF;
     250                 :     else
     251               0 :         return (long)floor(x + 0.5);
     252                 : }
     253                 : 
     254             336 : string ReadElement(string section, string entry, string filename)
     255                 : {
     256             336 :     if (section.length() == 0)
     257               0 :         return string();
     258             336 :     if (entry.length() == 0)
     259               0 :         return string();
     260             336 :     if (filename.length() == 0)
     261               0 :         return string();
     262                 : 
     263             336 :     IniFile MyIniFile (filename);
     264                 : 
     265             336 :     return MyIniFile.GetKeyValue(section, entry);;
     266                 : }
     267                 : 
     268             859 : bool WriteElement(string sSection, string sEntry,
     269                 :                              string fn, string sValue)
     270                 : {
     271             859 :     if (0 == fn.length())
     272               0 :         return false;
     273                 : 
     274             859 :     IniFile MyIniFile (fn);
     275                 : 
     276             859 :     MyIniFile.SetKeyValue(sSection, sEntry, sValue);
     277             859 :     return true;
     278                 : }
     279                 : 
     280              53 : bool WriteElement(string sSection, string sEntry,
     281                 :                              string fn, int nValue)
     282                 : {
     283              53 :     if (0 == fn.length())
     284               0 :         return false;
     285                 : 
     286                 :     char strdouble[45];
     287              53 :     sprintf(strdouble, "%d", nValue);
     288              53 :     string sValue = string(strdouble);
     289             106 :     return WriteElement(sSection, sEntry, fn, sValue) != 0;
     290                 : }
     291                 : 
     292              78 : bool WriteElement(string sSection, string sEntry,
     293                 :                              string fn, double dValue)
     294                 : {
     295              78 :     if (0 == fn.length())
     296               0 :         return false;
     297                 : 
     298                 :     char strdouble[45];
     299              78 :     sprintf(strdouble, "%.6f", dValue);
     300              78 :     string sValue = string(strdouble);
     301             156 :     return WriteElement(sSection, sEntry, fn, sValue) != 0;
     302                 : }
     303                 : 
     304              10 : static CPLErr GetRowCol(string str,int &Row, int &Col)
     305                 : {
     306              10 :     string delimStr = " ,;";
     307              20 :     size_t iPos = str.find_first_of(delimStr);
     308              10 :     if (iPos != string::npos)
     309                 :     {
     310              10 :         Row = atoi(str.substr(0, iPos).c_str());
     311                 :     }
     312                 :     else 
     313                 :     {
     314                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     315               0 :                   "Read of RowCol failed.");
     316               0 :         return CE_Failure;
     317                 :     }
     318              20 :     iPos = str.find_last_of(delimStr);
     319              10 :     if (iPos != string::npos)
     320                 :     {
     321              10 :         Col = atoi(str.substr(iPos+1, str.length()-iPos).c_str());
     322                 :     }
     323              10 :     return CE_None;
     324                 : }
     325                 : 
     326                 : //! Converts ILWIS data type to GDAL data type.
     327              49 : static GDALDataType ILWIS2GDALType(ilwisStoreType stStoreType)
     328                 : {
     329              49 :   GDALDataType eDataType = GDT_Unknown;
     330                 : 
     331              49 :   switch (stStoreType){
     332                 :     case stByte: {
     333              36 :       eDataType = GDT_Byte;
     334              36 :       break;
     335                 :     } 
     336                 :     case stInt:{
     337               4 :       eDataType = GDT_Int16;
     338               4 :       break;
     339                 :     }
     340                 :     case stLong:{
     341               4 :       eDataType = GDT_Int32;
     342               4 :       break;
     343                 :     }
     344                 :     case stFloat:{
     345               3 :       eDataType = GDT_Float32;
     346               3 :       break;
     347                 :     }
     348                 :     case stReal:{
     349               2 :       eDataType = GDT_Float64;
     350                 :       break;
     351                 :     }
     352                 :     default: {
     353                 :       break;
     354                 :     }
     355                 :   }
     356                 : 
     357              49 :   return eDataType;
     358                 : }
     359                 : 
     360                 : //Determine store type of ILWIS raster
     361              52 : static string GDALType2ILWIS(GDALDataType type)
     362                 : {
     363              52 :     string sStoreType;
     364              52 :     sStoreType = "";
     365              52 :     switch( type )
     366                 :     {
     367                 :       case GDT_Byte:{
     368              33 :           sStoreType = "Byte";
     369              33 :           break;
     370                 :       }
     371                 :       case GDT_Int16:
     372                 :       case GDT_UInt16:{
     373               6 :           sStoreType = "Int";
     374               6 :           break;
     375                 :       }
     376                 :       case GDT_Int32:
     377                 :       case GDT_UInt32:{
     378               6 :           sStoreType = "Long";
     379               6 :           break;
     380                 :       }
     381                 :       case GDT_Float32:{
     382               4 :           sStoreType = "Float";
     383               4 :           break;
     384                 :       }
     385                 :       case GDT_Float64:{
     386               3 :           sStoreType = "Real";
     387               3 :           break;
     388                 :       }
     389                 :       default:{
     390                 :           CPLError( CE_Failure, CPLE_NotSupported,
     391                 :                     "Data type %s not supported by ILWIS format.\n",
     392               0 :                     GDALGetDataTypeName( type ) );
     393                 :           break;
     394                 :       } 
     395                 :     }
     396               0 :     return sStoreType;
     397                 : }
     398                 : 
     399              68 : static CPLErr GetStoreType(string pszFileName, ilwisStoreType &stStoreType)
     400                 : {
     401              68 :     string st = ReadElement("MapStore", "Type", pszFileName.c_str());
     402                 :     
     403             136 :     if( EQUAL(st.c_str(),"byte"))
     404                 :     {
     405              51 :         stStoreType = stByte;
     406                 :     }
     407              17 :     else if( EQUAL(st.c_str(),"int"))
     408                 :     {
     409               4 :         stStoreType = stInt;
     410                 :     }
     411              13 :     else if( EQUAL(st.c_str(),"long"))
     412                 :     {
     413               4 :         stStoreType = stLong;
     414                 :     }
     415               9 :     else if( EQUAL(st.c_str(),"float"))
     416                 :     {
     417               7 :         stStoreType = stFloat;
     418                 :     }
     419               2 :     else if( EQUAL(st.c_str(),"real"))
     420                 :     {
     421               2 :         stStoreType = stReal;
     422                 :     }
     423                 :     else 
     424                 :     {
     425                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     426               0 :                   "Unsupported ILWIS store type.");
     427               0 :         return CE_Failure;
     428                 :     }
     429              68 :     return CE_None;
     430                 : }
     431                 : 
     432                 : 
     433              39 : ILWISDataset::ILWISDataset()
     434                 : 
     435                 : {
     436              39 :     bGeoDirty = FALSE;
     437              39 :     bNewDataset = FALSE;
     438              39 :     pszProjection = CPLStrdup("");
     439              39 :     adfGeoTransform[0] = 0.0;
     440              39 :     adfGeoTransform[1] = 1.0;
     441              39 :     adfGeoTransform[2] = 0.0;
     442              39 :     adfGeoTransform[3] = 0.0;
     443              39 :     adfGeoTransform[4] = 0.0;
     444              39 :     adfGeoTransform[5] = 1.0;
     445              39 : }
     446                 : 
     447                 : /************************************************************************/
     448                 : /*                  ~ILWISDataset()                                     */
     449                 : /************************************************************************/
     450                 : 
     451              78 : ILWISDataset::~ILWISDataset()
     452                 : 
     453                 : {
     454              39 :     FlushCache();
     455              39 :     CPLFree( pszProjection );
     456              78 : }
     457                 : 
     458                 : /************************************************************************/
     459                 : /*                        CollectTransformCoef()                        */
     460                 : /*                                                                      */
     461                 : /*      Collect the geotransform, support for the GeoRefCorners         */
     462                 : /*      georeferencing only; We use the extent of the coordinates       */
     463                 : /*      to determine the pixelsize in X and Y direction. Then calculate */
     464                 : /*      the transform coefficients from the extent and pixelsize        */
     465                 : /************************************************************************/
     466                 : 
     467              10 : void ILWISDataset::CollectTransformCoef(string &pszRefName)
     468                 : 
     469                 : {
     470              10 :     pszRefName = "";
     471              10 :     string georef;
     472              10 :     if ( EQUAL(pszFileType.c_str(),"Map") )
     473               7 :         georef = ReadElement("Map", "GeoRef", osFileName);
     474                 :     else
     475               3 :         georef = ReadElement("MapList", "GeoRef", osFileName);
     476                 : 
     477                 :     //Capture the geotransform, only if the georef is not 'none', 
     478                 :     //otherwise, the default transform should be returned.
     479              10 :     if( (georef.length() != 0) && !EQUAL(georef.c_str(),"none"))
     480                 :     {
     481                 :         //Form the geo-referencing name
     482              10 :         string pszBaseName = string(CPLGetBasename(georef.c_str()) );
     483              20 :         string pszPath = string(CPLGetPath( osFileName ));
     484                 :         pszRefName = string(CPLFormFilename(pszPath.c_str(),
     485              20 :                                             pszBaseName.c_str(),"grf" ));
     486                 : 
     487                 :         //Check the geo-reference type,support for the GeoRefCorners only 
     488              20 :         string georeftype = ReadElement("GeoRef", "Type", pszRefName);
     489              10 :         if (EQUAL(georeftype.c_str(),"GeoRefCorners"))
     490                 :         {
     491                 :             //Center or top-left corner of the pixel approach? 
     492               5 :             string IsCorner = ReadElement("GeoRefCorners", "CornersOfCorners", pszRefName);
     493                 : 
     494                 :             //Collect the extent of the coordinates 
     495               5 :             string sMinX = ReadElement("GeoRefCorners", "MinX", pszRefName);
     496               5 :             string sMinY = ReadElement("GeoRefCorners", "MinY", pszRefName);
     497               5 :             string sMaxX = ReadElement("GeoRefCorners", "MaxX", pszRefName);
     498               5 :             string sMaxY = ReadElement("GeoRefCorners", "MaxY", pszRefName);
     499                 :         
     500                 :             //Calculate pixel size in X and Y direction from the extent
     501               5 :             double deltaX = atof(sMaxX.c_str()) - atof(sMinX.c_str());
     502               5 :             double deltaY = atof(sMaxY.c_str()) - atof(sMinY.c_str());
     503                 : 
     504               5 :             double PixelSizeX = deltaX / (double)nRasterXSize;
     505               5 :             double PixelSizeY = deltaY / (double)nRasterYSize;
     506                 :         
     507               5 :             if (EQUAL(IsCorner.c_str(),"Yes"))
     508                 :             {
     509               5 :                 adfGeoTransform[0] = atof(sMinX.c_str());
     510               5 :                 adfGeoTransform[3] = atof(sMaxY.c_str());
     511                 :             }
     512                 :             else
     513                 :             {
     514               0 :                 adfGeoTransform[0] = atof(sMinX.c_str()) - PixelSizeX/2.0;
     515               0 :                 adfGeoTransform[3] = atof(sMaxY.c_str()) + PixelSizeY/2.0;
     516                 :             }
     517                 : 
     518               5 :             adfGeoTransform[1] = PixelSizeX;
     519               5 :             adfGeoTransform[2] = 0.0;
     520               5 :             adfGeoTransform[4] = 0.0;
     521               5 :             adfGeoTransform[5] = -PixelSizeY;
     522              10 :         }
     523                 : 
     524              10 :     }
     525                 : 
     526              10 : }
     527                 : 
     528                 : /************************************************************************/
     529                 : /*                         WriteGeoReference()                          */
     530                 : /*                                                                      */
     531                 : /*      Try to write a geo-reference file for the dataset to create     */
     532                 : /************************************************************************/
     533                 : 
     534              13 : CPLErr ILWISDataset::WriteGeoReference()
     535                 : {
     536                 :     //check wheather we should write out a georeference file. 
     537                 :     //dataset must be north up 
     538              13 :     if( adfGeoTransform[0] != 0.0 || adfGeoTransform[1] != 1.0
     539               0 :         || adfGeoTransform[2] != 0.0 || adfGeoTransform[3] != 0.0
     540               0 :         || adfGeoTransform[4] != 0.0 || fabs(adfGeoTransform[5]) != 1.0 )
     541                 :     {
     542              13 :         SetGeoTransform( adfGeoTransform ); // is this needed?
     543              13 :         if (adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0)
     544                 :         {
     545              13 :             int   nXSize = GetRasterXSize();
     546              13 :             int   nYSize = GetRasterYSize();
     547              13 :             double dLLLat = (adfGeoTransform[3] 
     548              13 :                       + nYSize * adfGeoTransform[5] );
     549              13 :             double dLLLong = (adfGeoTransform[0] );
     550              13 :             double dURLat  = (adfGeoTransform[3] );
     551              13 :             double dURLong = (adfGeoTransform[0] 
     552              13 :                        + nXSize * adfGeoTransform[1] );
     553                 : 
     554              13 :             string grFileName = CPLResetExtension(osFileName, "grf" );
     555              26 :             WriteElement("Ilwis", "Type", grFileName, "GeoRef");
     556              26 :             WriteElement("GeoRef", "lines", grFileName, nYSize);
     557              13 :             WriteElement("GeoRef", "columns", grFileName, nXSize);
     558              13 :             WriteElement("GeoRef", "Type", grFileName, "GeoRefCorners");
     559              26 :             WriteElement("GeoRefCorners", "CornersOfCorners", grFileName, "Yes");
     560              26 :             WriteElement("GeoRefCorners", "MinX", grFileName, dLLLong);
     561              13 :             WriteElement("GeoRefCorners", "MinY", grFileName, dLLLat);
     562              13 :             WriteElement("GeoRefCorners", "MaxX", grFileName, dURLong);
     563              13 :             WriteElement("GeoRefCorners", "MaxY", grFileName, dURLat);
     564                 : 
     565                 :             //Re-write the GeoRef property to raster ODF
     566                 :             //Form band file name  
     567              13 :             string sBaseName = string(CPLGetBasename(osFileName) );
     568              26 :             string sPath = string(CPLGetPath(osFileName));
     569              13 :             if (nBands == 1) 
     570                 :             {
     571               9 :                 WriteElement("Map", "GeoRef", osFileName, sBaseName + ".grf");
     572                 :             }
     573                 :             else
     574                 :             {
     575              18 :                 for( int iBand = 0; iBand < nBands; iBand++ )
     576                 :                 {
     577              14 :                     if (iBand == 0)
     578               4 :                       WriteElement("MapList", "GeoRef", osFileName, sBaseName + ".grf");
     579                 :                     char pszName[100];
     580              14 :                     sprintf(pszName, "%s_band_%d", sBaseName.c_str(),iBand + 1 );
     581              14 :                     string pszODFName = string(CPLFormFilename(sPath.c_str(),pszName,"mpr"));
     582              28 :                     WriteElement("Map", "GeoRef", pszODFName, sBaseName + ".grf");
     583                 :                 }
     584              13 :             }
     585                 :         }
     586                 :     }
     587              13 :     return CE_None;
     588                 : }
     589                 : 
     590                 : /************************************************************************/
     591                 : /*                          GetProjectionRef()                          */
     592                 : /************************************************************************/
     593                 : 
     594              32 : const char *ILWISDataset::GetProjectionRef()
     595                 : 
     596                 : {
     597              32 :    return ( pszProjection );
     598                 : }
     599                 : 
     600                 : /************************************************************************/
     601                 : /*                           SetProjection()                            */
     602                 : /************************************************************************/
     603                 : 
     604              13 : CPLErr ILWISDataset::SetProjection( const char * pszNewProjection )
     605                 : 
     606                 : {
     607              13 :     CPLFree( pszProjection );
     608              13 :     pszProjection = CPLStrdup( pszNewProjection );
     609              13 :     bGeoDirty = TRUE;
     610                 : 
     611              13 :     return CE_None;
     612                 : }
     613                 : 
     614                 : /************************************************************************/
     615                 : /*                          GetGeoTransform()                           */
     616                 : /************************************************************************/
     617                 : 
     618              20 : CPLErr ILWISDataset::GetGeoTransform( double * padfTransform )
     619                 : 
     620                 : {
     621              20 :     memcpy( padfTransform,  adfGeoTransform, sizeof(double) * 6 ); 
     622              20 :     return( CE_None );
     623                 : }
     624                 : 
     625                 : /************************************************************************/
     626                 : /*                          SetGeoTransform()                           */
     627                 : /************************************************************************/
     628                 : 
     629              26 : CPLErr ILWISDataset::SetGeoTransform( double * padfTransform )
     630                 : 
     631                 : {
     632              26 :     memmove( adfGeoTransform, padfTransform, sizeof(double)*6 );
     633                 : 
     634              26 :     if (adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0)
     635              26 :         bGeoDirty = TRUE;
     636                 : 
     637              26 :     return CE_None;
     638                 : }
     639                 : 
     640              10 : bool CheckASCII(unsigned char * buf, int size)
     641                 : {
     642            2539 :   for (int i = 0; i < size; ++i)
     643            2529 :     if (!isascii(buf[i]))
     644               0 :       return false;
     645                 : 
     646              10 :   return true;
     647                 : }
     648                 : /************************************************************************/
     649                 : /*                       Open()                                         */
     650                 : /************************************************************************/
     651                 : 
     652            9538 : GDALDataset *ILWISDataset::Open( GDALOpenInfo * poOpenInfo )
     653                 : 
     654                 : {
     655                 : /* -------------------------------------------------------------------- */
     656                 : /*      Does this look like an ILWIS file                               */
     657                 : /* -------------------------------------------------------------------- */
     658            9538 :     if( poOpenInfo->nHeaderBytes < 1 )
     659            8529 :         return NULL;
     660                 : 
     661            1009 :     string sExt = CPLGetExtension( poOpenInfo->pszFilename );
     662            2018 :     if (!EQUAL(sExt.c_str(),"mpr") && !EQUAL(sExt.c_str(),"mpl"))
     663             999 :         return NULL;
     664                 : 
     665              10 :     if (!CheckASCII(poOpenInfo->pabyHeader, poOpenInfo->nHeaderBytes))
     666               0 :         return NULL;
     667                 : 
     668              10 :     string ilwistype = ReadElement("Ilwis", "Type", poOpenInfo->pszFilename);
     669              20 :     if( ilwistype.length() == 0)
     670               0 :         return NULL;
     671                 :     
     672              10 :     string sFileType; //map or map list
     673                 :     int    iBandCount;
     674              10 :     string mapsize;
     675              10 :     string maptype = ReadElement("BaseMap", "Type", poOpenInfo->pszFilename);
     676              20 :     string sBaseName = string(CPLGetBasename(poOpenInfo->pszFilename) );
     677              20 :     string sPath = string(CPLGetPath( poOpenInfo->pszFilename));
     678                 :               
     679                 :     //Verify whether it is a map list or a map
     680              20 :     if( EQUAL(ilwistype.c_str(),"MapList") )
     681                 :     {
     682               3 :         sFileType = string("MapList");
     683               6 :         string sMaps = ReadElement("MapList", "Maps", poOpenInfo->pszFilename);
     684               6 :         iBandCount = atoi(sMaps.c_str());
     685               3 :         mapsize = ReadElement("MapList", "Size", poOpenInfo->pszFilename);
     686               3 :         for (int iBand = 0; iBand < iBandCount; ++iBand )
     687                 :         {
     688                 :             //Form the band file name.
     689                 :             char cBandName[45];
     690               6 :             sprintf( cBandName, "Map%d", iBand);
     691               6 :             string sBandName = ReadElement("MapList", string(cBandName), poOpenInfo->pszFilename);
     692              12 :             string pszBandBaseName = string(CPLGetBasename(sBandName.c_str()) );
     693              12 :             string pszBandPath = string(CPLGetPath( sBandName.c_str()));
     694              12 :             if ( 0 == pszBandPath.length() )
     695                 :             { 
     696                 :                 sBandName = string(CPLFormFilename(sPath.c_str(),
     697               6 :                                                    pszBandBaseName.c_str(),"mpr" ));
     698                 :             }
     699                 :             //Verify the file exetension, it must be an ILWIS raw data file
     700                 :             //with extension .mp#, otherwise, unsupported 
     701                 :             //This drive only supports a map list which stores a set of ILWIS raster maps, 
     702               6 :             string sMapStoreName = ReadElement("MapStore", "Data", sBandName);
     703               6 :             string sExt = CPLGetExtension( sMapStoreName.c_str() );
     704              12 :             if ( !EQUALN( sExt.c_str(), "mp#", 3 ))
     705                 :             {
     706                 :                 CPLError( CE_Failure, CPLE_AppDefined,
     707                 :                           "Unsupported ILWIS data file. \n"
     708               0 :                           "can't treat as raster.\n" );
     709               0 :                 return FALSE;
     710                 :             }
     711               0 :         }
     712                 :     } 
     713               7 :     else if(EQUAL(ilwistype.c_str(),"BaseMap") && EQUAL(maptype.c_str(),"Map"))
     714                 :     {
     715               7 :         sFileType = "Map";
     716               7 :         iBandCount = 1;
     717               7 :         mapsize = ReadElement("Map", "Size", poOpenInfo->pszFilename);
     718              14 :         string sMapType = ReadElement("Map", "Type", poOpenInfo->pszFilename);
     719                 :         ilwisStoreType stStoreType;
     720              14 :         if (  
     721                 :             GetStoreType(string(poOpenInfo->pszFilename), stStoreType) != CE_None )
     722                 :         {
     723                 :             //CPLError( CE_Failure, CPLE_AppDefined,
     724                 :             //      "Unsupported ILWIS data file. \n"
     725                 :             //      "can't treat as raster.\n" );
     726               0 :             return FALSE;
     727               0 :         }
     728                 :     }
     729                 :     else
     730                 :     {
     731                 :         CPLError( CE_Failure, CPLE_AppDefined,
     732                 :                   "Unsupported ILWIS data file. \n"
     733               0 :                   "can't treat as raster.\n" );
     734               0 :         return FALSE;
     735                 :     } 
     736                 : 
     737                 : /* -------------------------------------------------------------------- */
     738                 : /*      Create a corresponding GDALDataset.                             */
     739                 : /* -------------------------------------------------------------------- */
     740                 :     ILWISDataset  *poDS;
     741              10 :     poDS = new ILWISDataset();
     742                 :     
     743                 : /* -------------------------------------------------------------------- */
     744                 : /*      Capture raster size from ILWIS file (.mpr).                     */
     745                 : /* -------------------------------------------------------------------- */
     746              10 :     int Row = 0, Col = 0;
     747              20 :     if ( GetRowCol(mapsize, Row, Col) != CE_None)
     748               0 :         return FALSE;
     749              10 :     poDS->nRasterXSize = Col;
     750              10 :     poDS->nRasterYSize = Row;
     751              10 :     poDS->osFileName = poOpenInfo->pszFilename;
     752              10 :     poDS->pszFileType = sFileType;  
     753                 : /* -------------------------------------------------------------------- */
     754                 : /*      Create band information objects.                                */
     755                 : /* -------------------------------------------------------------------- */
     756                 :     //poDS->pszFileName = new char[strlen(poOpenInfo->pszFilename) + 1];
     757              10 :     poDS->nBands = iBandCount;
     758              23 :     for( int iBand = 0; iBand < poDS->nBands; iBand++ )
     759                 :     {
     760              13 :         poDS->SetBand( iBand+1, new ILWISRasterBand( poDS, iBand+1 ) );
     761                 :     }
     762                 :     
     763                 : /* -------------------------------------------------------------------- */
     764                 : /*      Collect the geotransform coefficients                           */
     765                 : /* -------------------------------------------------------------------- */
     766              10 :     string pszGeoRef;
     767              10 :     poDS->CollectTransformCoef(pszGeoRef);
     768                 : 
     769                 : /* -------------------------------------------------------------------- */
     770                 : /*      Translation from ILWIS coordinate system definition             */
     771                 : /* -------------------------------------------------------------------- */
     772              10 :     if( (pszGeoRef.length() != 0) && !EQUAL(pszGeoRef.c_str(),"none"))
     773                 :     {
     774                 :     
     775                 :         //  Fetch coordinate system
     776              10 :         string csy = ReadElement("GeoRef", "CoordSystem", pszGeoRef);
     777              10 :         string pszProj;
     778                 : 
     779              10 :         if( (csy.length() != 0) && !EQUAL(csy.c_str(),"unknown.csy"))
     780                 :         {
     781                 : 
     782                 :             //Form the coordinate system file name
     783               5 :             if( !(EQUALN( csy.c_str(), "latlon.csy", 10 )) && 
     784                 :                 !(EQUALN( csy.c_str(), "LatlonWGS84.csy", 15 )))            
     785                 :             {
     786               5 :                 string pszBaseName = string(CPLGetBasename(csy.c_str()) );
     787              10 :                 string pszPath = string(CPLGetPath( poDS->osFileName ));
     788                 :                 csy = string(CPLFormFilename(pszPath.c_str(),
     789              10 :                                              pszBaseName.c_str(),"csy" ));
     790              10 :                 pszProj = ReadElement("CoordSystem", "Type", csy);
     791               5 :                 if (pszProj.length() == 0 ) //default to projection
     792               0 :                     pszProj = "Projection";
     793                 :             }
     794                 :             else
     795                 :             {
     796               0 :                 pszProj = "LatLon";
     797                 :             }
     798                 :           
     799               5 :             if( (EQUALN( pszProj.c_str(), "LatLon", 6 )) || 
     800                 :                 (EQUALN( pszProj.c_str(), "Projection", 10 )))      
     801               5 :                 poDS->ReadProjection( csy );
     802              10 :         }
     803                 :     }
     804                 : 
     805                 : /* -------------------------------------------------------------------- */
     806                 : /*      Initialize any PAM information.                                 */
     807                 : /* -------------------------------------------------------------------- */
     808              10 :     poDS->SetDescription( poOpenInfo->pszFilename );
     809              10 :     poDS->TryLoadXML();
     810                 : 
     811              10 :     return( poDS );
     812                 : }
     813                 : 
     814                 : /************************************************************************/
     815                 : /*                             FlushCache()                             */
     816                 : /************************************************************************/
     817                 : 
     818              53 : void ILWISDataset::FlushCache()
     819                 : 
     820                 : {
     821              53 :     GDALDataset::FlushCache();
     822                 : 
     823              53 :     if( bGeoDirty == TRUE )
     824                 :     {
     825              13 :         WriteGeoReference();
     826              13 :         WriteProjection();
     827              13 :         bGeoDirty = FALSE;
     828                 :     }
     829              53 : }
     830                 : 
     831                 : /************************************************************************/
     832                 : /*                               Create()                               */
     833                 : /*                                                                      */
     834                 : /*      Create a new ILWIS file.                                         */
     835                 : /************************************************************************/
     836                 : 
     837              37 : GDALDataset *ILWISDataset::Create(const char* pszFilename,
     838                 :                                   int nXSize, int nYSize, 
     839                 :                                   int nBands, GDALDataType eType,
     840                 :                                   char** papszParmList) 
     841                 : {
     842                 :     ILWISDataset  *poDS;
     843                 :     int     iBand;
     844                 : 
     845                 : /* -------------------------------------------------------------------- */
     846                 : /*      Verify input options.                                           */
     847                 : /* -------------------------------------------------------------------- */
     848              37 :     if( eType != GDT_Byte && eType != GDT_Int16 && eType != GDT_Int32
     849                 :         && eType != GDT_Float32 && eType != GDT_Float64 && eType != GDT_UInt16 && eType != GDT_UInt32)
     850                 :     {
     851                 :         CPLError( CE_Failure, CPLE_AppDefined,
     852                 :                   "Attempt to create ILWIS dataset with an illegal\n"
     853                 :                   "data type (%s).\n",
     854               8 :                   GDALGetDataTypeName(eType) );
     855                 : 
     856               8 :         return NULL;
     857                 :     }
     858                 : 
     859                 : /* -------------------------------------------------------------------- */
     860                 : /*      Translate the data type.                                        */
     861                 : /*  Determine store type of ILWIS raster                            */
     862                 : /* -------------------------------------------------------------------- */
     863              29 :     string sDomain= "value.dom";
     864              29 :     double stepsize = 1;
     865              29 :     string sStoreType = GDALType2ILWIS(eType);
     866              29 :     if( EQUAL(sStoreType.c_str(),""))
     867               0 :         return NULL;
     868              29 :     else if( EQUAL(sStoreType.c_str(),"Real") || EQUAL(sStoreType.c_str(),"float"))
     869               5 :         stepsize = 0;
     870                 : 
     871              29 :     string pszBaseName = string(CPLGetBasename( pszFilename ));
     872              58 :     string pszPath = string(CPLGetPath( pszFilename ));
     873                 :     
     874                 : /* -------------------------------------------------------------------- */
     875                 : /*      Write out object definition file for each band                  */
     876                 : /* -------------------------------------------------------------------- */
     877              29 :     string pszODFName;
     878              29 :     string pszDataBaseName;
     879              29 :     string pszFileName;
     880                 : 
     881                 :     char strsize[45];
     882              29 :     sprintf(strsize, "%d %d", nYSize, nXSize);
     883                 :     
     884                 :     //Form map/maplist name. 
     885              29 :     if ( nBands == 1 )
     886                 :     {
     887              17 :         pszODFName = string(CPLFormFilename(pszPath.c_str(),pszBaseName.c_str(),"mpr"));
     888              17 :         pszDataBaseName = pszBaseName;
     889              17 :         pszFileName = CPLFormFilename(pszPath.c_str(),pszBaseName.c_str(),"mpr");
     890                 :     }
     891                 :     else
     892                 :     {
     893              12 :         pszFileName = CPLFormFilename(pszPath.c_str(),pszBaseName.c_str(),"mpl");
     894              12 :         WriteElement("Ilwis", "Type", string(pszFileName), "MapList");
     895              24 :         WriteElement("MapList", "GeoRef", string(pszFileName), "none.grf");
     896              24 :         WriteElement("MapList", "Size", string(pszFileName), string(strsize));
     897              24 :         WriteElement("MapList", "Maps", string(pszFileName), nBands);
     898                 :     }
     899                 : 
     900              29 :     for( iBand = 0; iBand < nBands; iBand++ )
     901                 :     {
     902              48 :         if ( nBands > 1 )
     903                 :         {
     904                 :             char pszBandName[100];
     905              31 :             sprintf(pszBandName, "%s_band_%d", pszBaseName.c_str(),iBand + 1 );
     906              31 :             pszODFName = string(pszBandName) + ".mpr";
     907              62 :             pszDataBaseName = string(pszBandName);
     908              31 :             sprintf(pszBandName, "Map%d", iBand); 
     909              62 :             WriteElement("MapList", string(pszBandName), string(pszFileName), pszODFName);
     910              31 :             pszODFName = CPLFormFilename(pszPath.c_str(),pszDataBaseName.c_str(),"mpr");
     911                 :         }
     912                 : /* -------------------------------------------------------------------- */
     913                 : /*      Write data definition per band (.mpr)                           */
     914                 : /* -------------------------------------------------------------------- */
     915                 :         
     916              48 :         WriteElement("Ilwis", "Type", pszODFName, "BaseMap");
     917              96 :         WriteElement("BaseMap", "Type", pszODFName, "Map");
     918              96 :         WriteElement("Map", "Type", pszODFName, "MapStore");
     919                 :         
     920              96 :         WriteElement("BaseMap", "Domain", pszODFName, sDomain);
     921              48 :         string pszDataName = pszDataBaseName + ".mp#";
     922              48 :         WriteElement("MapStore", "Data", pszODFName, pszDataName);
     923              48 :         WriteElement("MapStore", "Structure", pszODFName, "Line");
     924                 :         // sStoreType is used by ILWISRasterBand constructor to determine eDataType
     925              96 :         WriteElement("MapStore", "Type", pszODFName, sStoreType);
     926                 : 
     927                 :         // For now write-out a "Range" that is as broad as possible.
     928                 :         // If later a better range is found (by inspecting metadata in the source dataset),
     929                 :         // the "Range" will be overwritten by a better version.
     930                 :         double adfMinMax[2];
     931              48 :         adfMinMax[0] = -9999999.9;
     932              48 :         adfMinMax[1] = 9999999.9;
     933                 :         char strdouble[45];
     934              48 :         sprintf(strdouble, "%.3f:%.3f:%3f:offset=0", adfMinMax[0], adfMinMax[1],stepsize);
     935              48 :         string range = string(strdouble);
     936              96 :         WriteElement("BaseMap", "Range", pszODFName, range);
     937                 : 
     938              48 :         WriteElement("Map", "GeoRef", pszODFName, "none.grf");
     939              96 :         WriteElement("Map", "Size", pszODFName, string(strsize));
     940                 :               
     941                 : /* -------------------------------------------------------------------- */
     942                 : /*      Try to create the data file.                                    */
     943                 : /* -------------------------------------------------------------------- */
     944              96 :         pszDataName = CPLResetExtension(pszODFName.c_str(), "mp#" );
     945                 : 
     946              48 :         FILE  *fp = VSIFOpenL( pszDataName.c_str(), "wb" );
     947                 : 
     948              48 :         if( fp == NULL )
     949                 :         {
     950                 :             CPLError( CE_Failure, CPLE_OpenFailed,
     951               0 :                       "Unable to create file %s.\n", pszDataName.c_str() );
     952               0 :             return NULL;
     953                 :         }
     954              48 :         VSIFCloseL( fp );
     955                 :     }
     956              29 :     poDS = new ILWISDataset();
     957              29 :     poDS->nRasterXSize = nXSize;
     958              29 :     poDS->nRasterYSize = nYSize;
     959              29 :     poDS->nBands = nBands;
     960              29 :     poDS->eAccess = GA_Update;
     961              29 :     poDS->bNewDataset = TRUE;
     962              29 :     poDS->SetDescription(pszFilename);
     963              29 :     poDS->osFileName = pszFileName;
     964              29 :     poDS->pszIlwFileName = string(pszFileName);
     965              29 :     if ( nBands == 1 )
     966              17 :         poDS->pszFileType = "Map";
     967                 :     else
     968              12 :         poDS->pszFileType = "MapList";
     969                 : 
     970                 : /* -------------------------------------------------------------------- */
     971                 : /*      Create band information objects.                                */
     972                 : /* -------------------------------------------------------------------- */
     973                 : 
     974              77 :     for( iBand = 1; iBand <= poDS->nBands; iBand++ )
     975                 :     {
     976              48 :         poDS->SetBand( iBand, new ILWISRasterBand( poDS, iBand ) );
     977                 :     }
     978                 : 
     979              29 :     return poDS;
     980                 :     //return (GDALDataset *) GDALOpen( pszFilename, GA_Update );
     981                 : }
     982                 : 
     983                 : /************************************************************************/
     984                 : /*                             CreateCopy()                             */
     985                 : /************************************************************************/
     986                 : 
     987                 : GDALDataset *
     988              18 : ILWISDataset::CreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
     989                 :                         int bStrict, char ** papszOptions,
     990                 :                         GDALProgressFunc pfnProgress, void * pProgressData )
     991                 : 
     992                 : {
     993                 :     
     994                 :     ILWISDataset  *poDS;
     995              18 :     GDALDataType eType = GDT_Byte;
     996                 :     int iBand;
     997                 :     (void) bStrict;
     998                 : 
     999                 :     
    1000              18 :     int   nXSize = poSrcDS->GetRasterXSize();
    1001              18 :     int   nYSize = poSrcDS->GetRasterYSize();
    1002              18 :     int   nBands = poSrcDS->GetRasterCount();
    1003                 : 
    1004              18 :     if( !pfnProgress( 0.0, NULL, pProgressData ) )
    1005               0 :         return NULL;
    1006                 : 
    1007                 : /* -------------------------------------------------------------------- */
    1008                 : /*      Create the basic dataset.                                       */
    1009                 : /* -------------------------------------------------------------------- */
    1010              45 :     for( iBand = 0; iBand < nBands; iBand++ )
    1011                 :     {
    1012              27 :         GDALRasterBand *poBand = poSrcDS->GetRasterBand( iBand+1 );
    1013              27 :         eType = GDALDataTypeUnion( eType, poBand->GetRasterDataType() );
    1014                 :     }
    1015                 : 
    1016                 :     poDS = (ILWISDataset *) Create( pszFilename,
    1017                 :                                     poSrcDS->GetRasterXSize(),
    1018                 :                                     poSrcDS->GetRasterYSize(),
    1019                 :                                     nBands,
    1020              18 :                                     eType, papszOptions );
    1021                 : 
    1022              18 :     if( poDS == NULL )
    1023               4 :         return NULL;
    1024              14 :     string pszBaseName = string(CPLGetBasename( pszFilename ));
    1025              28 :     string pszPath = string(CPLGetPath( pszFilename ));
    1026                 :         
    1027                 : /* -------------------------------------------------------------------- */
    1028                 : /*  Copy and geo-transform and projection information.                  */
    1029                 : /* -------------------------------------------------------------------- */
    1030                 :     double adfGeoTransform[6];
    1031              28 :     string georef = "none.grf";
    1032                 : 
    1033                 :     //check wheather we should create georeference file. 
    1034                 :     //source dataset must be north up 
    1035              47 :     if( poSrcDS->GetGeoTransform( adfGeoTransform ) == CE_None
    1036              15 :         && (adfGeoTransform[0] != 0.0 || adfGeoTransform[1] != 1.0
    1037               2 :             || adfGeoTransform[2] != 0.0 || adfGeoTransform[3] != 0.0
    1038               2 :             || adfGeoTransform[4] != 0.0 || fabs(adfGeoTransform[5]) != 1.0))
    1039                 :     {
    1040              13 :         poDS->SetGeoTransform( adfGeoTransform );
    1041              13 :         if (adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0)
    1042              13 :             georef = pszBaseName + ".grf";
    1043                 :     }
    1044                 : 
    1045              14 :     const char *pszProj = poSrcDS->GetProjectionRef();
    1046              14 :     if( pszProj != NULL && strlen(pszProj) > 0 )
    1047              13 :         poDS->SetProjection( pszProj );
    1048                 : 
    1049                 : /* -------------------------------------------------------------------- */
    1050                 : /*      Create the output raster files for each band                    */
    1051                 : /* -------------------------------------------------------------------- */
    1052                 :     
    1053              14 :     for( iBand = 0; iBand < nBands; iBand++ )
    1054                 :     {
    1055                 :         FILE *fpData;
    1056                 :         GByte *pData;
    1057                 :         
    1058              23 :         GDALRasterBand *poBand = poSrcDS->GetRasterBand( iBand+1 );
    1059              23 :         ILWISRasterBand *desBand = (ILWISRasterBand *) poDS->GetRasterBand( iBand+1 );
    1060                 :         
    1061                 : /* -------------------------------------------------------------------- */
    1062                 : /*      Translate the data type.                                        */
    1063                 : /* -------------------------------------------------------------------- */
    1064              23 :         int nLineSize =  nXSize * GDALGetDataTypeSize(eType) / 8;
    1065              23 :         pData = (GByte *) CPLMalloc( nLineSize );
    1066                 : 
    1067                 :         //Determine the nodata value
    1068                 :         int bHasNoDataValue;
    1069              23 :         double dNoDataValue = poBand->GetNoDataValue(&bHasNoDataValue); 
    1070                 :                 
    1071                 :         //Determine store type of ILWIS raster
    1072              23 :         string sStoreType = GDALType2ILWIS( eType );
    1073              23 :         double stepsize = 1;
    1074              23 :         if( EQUAL(sStoreType.c_str(),""))
    1075               0 :             return NULL;
    1076              23 :         else if( EQUAL(sStoreType.c_str(),"Real") || EQUAL(sStoreType.c_str(),"float"))
    1077               2 :             stepsize = 0;
    1078                 : 
    1079                 :         //Form the image file name, create the object definition file. 
    1080              23 :         string pszODFName;
    1081              23 :         string pszDataBaseName;
    1082              23 :         if (nBands == 1) 
    1083                 :         {
    1084               9 :             pszODFName = string(CPLFormFilename(pszPath.c_str(),pszBaseName.c_str(),"mpr"));
    1085               9 :             pszDataBaseName = pszBaseName;
    1086                 :         }
    1087                 :         else
    1088                 :         {
    1089                 :             char pszName[100];
    1090              14 :             sprintf(pszName, "%s_band_%d", pszBaseName.c_str(),iBand + 1 );
    1091              14 :             pszODFName = string(CPLFormFilename(pszPath.c_str(),pszName,"mpr"));
    1092              28 :             pszDataBaseName = string(pszName);
    1093                 :         }
    1094                 : /* -------------------------------------------------------------------- */
    1095                 : /*      Write data definition file for each band (.mpr)                 */
    1096                 : /* -------------------------------------------------------------------- */
    1097                 :         
    1098                 :         double adfMinMax[2];
    1099                 :         int    bGotMin, bGotMax;
    1100                 : 
    1101              23 :         adfMinMax[0] = poBand->GetMinimum( &bGotMin );
    1102              23 :         adfMinMax[1] = poBand->GetMaximum( &bGotMax );
    1103              23 :         if( ! (bGotMin && bGotMax) )
    1104              23 :             GDALComputeRasterMinMax((GDALRasterBandH)poBand, FALSE, adfMinMax);
    1105              23 :         if ((!CPLIsNan(adfMinMax[0])) && CPLIsFinite(adfMinMax[0]) && (!CPLIsNan(adfMinMax[1])) && CPLIsFinite(adfMinMax[1]))
    1106                 :         {
    1107                 :             // only write a range if we got a correct one from the source dataset (otherwise ILWIS can't show the map properly)
    1108                 :             char strdouble[45];
    1109              23 :             sprintf(strdouble, "%.3f:%.3f:%3f:offset=0", adfMinMax[0], adfMinMax[1],stepsize);
    1110              23 :             string range = string(strdouble);
    1111              46 :             WriteElement("BaseMap", "Range", pszODFName, range);
    1112                 :         }
    1113              23 :         WriteElement("Map", "GeoRef", pszODFName, georef);
    1114                 :         
    1115                 : /* -------------------------------------------------------------------- */
    1116                 : /*      Loop over image, copy the image data.                           */
    1117                 : /* -------------------------------------------------------------------- */
    1118              23 :         CPLErr      eErr = CE_None;
    1119                 :       
    1120                 :         //For file name for raw data, and create binary files. 
    1121              23 :         string pszDataFileName = CPLResetExtension(pszODFName.c_str(), "mp#" );
    1122                 :         
    1123              23 :         fpData = desBand->fpRaw;
    1124              23 :         if( fpData == NULL )
    1125                 :         {
    1126                 :             CPLError( CE_Failure, CPLE_OpenFailed,
    1127                 :                       "Attempt to create file `%s' failed.\n",
    1128               0 :                       pszFilename );
    1129               0 :             return NULL;
    1130                 :         }
    1131                 : 
    1132             273 :         for( int iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ )
    1133                 :         {
    1134                 :             eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
    1135                 :                                      pData, nXSize, 1, eType, 
    1136             250 :                                      0, 0 );
    1137                 : 
    1138             250 :             if( eErr == CE_None )
    1139                 :             {
    1140             250 :                 if (bHasNoDataValue)
    1141                 :                 {
    1142                 :                     // pData may have entries with value = dNoDataValue
    1143                 :                     // ILWIS uses a fixed value for nodata, depending on the data-type
    1144                 :                     // Therefore translate the NoDataValue from each band to ILWIS
    1145               0 :                     for (int iCol = 0; iCol < nXSize; iCol++ )
    1146                 :                     {
    1147               0 :                         if( EQUAL(sStoreType.c_str(),"Byte"))
    1148                 :                         {
    1149               0 :                             if ( ((GByte * )pData)[iCol] == dNoDataValue )
    1150               0 :                                 (( GByte * )pData)[iCol] = 0;
    1151                 :                         }
    1152               0 :                         else if( EQUAL(sStoreType.c_str(),"Int")) 
    1153                 :                         {
    1154               0 :                             if ( ((GInt16 * )pData)[iCol] == dNoDataValue )
    1155               0 :                                 (( GInt16 * )pData)[iCol] = shUNDEF;
    1156                 :                         }
    1157               0 :                         else if( EQUAL(sStoreType.c_str(),"Long"))  
    1158                 :                         {
    1159               0 :                             if ( ((GInt32 * )pData)[iCol] == dNoDataValue )
    1160               0 :                                 (( GInt32 * )pData)[iCol] = iUNDEF;
    1161                 :                         }
    1162               0 :                         else if( EQUAL(sStoreType.c_str(),"float")) 
    1163                 :                         {
    1164               0 :                             if ((((float * )pData)[iCol] == dNoDataValue ) || (CPLIsNan((( float * )pData)[iCol])))
    1165               0 :                                 (( float * )pData)[iCol] = flUNDEF;
    1166                 :                         }
    1167               0 :                         else if( EQUAL(sStoreType.c_str(),"Real"))  
    1168                 :                         {
    1169               0 :                             if ((((double * )pData)[iCol] == dNoDataValue ) || (CPLIsNan((( double * )pData)[iCol])))
    1170               0 :                                 (( double * )pData)[iCol] = rUNDEF;
    1171                 :                         }
    1172                 :                     }
    1173                 :                 }
    1174             250 :                 int iSize = VSIFWriteL( pData, 1, nLineSize, desBand->fpRaw );
    1175             250 :                 if ( iSize < 1 )
    1176                 :                 {
    1177               0 :                     CPLFree( pData );
    1178                 :                     //CPLFree( pData32 );
    1179                 :                     CPLError( CE_Failure, CPLE_FileIO, 
    1180               0 :                               "Write of file failed with fwrite error.");
    1181               0 :                     return NULL;
    1182                 :                 }
    1183                 :             }
    1184             250 :             if( !pfnProgress(iLine / (nYSize * nBands), NULL, pProgressData ) )
    1185               0 :                 return NULL;
    1186                 :         }
    1187              23 :         VSIFFlushL( fpData );
    1188              23 :         CPLFree( pData );
    1189                 :     }
    1190                 : 
    1191              14 :     poDS->FlushCache();
    1192                 : 
    1193              14 :     if( !pfnProgress( 1.0, NULL, pProgressData ) )
    1194                 :     {
    1195                 :         CPLError( CE_Failure, CPLE_UserInterrupt,
    1196               0 :                   "User terminated" );
    1197               0 :         delete poDS;
    1198                 : 
    1199                 :         GDALDriver *poILWISDriver =
    1200               0 :             (GDALDriver *) GDALGetDriverByName( "ILWIS" );
    1201               0 :         poILWISDriver->Delete( pszFilename );
    1202               0 :         return NULL;
    1203                 :     }
    1204                 : 
    1205              14 :     poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
    1206                 : 
    1207              14 :     return poDS;
    1208                 : }
    1209                 : 
    1210                 : /************************************************************************/
    1211                 : /*                       ILWISRasterBand()                              */
    1212                 : /************************************************************************/
    1213                 : 
    1214              61 : ILWISRasterBand::ILWISRasterBand( ILWISDataset *poDS, int nBand )
    1215                 : 
    1216                 : {
    1217              61 :     string sBandName;
    1218              61 :     if ( EQUAL(poDS->pszFileType.c_str(),"Map"))     
    1219              24 :         sBandName = string(poDS->osFileName);
    1220                 :     else //map list
    1221                 :     {
    1222                 :         //Form the band name
    1223                 :         char cBandName[45];
    1224              37 :         sprintf( cBandName, "Map%d", nBand-1);
    1225              37 :         sBandName = ReadElement("MapList", string(cBandName), string(poDS->osFileName));
    1226              37 :         string sInputPath = string(CPLGetPath( poDS->osFileName)); 
    1227              74 :         string sBandPath = string(CPLGetPath( sBandName.c_str()));
    1228              74 :         string sBandBaseName = string(CPLGetBasename( sBandName.c_str()));
    1229              74 :         if ( 0==sBandPath.length() )
    1230              37 :             sBandName = string(CPLFormFilename(sInputPath.c_str(),sBandBaseName.c_str(),"mpr" ));   
    1231                 :         else
    1232               0 :             sBandName = string(CPLFormFilename(sBandPath.c_str(),sBandBaseName.c_str(),"mpr" ));    
    1233                 :     }
    1234                 : 
    1235              61 :     if (poDS->bNewDataset)
    1236                 :     {
    1237                 :       // Called from Create():
    1238                 :       // eDataType is defaulted to GDT_Byte by GDALRasterBand::GDALRasterBand
    1239                 :       // Here we set it to match the value of sStoreType (that was set in ILWISDataset::Create)
    1240                 :       // Unfortunately we can't take advantage of the ILWIS "ValueRange" object that would use
    1241                 :       // the most compact storeType possible, without going through all values.
    1242              48 :         GetStoreType(sBandName, psInfo.stStoreType);
    1243              48 :         eDataType = ILWIS2GDALType(psInfo.stStoreType);
    1244                 :     }         
    1245                 :     else // Called from Open(), thus convert ILWIS type from ODF to eDataType
    1246              13 :         GetILWISInfo(sBandName);
    1247              61 :     this->poDS = poDS;
    1248              61 :     this->nBand = nBand;
    1249              61 :     nBlockXSize = poDS->GetRasterXSize();
    1250              61 :     nBlockYSize = 1;
    1251              61 :     switch (psInfo.stStoreType)
    1252                 :     {
    1253                 :       case stByte: 
    1254              46 :         nSizePerPixel = GDALGetDataTypeSize(GDT_Byte) / 8;
    1255              46 :         break;
    1256                 :       case stInt:
    1257               4 :         nSizePerPixel = GDALGetDataTypeSize(GDT_Int16) / 8;
    1258               4 :         break;
    1259                 :       case stLong:
    1260               4 :         nSizePerPixel = GDALGetDataTypeSize(GDT_Int32) / 8;
    1261               4 :         break;
    1262                 :       case stFloat:
    1263               5 :         nSizePerPixel = GDALGetDataTypeSize(GDT_Float32) / 8;
    1264               5 :         break;
    1265                 :       case stReal:
    1266               2 :         nSizePerPixel = GDALGetDataTypeSize(GDT_Float64) / 8;
    1267                 :         break;
    1268                 :     }
    1269              61 :     ILWISOpen(sBandName);
    1270              61 : }
    1271                 : 
    1272                 : /************************************************************************/
    1273                 : /*                          ~ILWISRasterBand()                          */
    1274                 : /************************************************************************/
    1275                 : 
    1276             122 : ILWISRasterBand::~ILWISRasterBand()
    1277                 : 
    1278                 : {
    1279              61 :     if( fpRaw != NULL )
    1280                 :     {
    1281              61 :         VSIFCloseL( fpRaw );
    1282              61 :         fpRaw = NULL;
    1283                 :     }
    1284             122 : }
    1285                 : 
    1286                 : 
    1287                 : /************************************************************************/
    1288                 : /*                             ILWISOpen()                             */
    1289                 : /************************************************************************/
    1290              61 : void ILWISRasterBand::ILWISOpen( string pszFileName )
    1291                 : {
    1292              61 :     ILWISDataset* dataset = (ILWISDataset*) poDS;
    1293              61 :     string pszDataFile;
    1294              61 :     pszDataFile = string(CPLResetExtension( pszFileName.c_str(), "mp#" ));
    1295                 : 
    1296             109 :     fpRaw = VSIFOpenL( pszDataFile.c_str(), (dataset->eAccess == GA_Update) ? "rb+" : "rb");
    1297              61 : }
    1298                 : 
    1299                 : /************************************************************************/
    1300                 : /*                 ReadValueDomainProperties()                          */
    1301                 : /************************************************************************/
    1302                 : // Helper function for GetILWISInfo, to avoid code-duplication
    1303                 : // Unfortunately with side-effect (changes members psInfo and eDataType)
    1304              12 : void ILWISRasterBand::ReadValueDomainProperties(string pszFileName)
    1305                 : {
    1306              12 :     string rangeString = ReadElement("BaseMap", "Range", pszFileName.c_str());
    1307              24 :     psInfo.vr = ValueRange(rangeString);
    1308              12 :     double rStep = psInfo.vr.get_rStep();
    1309              12 :     if ( rStep != 0 )
    1310                 :     {
    1311              10 :         psInfo.bUseValueRange = true; // use ILWIS ValueRange object to convert from "raw" to "value"
    1312              10 :         double rMin = psInfo.vr.get_rLo();
    1313              10 :         double rMax = psInfo.vr.get_rHi();
    1314              10 :         if (rStep - (long)rStep == 0.0) // Integer values
    1315                 :         {
    1316              14 :             if ( rMin >= 0 && rMax <= UCHAR_MAX)
    1317               4 :               eDataType =  GDT_Byte;
    1318               6 :             else if ( rMin >= SHRT_MIN && rMax <= SHRT_MAX)
    1319               0 :               eDataType =  GDT_Int16;
    1320               6 :             else if ( rMin >= 0 && rMax <= USHRT_MAX)
    1321               0 :               eDataType =  GDT_UInt16;
    1322              12 :             else if ( rMin >= INT_MIN && rMax <= INT_MAX)
    1323               6 :               eDataType =  GDT_Int32;
    1324               0 :             else if ( rMin >= 0 && rMax <= UINT_MAX)
    1325               0 :               eDataType =  GDT_UInt32;
    1326                 :             else
    1327               0 :               eDataType = GDT_Float64;
    1328                 :         }
    1329                 :         else // Floating point values
    1330                 :         {
    1331               0 :             if ((rMin >= -FLT_MAX) && (rMax <= FLT_MAX) && (fabs(rStep) >= FLT_EPSILON)) // is "float" good enough?
    1332               0 :               eDataType = GDT_Float32;
    1333                 :             else
    1334               0 :               eDataType = GDT_Float64;
    1335                 :         }
    1336                 :     }
    1337                 :     else
    1338                 :     {
    1339               2 :         if (psInfo.stStoreType == stFloat) // is "float" good enough?
    1340               2 :           eDataType = GDT_Float32;
    1341                 :         else
    1342               0 :           eDataType = GDT_Float64;
    1343              12 :     }
    1344              12 : }
    1345                 : 
    1346                 : /************************************************************************/
    1347                 : /*                       GetILWISInfo()                                 */
    1348                 : /************************************************************************/
    1349                 : // Calculates members psInfo and eDataType
    1350              13 : CPLErr ILWISRasterBand::GetILWISInfo(string pszFileName)
    1351                 : {
    1352                 :     // Fill the psInfo struct with defaults.
    1353                 :     // Get the store type from the ODF
    1354              13 :     if (GetStoreType(pszFileName, psInfo.stStoreType) != CE_None)
    1355                 :     {
    1356               0 :         return CE_Failure;
    1357                 :     }
    1358              13 :     psInfo.bUseValueRange = false;
    1359              13 :     psInfo.stDomain = "";
    1360                 : 
    1361                 :     // ILWIS has several (currently 22) predefined "system-domains", that influence the data-type
    1362                 :     // The user can also create his own domains. The possible types for these are "class", "identifier", "bool" and "value"
    1363                 :     // The last one has Type=DomainValue
    1364                 :     // Here we make an effort to determine the most-compact gdal-type (eDataType) that is suitable
    1365                 :     // for the data in the current ILWIS band.
    1366                 :     // First check against all predefined domain names (the "system-domains")
    1367                 :     // If no match is found, read the domain ODF from disk, and get its type
    1368                 :     // We have hardcoded the system domains here, because ILWIS may not be installed, and even if it is,
    1369                 :     // we don't know where (thus it is useless to attempt to read a system-domain-file).
    1370                 : 
    1371              13 :     string domName = ReadElement("BaseMap", "Domain", pszFileName.c_str());
    1372              26 :     string pszBaseName = string(CPLGetBasename( domName.c_str() ));
    1373              26 :     string pszPath = string(CPLGetPath( pszFileName.c_str() ));
    1374                 : 
    1375                 :     // Check against all "system-domains"
    1376              26 :     if ( EQUAL(pszBaseName.c_str(),"value") // is it a system domain with Type=DomainValue?
    1377                 :         || EQUAL(pszBaseName.c_str(),"count") 
    1378                 :         || EQUAL(pszBaseName.c_str(),"distance") 
    1379                 :         || EQUAL(pszBaseName.c_str(),"min1to1") 
    1380                 :         || EQUAL(pszBaseName.c_str(),"nilto1") 
    1381                 :         || EQUAL(pszBaseName.c_str(),"noaa") 
    1382                 :         || EQUAL(pszBaseName.c_str(),"perc") 
    1383                 :         || EQUAL(pszBaseName.c_str(),"radar") )
    1384                 :     {
    1385              12 :         ReadValueDomainProperties(pszFileName);
    1386                 :     }
    1387               1 :     else if( EQUAL(pszBaseName.c_str(),"bool") 
    1388                 :              || EQUAL(pszBaseName.c_str(),"byte") 
    1389                 :              || EQUAL(pszBaseName.c_str(),"bit") 
    1390                 :              || EQUAL(pszBaseName.c_str(),"image") 
    1391                 :              || EQUAL(pszBaseName.c_str(),"colorcmp") 
    1392                 :              || EQUAL(pszBaseName.c_str(),"flowdirection") 
    1393                 :              || EQUAL(pszBaseName.c_str(),"hortonratio") 
    1394                 :              || EQUAL(pszBaseName.c_str(),"yesno") )
    1395                 :     {
    1396               0 :         eDataType = GDT_Byte;
    1397               0 :         if( EQUAL(pszBaseName.c_str(),"image") 
    1398                 :             || EQUAL(pszBaseName.c_str(),"colorcmp"))
    1399               0 :             psInfo.stDomain = pszBaseName;
    1400                 :     }
    1401               1 :     else if( EQUAL(pszBaseName.c_str(),"color") 
    1402                 :              || EQUAL(pszBaseName.c_str(),"none" )
    1403                 :              || EQUAL(pszBaseName.c_str(),"coordbuf") 
    1404                 :              || EQUAL(pszBaseName.c_str(),"binary") 
    1405                 :              || EQUAL(pszBaseName.c_str(),"string") )
    1406                 :     {
    1407                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1408               0 :                   "Unsupported ILWIS domain type.");
    1409               0 :         return CE_Failure;    
    1410                 :     }
    1411                 :     else
    1412                 :     {
    1413                 :         // No match found. Assume it is a self-created domain. Read its type and decide the GDAL type.
    1414               1 :         string pszDomainFileName = string(CPLFormFilename(pszPath.c_str(),pszBaseName.c_str(),"dom" ));
    1415               2 :         string domType = ReadElement("Domain", "Type", pszDomainFileName.c_str());
    1416               2 :         if EQUAL(domType.c_str(),"domainvalue") // is it a self-created domain of type=DomainValue?
    1417                 :         {
    1418               0 :             ReadValueDomainProperties(pszFileName);
    1419                 :         }
    1420               1 :         else if((!EQUAL(domType.c_str(),"domainbit")) 
    1421                 :                 && (!EQUAL(domType.c_str(),"domainstring")) 
    1422                 :                 && (!EQUAL(domType.c_str(),"domaincolor"))
    1423                 :                 && (!EQUAL(domType.c_str(),"domainbinary")) 
    1424                 :                 && (!EQUAL(domType.c_str(),"domaincoordBuf")) 
    1425                 :                 && (!EQUAL(domType.c_str(),"domaincoord")))
    1426                 :         {
    1427                 :             // Type is "DomainClass", "DomainBool" or "DomainIdentifier".
    1428                 :             // For now we set the GDAL storeType be the same as the ILWIS storeType
    1429                 :             // The user will have to convert the classes manually.
    1430               1 :             eDataType = ILWIS2GDALType(psInfo.stStoreType);
    1431                 :         }
    1432                 :         else
    1433                 :         {
    1434                 :             CPLError( CE_Failure, CPLE_AppDefined, 
    1435               0 :                       "Unsupported ILWIS domain type.");
    1436               0 :             return CE_Failure;    
    1437               0 :         }
    1438                 :     }
    1439                 :     
    1440              13 :     return CE_None;
    1441                 : }
    1442                 : 
    1443                 : /** This driver defines a Block to be the entire raster; The method reads
    1444                 :     each line as a block. it reads the data into pImage.  
    1445                 : 
    1446                 :     @param nBlockXOff This must be zero for this driver
    1447                 :     @param pImage Dump the data here
    1448                 : 
    1449                 :     @return A CPLErr code. This implementation returns a CE_Failure if the
    1450                 :     block offsets are non-zero, If successful, returns CE_None. */
    1451                 : /************************************************************************/
    1452                 : /*                             IReadBlock()                             */
    1453                 : /************************************************************************/
    1454             506 : CPLErr ILWISRasterBand::IReadBlock( int nBlockXOff, int nBlockYOff,
    1455                 :                                   void * pImage )
    1456                 : {
    1457                 :     // pImage is empty; this function fills it with data from fpRaw
    1458                 :     // (ILWIS data to foreign data)
    1459                 : 
    1460                 :     // If the x block offset is non-zero, something is wrong.
    1461                 :     CPLAssert( nBlockXOff == 0 );
    1462                 :     
    1463             506 :     int nBlockSize =  nBlockXSize * nBlockYSize * nSizePerPixel;
    1464             506 :     if( fpRaw == NULL )
    1465                 :     {
    1466                 :         CPLError( CE_Failure, CPLE_OpenFailed,
    1467               0 :                   "Failed to open ILWIS data file.");  
    1468               0 :         return( CE_Failure );
    1469                 :     }
    1470                 : 
    1471                 : /* -------------------------------------------------------------------- */
    1472                 : /*  Handle the case of a strip in a writable file that doesn't          */
    1473                 : /*  exist yet, but that we want to read.  Just set to zeros and         */
    1474                 : /*  return.                                                             */
    1475                 : /* -------------------------------------------------------------------- */
    1476             506 :     ILWISDataset* poIDS = (ILWISDataset*) poDS;
    1477                 : 
    1478                 : #ifdef notdef
    1479                 :     if( poIDS->bNewDataset && (poIDS->eAccess == GA_Update))
    1480                 :     {
    1481                 :         FillWithNoData(pImage);
    1482                 :         return CE_None;
    1483                 :     }
    1484                 : #endif
    1485                 : 
    1486             506 :     VSIFSeekL( fpRaw, nBlockSize*nBlockYOff, SEEK_SET );
    1487             506 :     void *pData = (char *)CPLMalloc(nBlockSize);
    1488             506 :     if (VSIFReadL( pData, 1, nBlockSize, fpRaw ) < 1)
    1489                 :     {
    1490               0 :         if( poIDS->bNewDataset )
    1491                 :         {
    1492               0 :             FillWithNoData(pImage);
    1493               0 :             return CE_None;
    1494                 :         }
    1495                 :         else
    1496                 :         {
    1497               0 :             CPLFree( pData );
    1498                 :             CPLError( CE_Failure, CPLE_FileIO, 
    1499               0 :                       "Read of file failed with fread error.");
    1500               0 :             return CE_Failure;
    1501                 :         }
    1502                 :     }
    1503                 : 
    1504                 :     // Copy the data from pData to pImage, and convert the store-type
    1505                 :     // The data in pData has store-type = psInfo.stStoreType
    1506                 :     // The data in pImage has store-type = eDataType
    1507                 :     // They may not match, because we have chosen the most compact store-type,
    1508                 :     // and for GDAL this may be different than for ILWIS.
    1509                 : 
    1510             506 :     switch (psInfo.stStoreType)
    1511                 :     {
    1512                 :       int iCol;
    1513                 :       case stByte:
    1514           15030 :         for( iCol = 0; iCol < nBlockXSize; iCol++ )
    1515                 :         {
    1516           14725 :           double rV = psInfo.bUseValueRange ? psInfo.vr.rValue(((GByte *) pData)[iCol]) : ((GByte *) pData)[iCol];
    1517           14725 :           SetValue(pImage, iCol, rV);
    1518                 :         }
    1519             305 :         break;
    1520                 :       case stInt:
    1521               0 :         for( iCol = 0; iCol < nBlockXSize; iCol++ )
    1522                 :         {
    1523               0 :           double rV = psInfo.bUseValueRange ? psInfo.vr.rValue(((GInt16 *) pData)[iCol]) : ((GInt16 *) pData)[iCol];
    1524               0 :           SetValue(pImage, iCol, rV);
    1525                 :         }
    1526               0 :       break;
    1527                 :       case stLong:
    1528               0 :         for( iCol = 0; iCol < nBlockXSize; iCol++ )
    1529                 :         {
    1530               0 :           double rV = psInfo.bUseValueRange ? psInfo.vr.rValue(((GInt32 *) pData)[iCol]) : ((GInt32 *) pData)[iCol];
    1531               0 :           SetValue(pImage, iCol, rV);
    1532                 :         }
    1533               0 :         break;
    1534                 :       case stFloat:
    1535           40602 :         for( iCol = 0; iCol < nBlockXSize; iCol++ )
    1536           40401 :           ((float *) pImage)[iCol] = ((float *) pData)[iCol];
    1537             201 :         break;  
    1538                 :       case stReal:
    1539               0 :         for( iCol = 0; iCol < nBlockXSize; iCol++ )
    1540               0 :           ((double *) pImage)[iCol] = ((double *) pData)[iCol];
    1541                 :         break;
    1542                 :       default:
    1543                 :         CPLAssert(0);
    1544                 :     }
    1545                 : 
    1546                 :     // Officially we should also translate "nodata" values, but at this point
    1547                 :     // we can't tell what's the "nodata" value of the destination (foreign) dataset
    1548                 : 
    1549             506 :     CPLFree( pData );
    1550                 : 
    1551             506 :     return CE_None;
    1552                 : }
    1553                 : 
    1554           14725 : void ILWISRasterBand::SetValue(void *pImage, int i, double rV) {
    1555           14725 :     switch ( eDataType ) {
    1556                 :     case GDT_Byte:
    1557            7225 :       ((GByte *)pImage)[i] = (GByte) rV;
    1558            7225 :       break;
    1559                 :     case GDT_UInt16:
    1560               0 :       ((GUInt16 *) pImage)[i] = (GUInt16) rV;
    1561               0 :       break;
    1562                 :     case GDT_Int16:
    1563               0 :       ((GInt16 *) pImage)[i] = (GInt16) rV;
    1564               0 :       break;
    1565                 :     case GDT_UInt32:
    1566               0 :       ((GUInt32 *) pImage)[i] = (GUInt32) rV;
    1567               0 :       break;
    1568                 :     case GDT_Int32:
    1569            7500 :       ((GInt32 *) pImage)[i] = (GInt32) rV;
    1570            7500 :       break;
    1571                 :     case GDT_Float32:
    1572               0 :       ((float *) pImage)[i] = (float) rV;
    1573               0 :       break;
    1574                 :     case GDT_Float64:
    1575               0 :       ((double *) pImage)[i] = rV;
    1576                 :       break;
    1577                 :     default:
    1578                 :       CPLAssert(0);
    1579                 :     }
    1580           14725 : }
    1581                 : 
    1582            7500 : double ILWISRasterBand::GetValue(void *pImage, int i) {
    1583            7500 :   double rV = 0; // Does GDAL have an official nodata value?
    1584            7500 :     switch ( eDataType ) {
    1585                 :     case GDT_Byte:
    1586            7500 :       rV = ((GByte *)pImage)[i];
    1587            7500 :       break;
    1588                 :     case GDT_UInt16:
    1589               0 :       rV = ((GUInt16 *) pImage)[i];
    1590               0 :       break;
    1591                 :     case GDT_Int16:
    1592               0 :       rV = ((GInt16 *) pImage)[i];
    1593               0 :       break;
    1594                 :     case GDT_UInt32:
    1595               0 :       rV = ((GUInt32 *) pImage)[i];
    1596               0 :       break;
    1597                 :     case GDT_Int32:
    1598               0 :       rV = ((GInt32 *) pImage)[i];
    1599               0 :       break;
    1600                 :     case GDT_Float32:
    1601               0 :       rV = ((float *) pImage)[i];
    1602               0 :       break;
    1603                 :     case GDT_Float64:
    1604               0 :       rV = ((double *) pImage)[i];
    1605                 :       break;
    1606                 :     default:
    1607                 :       CPLAssert(0);
    1608                 :     }
    1609            7500 :     return rV;
    1610                 : }
    1611                 : 
    1612               0 : void ILWISRasterBand::FillWithNoData(void * pImage)
    1613                 : {
    1614               0 :     if (psInfo.stStoreType == stByte)
    1615               0 :         memset(pImage, 0, nBlockXSize * nBlockYSize);
    1616                 :     else
    1617                 :     {
    1618               0 :         switch (psInfo.stStoreType)
    1619                 :         {
    1620                 :           case stInt:
    1621               0 :             ((GInt16*)pImage)[0] = shUNDEF;
    1622               0 :             break;
    1623                 :           case stLong:
    1624               0 :             ((GInt32*)pImage)[0] = iUNDEF;
    1625               0 :             break;
    1626                 :           case stFloat:
    1627               0 :             ((float*)pImage)[0] = flUNDEF;
    1628               0 :             break;
    1629                 :           case stReal:
    1630               0 :             ((double*)pImage)[0] = rUNDEF;
    1631                 :             break;
    1632                 :           default: // should there be handling for stByte? 
    1633                 :             break;
    1634                 :         }
    1635               0 :         int iItemSize = GDALGetDataTypeSize(eDataType) / 8;
    1636               0 :         for (int i = 1; i < nBlockXSize * nBlockYSize; ++i)
    1637               0 :             memcpy( ((char*)pImage) + iItemSize * i, (char*)pImage + iItemSize * (i - 1), iItemSize);
    1638                 :     }
    1639               0 : }
    1640                 : 
    1641                 : /************************************************************************/
    1642                 : /*                            IWriteBlock()                             */
    1643                 : /*                                                                      */
    1644                 : /************************************************************************/
    1645                 : 
    1646             351 : CPLErr ILWISRasterBand::IWriteBlock(int nBlockXOff, int nBlockYOff,
    1647                 :            void* pImage)
    1648                 : {
    1649                 :     // pImage has data; this function reads this data and stores it to fpRaw
    1650                 :     // (foreign data to ILWIS data)
    1651                 : 
    1652                 :     // Note that this function will not overwrite existing data in fpRaw, but
    1653                 :     // it will "fill gaps" marked by "nodata" values
    1654                 : 
    1655             351 :     ILWISDataset* dataset = (ILWISDataset*) poDS;
    1656                 : 
    1657                 :     CPLAssert( dataset != NULL
    1658                 :                && nBlockXOff == 0
    1659                 :                && nBlockYOff >= 0
    1660                 :                && pImage != NULL );
    1661                 : 
    1662             351 :     int nXSize = dataset->GetRasterXSize();
    1663             351 :     int nBlockSize = nBlockXSize * nBlockYSize * nSizePerPixel;
    1664             351 :     void *pData = CPLMalloc(nBlockSize);
    1665                 :     
    1666             351 :     VSIFSeekL( fpRaw, nBlockSize * nBlockYOff, SEEK_SET );
    1667                 : 
    1668             351 :     bool fDataExists = (VSIFReadL( pData, 1, nBlockSize, fpRaw ) >= 1);
    1669                 : 
    1670                 :     // Copy the data from pImage to pData, and convert the store-type
    1671                 :     // The data in pData has store-type = psInfo.stStoreType
    1672                 :     // The data in pImage has store-type = eDataType
    1673                 :     // They may not match, because we have chosen the most compact store-type,
    1674                 :     // and for GDAL this may be different than for ILWIS.
    1675                 : 
    1676             351 :     if( fDataExists )
    1677                 :     {
    1678                 :         // fpRaw (thus pData) already has data
    1679                 :         // Take care to not overwrite it
    1680                 :         // thus only fill in gaps (nodata values)
    1681               0 :         switch (psInfo.stStoreType)
    1682                 :         {
    1683                 :           int iCol;
    1684                 :           case stByte:
    1685               0 :             for (iCol = 0; iCol < nXSize; iCol++ )
    1686               0 :                 if ((( GByte * )pData)[iCol] == 0)
    1687                 :                 {
    1688               0 :                     double rV = GetValue(pImage, iCol);
    1689               0 :                     (( GByte * )pData)[iCol] = (GByte) 
    1690               0 :                         (psInfo.bUseValueRange ? psInfo.vr.iRaw(rV) : rV);
    1691                 :                 }
    1692               0 :             break;
    1693                 :           case stInt:
    1694               0 :             for (iCol = 0; iCol < nXSize; iCol++ )
    1695               0 :                 if ((( GInt16 * )pData)[iCol] == shUNDEF)
    1696                 :                 {
    1697               0 :                     double rV = GetValue(pImage, iCol);
    1698               0 :                     (( GInt16 * )pData)[iCol] = (GInt16) 
    1699               0 :                         (psInfo.bUseValueRange ? psInfo.vr.iRaw(rV) : rV);
    1700                 :                 }
    1701               0 :             break;
    1702                 :           case stLong:
    1703               0 :             for (iCol = 0; iCol < nXSize; iCol++ )
    1704               0 :                 if ((( GInt32 * )pData)[iCol] == iUNDEF)
    1705                 :                 {
    1706               0 :                     double rV = GetValue(pImage, iCol);
    1707               0 :                     (( GInt32 * )pData)[iCol] = (GInt32) 
    1708               0 :                         (psInfo.bUseValueRange ? psInfo.vr.iRaw(rV) : rV);
    1709                 :                 }
    1710               0 :             break;
    1711                 :           case stFloat:
    1712               0 :             for (iCol = 0; iCol < nXSize; iCol++ )
    1713               0 :                 if ((( float * )pData)[iCol] == flUNDEF)
    1714               0 :                     (( float * )pData)[iCol] = ((float* )pImage)[iCol];
    1715               0 :             break;
    1716                 :           case stReal:
    1717               0 :             for (iCol = 0; iCol < nXSize; iCol++ )
    1718               0 :                 if ((( double * )pData)[iCol] == rUNDEF)
    1719               0 :                     (( double * )pData)[iCol] = ((double* )pImage)[iCol];
    1720                 :             break;
    1721                 :         }
    1722                 :     }
    1723                 :     else
    1724                 :     {
    1725                 :         // fpRaw (thus pData) is still empty, just write the data
    1726             351 :         switch (psInfo.stStoreType)
    1727                 :         {
    1728                 :           int iCol;
    1729                 :           case stByte:
    1730            7650 :             for (iCol = 0; iCol < nXSize; iCol++ )
    1731                 :             {
    1732            7500 :                 double rV = GetValue(pImage, iCol);
    1733            7500 :                 (( GByte * )pData)[iCol] = (GByte) 
    1734            7500 :                     (psInfo.bUseValueRange ? psInfo.vr.iRaw(rV) : rV);
    1735                 :             }
    1736             150 :             break;
    1737                 :           case stInt:
    1738               0 :             for (iCol = 0; iCol < nXSize; iCol++ )
    1739                 :             {
    1740               0 :                 double rV = GetValue(pImage, iCol);
    1741               0 :                 (( GInt16 * )pData)[iCol] = (GInt16) 
    1742               0 :                     (psInfo.bUseValueRange ? psInfo.vr.iRaw(rV) : rV);
    1743                 :             }
    1744               0 :             break;
    1745                 :           case stLong:
    1746               0 :             for (iCol = 0; iCol < nXSize; iCol++ )
    1747                 :             {
    1748               0 :                 double rV = GetValue(pImage, iCol);
    1749               0 :                 ((GInt32 *)pData)[iCol] = (GInt32)
    1750               0 :                     (psInfo.bUseValueRange ? psInfo.vr.iRaw(rV) : rV);
    1751                 :             }
    1752               0 :             break;
    1753                 :           case stFloat:
    1754           40602 :             for (iCol = 0; iCol < nXSize; iCol++ )
    1755           40401 :                 (( float * )pData)[iCol] = ((float* )pImage)[iCol];
    1756             201 :             break;
    1757                 :           case stReal:
    1758               0 :             for (iCol = 0; iCol < nXSize; iCol++ )
    1759               0 :                 (( double * )pData)[iCol] = ((double* )pImage)[iCol];
    1760                 :             break;
    1761                 :         }
    1762                 :     }
    1763                 : 
    1764                 :     // Officially we should also translate "nodata" values, but at this point
    1765                 :     // we can't tell what's the "nodata" value of the source (foreign) dataset
    1766                 : 
    1767             351 :     VSIFSeekL( fpRaw, nBlockSize * nBlockYOff, SEEK_SET );
    1768                 : 
    1769             351 :     if (VSIFWriteL( pData, 1, nBlockSize, fpRaw ) < 1)
    1770                 :     {
    1771               0 :         CPLFree( pData );
    1772                 :         CPLError( CE_Failure, CPLE_FileIO, 
    1773               0 :                   "Write of file failed with fwrite error.");
    1774               0 :         return CE_Failure;
    1775                 :     }
    1776                 : 
    1777             351 :     CPLFree( pData );
    1778             351 :     return CE_None;
    1779                 : }
    1780                 : 
    1781                 : /************************************************************************/
    1782                 : /*                           GetNoDataValue()                           */
    1783                 : /************************************************************************/
    1784              12 : double ILWISRasterBand::GetNoDataValue( int *pbSuccess )
    1785                 : 
    1786                 : {
    1787              12 :     if( pbSuccess != NULL )
    1788              12 :         *pbSuccess = TRUE;
    1789                 : 
    1790              12 :     if( eDataType == GDT_Float64 )
    1791               0 :         return rUNDEF;
    1792              12 :     else if( eDataType == GDT_Int32)
    1793               3 :         return iUNDEF;
    1794               9 :     else if( eDataType == GDT_Int16)
    1795               0 :         return shUNDEF;
    1796               9 :     else if( eDataType == GDT_Float32)
    1797               2 :         return flUNDEF;
    1798               7 :     else if( EQUAL(psInfo.stDomain.c_str(),"image") 
    1799                 :              || EQUAL(psInfo.stDomain.c_str(),"colorcmp")) 
    1800                 :     {
    1801               0 :         *pbSuccess = false;
    1802               0 :         return 0;
    1803                 :     }
    1804                 :     else
    1805               7 :         return 0;
    1806                 : }
    1807                 : 
    1808                 : /************************************************************************/
    1809                 : /*                      ValueRange()                                    */
    1810                 : /************************************************************************/
    1811               0 : double Max(double a, double b) 
    1812               0 : { return (a>=b && a!=rUNDEF) ? a : b; }
    1813                 : 
    1814              24 : static double doubleConv(const char* s)
    1815                 : {
    1816              24 :     if (s == 0) return rUNDEF;
    1817                 :     char *endptr;
    1818              24 :     char *begin = const_cast<char*>(s);
    1819                 : 
    1820                 :     // skip leading spaces; strtol will return 0 on a string with only spaces
    1821                 :     // which is not what we want
    1822              24 :     while (isspace((unsigned char)*begin)) ++begin;
    1823                 : 
    1824              24 :     if (strlen(begin) == 0) return rUNDEF;
    1825              24 :     errno = 0;
    1826              24 :     double r = strtod(begin, &endptr);
    1827              24 :     if ((0 == *endptr) && (errno==0))
    1828              24 :         return r;
    1829               0 :     while (*endptr != 0) { // check trailing spaces
    1830               0 :         if (*endptr != ' ')
    1831               0 :             return rUNDEF;
    1832               0 :         endptr++;
    1833                 :     }
    1834               0 :     return r;
    1835                 : }
    1836                 : 
    1837              12 : ValueRange::ValueRange(string sRng)
    1838                 : {
    1839              12 :     char* sRange = new char[sRng.length() + 1];
    1840             476 :     for (unsigned int i = 0; i < sRng.length(); ++i)
    1841             464 :         sRange[i] = sRng[i];
    1842              12 :     sRange[sRng.length()] = 0;
    1843                 :   
    1844              12 :     char *p1 = strchr(sRange, ':');
    1845              12 :     if (0 == p1)
    1846               0 :         return;
    1847                 : 
    1848              12 :     char *p3 = strstr(sRange, ",offset=");
    1849              12 :     if (0 == p3)
    1850              12 :         p3 = strstr(sRange, ":offset=");
    1851              12 :     _r0 = rUNDEF;
    1852              12 :     if (0 != p3) {
    1853              12 :         _r0 = doubleConv(p3+8);
    1854              12 :         *p3 = 0;
    1855                 :     }
    1856              12 :     char *p2 = strrchr(sRange, ':');
    1857              12 :     _rStep = 1;
    1858              12 :     if (p1 != p2) { // step
    1859              12 :         _rStep = doubleConv(p2+1);
    1860              12 :         *p2 = 0;
    1861                 :     }
    1862                 : 
    1863              12 :     p2 = strchr(sRange, ':');
    1864              12 :     if (p2 != 0) {
    1865              12 :         *p2 = 0;
    1866              12 :         _rLo = atof(sRange);
    1867              12 :         _rHi = atof(p2+1);
    1868                 :     }
    1869                 :     else {
    1870               0 :         _rLo = atof(sRange);
    1871               0 :         _rHi = _rLo;
    1872                 :     }  
    1873              12 :     init(_r0);
    1874                 :    
    1875              12 :     delete [] sRange;
    1876                 : }
    1877                 : 
    1878              61 : ValueRange::ValueRange(double min, double max)  // step = 1
    1879                 : {
    1880              61 :     _rLo = min;
    1881              61 :     _rHi = max;
    1882              61 :     _rStep = 1;
    1883              61 :     init();
    1884              61 : }
    1885                 : 
    1886               0 : ValueRange::ValueRange(double min, double max, double step) 
    1887                 : {
    1888               0 :     _rLo = min;
    1889               0 :     _rHi = max;
    1890               0 :     _rStep = step;
    1891               0 :     init();
    1892               0 : }
    1893                 : 
    1894              71 : static ilwisStoreType stNeeded(unsigned long iNr)
    1895                 : {
    1896              71 :     if (iNr <= 256)
    1897              65 :         return stByte;
    1898               6 :     if (iNr <= SHRT_MAX)
    1899               0 :         return stInt;
    1900               6 :     return stLong;
    1901                 : }
    1902                 : 
    1903              61 : void ValueRange::init()
    1904                 : {
    1905              61 :     init(rUNDEF);
    1906              61 : }
    1907                 : 
    1908              73 : void ValueRange::init(double rRaw0)
    1909                 : {
    1910                 :     try {
    1911              73 :         _iDec = 0;
    1912              73 :         if (_rStep < 0)
    1913               0 :             _rStep = 0;
    1914              73 :         double r = _rStep;
    1915              73 :         if (r <= 1e-20)
    1916               2 :             _iDec = 3;
    1917             142 :         else while (r - floor(r) > 1e-20) {
    1918               0 :             r *= 10;
    1919               0 :             _iDec++;
    1920               0 :             if (_iDec > 10)
    1921               0 :                 break;
    1922                 :         }
    1923                 : 
    1924              73 :         short iBeforeDec = 1;
    1925              73 :         double rMax = MAX(fabs(get_rLo()), fabs(get_rHi()));
    1926              73 :         if (rMax != 0)
    1927              12 :             iBeforeDec = (short)floor(log10(rMax)) + 1;
    1928              73 :         if (get_rLo() < 0)
    1929               8 :             iBeforeDec++;
    1930              73 :         _iWidth = iBeforeDec + _iDec;
    1931              73 :         if (_iDec > 0)
    1932               2 :             _iWidth++;
    1933              73 :         if (_iWidth > 12)
    1934               0 :             _iWidth = 12;
    1935              73 :         if (_rStep < 1e-06)
    1936                 :         {
    1937               2 :             st = stReal;
    1938               2 :             _rStep = 0;
    1939                 :         }     
    1940                 :         else {
    1941              71 :             r = get_rHi() - get_rLo();
    1942              71 :             if (r <= ULONG_MAX) {
    1943              71 :                 r /= _rStep;
    1944              71 :                 r += 1;
    1945                 :             }
    1946              71 :             r += 1; 
    1947              71 :             if (r > LONG_MAX)
    1948               0 :                 st = stReal;
    1949                 :             else {
    1950              71 :                 st = stNeeded((unsigned long)floor(r+0.5));
    1951              71 :                 if (st < stByte)
    1952               0 :                     st = stByte;
    1953                 :             }
    1954                 :         }
    1955              73 :         if (rUNDEF != rRaw0)
    1956              12 :             _r0 = rRaw0;
    1957                 :         else {
    1958              61 :             _r0 = 0;
    1959              61 :             if (st <= stByte)
    1960              61 :                 _r0 = -1;
    1961                 :         }
    1962              73 :         if (st > stInt)
    1963               8 :             iRawUndef = iUNDEF;
    1964              65 :         else if (st == stInt)
    1965               0 :             iRawUndef = shUNDEF;
    1966                 :         else
    1967              65 :             iRawUndef = 0;
    1968                 :     }
    1969               0 :     catch (std::exception*) {
    1970               0 :         st = stReal;
    1971               0 :         _r0 = 0;
    1972               0 :         _rStep = 0.0001;
    1973               0 :         _rHi = 1e300;
    1974               0 :         _rLo = -1e300;
    1975               0 :         iRawUndef = iUNDEF;
    1976                 :     }
    1977              73 : }
    1978                 : 
    1979               0 : string ValueRange::ToString()
    1980                 : {
    1981                 :     char buffer[200];
    1982               0 :     if (fabs(get_rLo()) > 1.0e20 || fabs(get_rHi()) > 1.0e20)
    1983               0 :         sprintf(buffer, "%g:%g:%f:offset=%g", get_rLo(), get_rHi(), get_rStep(), get_rRaw0());
    1984               0 :     else if (get_iDec() >= 0)
    1985               0 :         sprintf(buffer, "%.*f:%.*f:%.*f:offset=%.0f", get_iDec(), get_rLo(), get_iDec(), get_rHi(), get_iDec(), get_rStep(), get_rRaw0());
    1986                 :     else
    1987               0 :         sprintf(buffer, "%f:%f:%f:offset=%.0f", get_rLo(), get_rHi(), get_rStep(), get_rRaw0());
    1988               0 :     return string(buffer);
    1989                 : }
    1990                 : 
    1991            8300 : double ValueRange::rValue(int iRaw)
    1992                 : {
    1993            8300 :     if (iRaw == iUNDEF || iRaw == iRawUndef)
    1994               0 :         return rUNDEF;
    1995            8300 :     double rVal = iRaw + _r0;
    1996            8300 :     rVal *= _rStep;
    1997            8300 :     if (get_rLo() == get_rHi())
    1998               0 :         return rVal;
    1999            8300 :     double rEpsilon = _rStep == 0.0 ? 1e-6 : _rStep / 3.0; // avoid any rounding problems with an epsilon directly based on the
    2000                 :     // the stepsize
    2001            8300 :     if ((rVal - get_rLo() < -rEpsilon) || (rVal - get_rHi() > rEpsilon))
    2002               0 :         return rUNDEF;
    2003            8300 :     return rVal;
    2004                 : }
    2005                 : 
    2006               0 : int ValueRange::iRaw(double rValue)
    2007                 : {
    2008               0 :     if (rValue == rUNDEF) // || !fContains(rValue))
    2009               0 :         return iUNDEF;
    2010               0 :     double rEpsilon = _rStep == 0.0 ? 1e-6 : _rStep / 3.0;  
    2011               0 :     if (rValue - get_rLo() < -rEpsilon) // take a little rounding tolerance
    2012               0 :         return iUNDEF;
    2013               0 :     else if (rValue - get_rHi() > rEpsilon) // take a little rounding tolerance
    2014               0 :         return iUNDEF;
    2015               0 :     rValue /= _rStep;
    2016               0 :     double rVal = floor(rValue+0.5);
    2017               0 :     rVal -= _r0;
    2018                 :     long iVal;
    2019               0 :     iVal = longConv(rVal);
    2020               0 :     return iVal;
    2021                 : }
    2022                 : 
    2023                 : 
    2024                 : /************************************************************************/
    2025                 : /*                    GDALRegister_ILWIS()                              */
    2026                 : /************************************************************************/
    2027                 : 
    2028             338 : void GDALRegister_ILWIS()
    2029                 : 
    2030                 : {
    2031                 :     GDALDriver  *poDriver;
    2032                 : 
    2033             338 :     if( GDALGetDriverByName( "ILWIS" ) == NULL )
    2034                 :     {
    2035             336 :         poDriver = new GDALDriver();
    2036                 :         
    2037             336 :         poDriver->SetDescription( "ILWIS" );
    2038                 :         poDriver->SetMetadataItem( GDAL_DMD_LONGNAME, 
    2039             336 :                                    "ILWIS Raster Map" );
    2040             336 :         poDriver->SetMetadataItem( GDAL_DMD_EXTENSION, "mpr/mpl" );
    2041                 :         poDriver->SetMetadataItem( GDAL_DMD_CREATIONDATATYPES, 
    2042             336 :                                    "Byte Int16 Int32 Float64" );
    2043             336 :         poDriver->SetMetadataItem( GDAL_DCAP_VIRTUALIO, "YES" );
    2044                 : 
    2045             336 :         poDriver->pfnOpen = ILWISDataset::Open;
    2046             336 :         poDriver->pfnCreate = ILWISDataset::Create;
    2047             336 :         poDriver->pfnCreateCopy = ILWISDataset::CreateCopy;
    2048                 : 
    2049             336 :         GetGDALDriverManager()->RegisterDriver( poDriver );
    2050                 :     }
    2051             338 : }

Generated by: LCOV version 1.7