LTP GCOV extension - code coverage report
Current view: directory - apps - gdaldem.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 983
Code covered: 71.9 % Executed lines: 707

       1                 : /******************************************************************************
       2                 :  * $Id: gdaldem.cpp 19812 2010-06-06 22:37:13Z rouault $
       3                 :  *
       4                 :  * Project:  GDAL DEM Utilities
       5                 :  * Purpose:  
       6                 :  * Authors:  Matthew Perry, perrygeo at gmail.com
       7                 :  *           Even Rouault, even dot rouault at mines dash paris dot org
       8                 :  *           Howard Butler, hobu.inc at gmail.com
       9                 :  *           Chris Yesson, chris dot yesson at ioz dot ac dot uk
      10                 :  *
      11                 :  ******************************************************************************
      12                 :  * Copyright (c) 2006, 2009 Matthew Perry 
      13                 :  * Copyright (c) 2009 Even Rouault
      14                 :  * Portions derived from GRASS 4.1 (public domain) See 
      15                 :  * http://trac.osgeo.org/gdal/ticket/2975 for more information regarding 
      16                 :  * history of this code
      17                 :  *
      18                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      19                 :  * copy of this software and associated documentation files (the "Software"),
      20                 :  * to deal in the Software without restriction, including without limitation
      21                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      22                 :  * and/or sell copies of the Software, and to permit persons to whom the
      23                 :  * Software is furnished to do so, subject to the following conditions:
      24                 :  *
      25                 :  * The above copyright notice and this permission notice shall be included
      26                 :  * in all copies or substantial portions of the Software.
      27                 :  *
      28                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      29                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      30                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      31                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      32                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      33                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      34                 :  * DEALINGS IN THE SOFTWARE.
      35                 :  ****************************************************************************
      36                 :  *
      37                 :  * Slope and aspect calculations based on original method for GRASS GIS 4.1
      38                 :  * by Michael Shapiro, U.S.Army Construction Engineering Research Laboratory
      39                 :  *    Olga Waupotitsch, U.S.Army Construction Engineering Research Laboratory
      40                 :  *    Marjorie Larson, U.S.Army Construction Engineering Research Laboratory
      41                 :  * as found in GRASS's r.slope.aspect module.
      42                 :  *
      43                 :  * Horn's formula is used to find the first order derivatives in x and y directions
      44                 :  * for slope and aspect calculations: Horn, B. K. P. (1981).
      45                 :  * "Hill Shading and the Reflectance Map", Proceedings of the IEEE, 69(1):14-47. 
      46                 :  *
      47                 :  * Other reference :
      48                 :  * Burrough, P.A. and McDonell, R.A., 1998. Principles of Geographical Information
      49                 :  * Systems. p. 190.
      50                 :  *
      51                 :  * Shaded relief based on original method for GRASS GIS 4.1 by Jim Westervelt,
      52                 :  * U.S. Army Construction Engineering Research Laboratory
      53                 :  * as found in GRASS's r.shaded.relief (formerly shade.rel.sh) module.
      54                 :  * ref: "r.mapcalc: An Algebra for GIS and Image Processing",
      55                 :  * by Michael Shapiro and Jim Westervelt, U.S. Army Construction Engineering
      56                 :  * Research Laboratory (March/1991)
      57                 :  *
      58                 :  * Color table of named colors and lookup code derived from src/libes/gis/named_colr.c
      59                 :  * of GRASS 4.1
      60                 :  *
      61                 :  * TRI - Terrain Ruggedness Index is as descibed in Wilson et al (2007)
      62                 :  * this is based on the method of Valentine et al. (2004)  
      63                 :  * 
      64                 :  * TPI - Topographic Position Index follows the description in Wilson et al (2007), following Weiss (2001)
      65                 :  * The radius is fixed at 1 cell width/height
      66                 :  * 
      67                 :  * Roughness - follows the definition in Wilson et al. (2007), which follows Dartnell (2000)
      68                 :  *
      69                 :  * References for TRI/TPI/Roughness:
      70                 :  * Dartnell, P. 2000. Applying Remote Sensing Techniques to map Seafloor 
      71                 :  *  Geology/Habitat Relationships. Masters Thesis, San Francisco State 
      72                 :  *  University, pp. 108.
      73                 :  * Valentine, P. C., S. J. Fuller, L. A. Scully. 2004. Terrain Ruggedness 
      74                 :  *  Analysis and Distribution of Boulder Ridges in the Stellwagen Bank National
      75                 :  *  Marine Sanctuary Region (poster). Galway, Ireland: 5th International 
      76                 :  *  Symposium on Marine Geological and Biological Habitat Mapping (GeoHAB), 
      77                 :  *  May 2004.
      78                 :  * Weiss, A. D. 2001. Topographic Positions and Landforms Analysis (poster), 
      79                 :  *  ESRI International User Conference, July 2001. San Diego, CA: ESRI.
      80                 :  * Wilson, M. F. J.; O'Connell, B.; Brown, C.; Guinan, J. C. & Grehan, A. J. 
      81                 :  *  Multiscale terrain analysis of multibeam bathymetry data for habitat mapping
      82                 :  *  on the continental slope Marine Geodesy, 2007, 30, 3-35
      83                 :  ****************************************************************************/
      84                 : 
      85                 : #include <stdlib.h>
      86                 : #include <math.h>
      87                 : 
      88                 : #include "cpl_conv.h"
      89                 : #include "cpl_string.h"
      90                 : #include "gdal.h"
      91                 : #include "gdal_priv.h"
      92                 : 
      93                 : CPL_CVSID("$Id: gdaldem.cpp 19812 2010-06-06 22:37:13Z rouault $");
      94                 : 
      95                 : #ifndef M_PI
      96                 : # define M_PI  3.1415926535897932384626433832795
      97                 : #endif
      98                 : 
      99                 : #define INTERPOL(a,b) ((bSrcHasNoData && (EQUAL_TO_NODATA(a, fSrcNoDataValue) || EQUAL_TO_NODATA(b, fSrcNoDataValue))) ? fSrcNoDataValue : 2 * (a) - (b))
     100                 : 
     101                 : /************************************************************************/
     102                 : /*                               Usage()                                */
     103                 : /************************************************************************/
     104                 : 
     105               0 : static void Usage()
     106                 : 
     107                 : {
     108                 :     printf( " Usage: \n"
     109                 :             " - To generate a shaded relief map from any GDAL-supported elevation raster : \n\n"
     110                 :             "     gdaldem hillshade input_dem output_hillshade \n"
     111                 :             "                 [-z ZFactor (default=1)] [-s scale* (default=1)] \n"
     112                 :             "                 [-az Azimuth (default=315)] [-alt Altitude (default=45)]\n"
     113                 :             "                 [-alg ZevenbergenThorne]\n"
     114                 :             "                 [-compute_edges] [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
     115                 :             "\n"
     116                 :             " - To generates a slope map from any GDAL-supported elevation raster :\n\n"
     117                 :             "     gdaldem slope input_dem output_slope_map \n"
     118                 :             "                 [-p use percent slope (default=degrees)] [-s scale* (default=1)]\n"
     119                 :             "                 [-alg ZevenbergenThorne]\n"
     120                 :             "                 [-compute_edges] [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
     121                 :             "\n"
     122                 :             " - To generate an aspect map from any GDAL-supported elevation raster\n"
     123                 :             "   Outputs a 32-bit float tiff with pixel values from 0-360 indicating azimuth :\n\n"
     124                 :             "     gdaldem aspect input_dem output_aspect_map \n"
     125                 :             "                 [-trigonometric] [-zero_for_flat]\n"
     126                 :             "                 [-alg ZevenbergenThorne]\n"
     127                 :             "                 [-compute_edges] [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
     128                 :             "\n"
     129                 :             " - To generate a color relief map from any GDAL-supported elevation raster\n"
     130                 :             "     gdaldem color-relief input_dem color_text_file output_color_relief_map\n"
     131                 :             "                 [-alpha] [-exact_color_entry | -nearest_color_entry]\n"
     132                 :             "                 [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
     133                 :             "     where color_text_file contains lines of the format \"elevation_value red green blue\"\n"
     134                 :             "\n"
     135                 :             " - To generate a Terrain Ruggedness Index (TRI) map from any GDAL-supported elevation raster\n"
     136                 :             "     gdaldem TRI input_dem output_TRI_map\n"
     137                 :             "                 [-compute_edges] [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
     138                 :             "\n"
     139                 :             " - To generate a Topographic Position Index (TPI) map from any GDAL-supported elevation raster\n"
     140                 :             "     gdaldem TPI input_dem output_TPI_map\n"
     141                 :             "                 [-compute_edges] [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
     142                 :             "\n"
     143                 :             " - To generate a roughness map from any GDAL-supported elevation raster\n"
     144                 :             "     gdaldem roughness input_dem output_roughness_map\n"
     145                 :             "                 [-compute_edges] [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
     146                 :             "\n"
     147                 :             " Notes : \n"
     148                 :             "   Scale is the ratio of vertical units to horizontal\n"
     149               0 :             "    for Feet:Latlong use scale=370400, for Meters:LatLong use scale=111120 \n\n");
     150               0 :     exit( 1 );
     151                 : }
     152                 : 
     153                 : /************************************************************************/
     154                 : /*                          ComputeVal()                                */
     155                 : /************************************************************************/
     156                 : 
     157                 : typedef float (*GDALGeneric3x3ProcessingAlg) (float* pafWindow, float fDstNoDataValue, void* pData);
     158                 : 
     159                 : static float ComputeVal(int bSrcHasNoData, float fSrcNoDataValue,
     160                 :                         float* afWin, float fDstNoDataValue,
     161                 :                         GDALGeneric3x3ProcessingAlg pfnAlg,
     162                 :                         void* pData,
     163           95530 :                         int bComputeAtEdges)
     164                 : {
     165           95530 :     if (bSrcHasNoData && EQUAL_TO_NODATA(afWin[4], fSrcNoDataValue))
     166                 :     {
     167               0 :         return fDstNoDataValue;
     168                 :     }
     169           95530 :     else if (bSrcHasNoData)
     170                 :     {
     171                 :         int k;
     172          859260 :         for(k=0;k<9;k++)
     173                 :         {
     174          773334 :             if (EQUAL_TO_NODATA(afWin[k], fSrcNoDataValue))
     175                 :             {
     176               0 :                 if (bComputeAtEdges)
     177               0 :                     afWin[k] = afWin[4];
     178                 :                 else
     179               0 :                     return fDstNoDataValue;
     180                 :             }
     181                 :         }
     182                 :     }
     183                 : 
     184           95530 :     return pfnAlg(afWin, fDstNoDataValue, pData);
     185                 : }
     186                 : 
     187                 : /************************************************************************/
     188                 : /*                  GDALGeneric3x3Processing()                          */
     189                 : /************************************************************************/
     190                 : 
     191                 : CPLErr GDALGeneric3x3Processing  ( GDALRasterBandH hSrcBand,
     192                 :                                    GDALRasterBandH hDstBand,
     193                 :                                    GDALGeneric3x3ProcessingAlg pfnAlg,
     194                 :                                    void* pData,
     195                 :                                    int bComputeAtEdges,
     196                 :                                    GDALProgressFunc pfnProgress,
     197               5 :                                    void * pProgressData)
     198                 : {
     199                 :     CPLErr eErr;
     200                 :     float *pafThreeLineWin; /* 3 line rotating source buffer */
     201                 :     float *pafOutputBuf;     /* 1 line destination buffer */
     202                 :     int i, j;
     203                 : 
     204                 :     int bSrcHasNoData, bDstHasNoData;
     205               5 :     float fSrcNoDataValue = 0.0, fDstNoDataValue = 0.0;
     206                 : 
     207               5 :     int nXSize = GDALGetRasterBandXSize(hSrcBand);
     208               5 :     int nYSize = GDALGetRasterBandYSize(hSrcBand);
     209                 : 
     210               5 :     if (pfnProgress == NULL)
     211               0 :         pfnProgress = GDALDummyProgress;
     212                 : 
     213                 : /* -------------------------------------------------------------------- */
     214                 : /*      Initialize progress counter.                                    */
     215                 : /* -------------------------------------------------------------------- */
     216               5 :     if( !pfnProgress( 0.0, NULL, pProgressData ) )
     217                 :     {
     218               0 :         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
     219               0 :         return CE_Failure;
     220                 :     }
     221                 : 
     222               5 :     pafOutputBuf = (float *) CPLMalloc(sizeof(float)*nXSize);
     223               5 :     pafThreeLineWin  = (float *) CPLMalloc(3*sizeof(float)*(nXSize+1));
     224                 : 
     225               5 :     fSrcNoDataValue = (float) GDALGetRasterNoDataValue(hSrcBand, &bSrcHasNoData);
     226               5 :     fDstNoDataValue = (float) GDALGetRasterNoDataValue(hDstBand, &bDstHasNoData);
     227               5 :     if (!bDstHasNoData)
     228               0 :         fDstNoDataValue = 0.0;
     229                 : 
     230                 :     // Move a 3x3 pafWindow over each cell 
     231                 :     // (where the cell in question is #4)
     232                 :     // 
     233                 :     //      0 1 2
     234                 :     //      3 4 5
     235                 :     //      6 7 8
     236                 : 
     237                 :     /* Preload the first 2 lines */
     238              15 :     for ( i = 0; i < 2 && i < nYSize; i++)
     239                 :     {
     240                 :         GDALRasterIO(   hSrcBand,
     241                 :                         GF_Read,
     242                 :                         0, i,
     243                 :                         nXSize, 1,
     244                 :                         pafThreeLineWin + i * nXSize,
     245                 :                         nXSize, 1,
     246                 :                         GDT_Float32,
     247              10 :                         0, 0);
     248                 :     }
     249                 :     
     250               6 :     if (bComputeAtEdges && nXSize >= 2 && nYSize >= 2)
     251                 :     {
     252             122 :         for (j = 0; j < nXSize; j++)
     253                 :         {
     254                 :             float afWin[9];
     255             121 :             int jmin = (j == 0) ? j : j - 1;
     256             121 :             int jmax = (j == nXSize - 1) ? j : j + 1;
     257                 : 
     258             121 :             afWin[0] = INTERPOL(pafThreeLineWin[jmin], pafThreeLineWin[nXSize + jmin]);
     259             121 :             afWin[1] = INTERPOL(pafThreeLineWin[j],    pafThreeLineWin[nXSize + j]);
     260             121 :             afWin[2] = INTERPOL(pafThreeLineWin[jmax], pafThreeLineWin[nXSize + jmax]);
     261             121 :             afWin[3] = pafThreeLineWin[jmin];
     262             121 :             afWin[4] = pafThreeLineWin[j];
     263             121 :             afWin[5] = pafThreeLineWin[jmax];
     264             121 :             afWin[6] = pafThreeLineWin[nXSize + jmin];
     265             121 :             afWin[7] = pafThreeLineWin[nXSize + j];
     266             121 :             afWin[8] = pafThreeLineWin[nXSize + jmax];
     267                 : 
     268                 :             pafOutputBuf[j] = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
     269                 :                                          afWin, fDstNoDataValue,
     270             121 :                                          pfnAlg, pData, bComputeAtEdges);
     271                 :         }
     272                 :         GDALRasterIO(hDstBand, GF_Write,
     273                 :                     0, 0, nXSize, 1,
     274               1 :                     pafOutputBuf, nXSize, 1, GDT_Float32, 0, 0);
     275                 :     }
     276                 :     else
     277                 :     {
     278                 :         // Exclude the edges
     279             467 :         for (j = 0; j < nXSize; j++)
     280                 :         {
     281             463 :             pafOutputBuf[j] = fDstNoDataValue;
     282                 :         }
     283                 :         GDALRasterIO(hDstBand, GF_Write,
     284                 :                     0, 0, nXSize, 1,
     285               4 :                     pafOutputBuf, nXSize, 1, GDT_Float32, 0, 0);
     286                 :     
     287               4 :         if (nYSize > 1)
     288                 :         {
     289                 :             GDALRasterIO(hDstBand, GF_Write,
     290                 :                         0, nYSize - 1, nXSize, 1,
     291               4 :                         pafOutputBuf, nXSize, 1, GDT_Float32, 0, 0);
     292                 :         }
     293                 :     }
     294                 :     
     295               5 :     int nLine1Off = 0*nXSize;
     296               5 :     int nLine2Off = 1*nXSize;
     297               5 :     int nLine3Off = 2*nXSize;
     298                 : 
     299             579 :     for ( i = 1; i < nYSize-1; i++)
     300                 :     {
     301                 :         /* Read third line of the line buffer */
     302                 :         eErr = GDALRasterIO(   hSrcBand,
     303                 :                         GF_Read,
     304                 :                         0, i+1,
     305                 :                         nXSize, 1,
     306                 :                         pafThreeLineWin + nLine3Off,
     307                 :                         nXSize, 1,
     308                 :                         GDT_Float32,
     309             574 :                         0, 0);
     310             574 :         if (eErr != CE_None)
     311               0 :             goto end;
     312                 : 
     313             693 :         if (bComputeAtEdges && nXSize >= 2)
     314                 :         {
     315                 :             float afWin[9];
     316                 : 
     317             119 :             j = 0;
     318             119 :             afWin[0] = INTERPOL(pafThreeLineWin[nLine1Off + j], pafThreeLineWin[nLine1Off + j+1]);
     319             119 :             afWin[1] = pafThreeLineWin[nLine1Off + j];
     320             119 :             afWin[2] = pafThreeLineWin[nLine1Off + j+1];
     321             119 :             afWin[3] = INTERPOL(pafThreeLineWin[nLine2Off + j], pafThreeLineWin[nLine2Off + j+1]);
     322             119 :             afWin[4] = pafThreeLineWin[nLine2Off + j];
     323             119 :             afWin[5] = pafThreeLineWin[nLine2Off + j+1];
     324             119 :             afWin[6] = INTERPOL(pafThreeLineWin[nLine3Off + j], pafThreeLineWin[nLine3Off + j+1]);
     325             119 :             afWin[7] = pafThreeLineWin[nLine3Off + j];
     326             119 :             afWin[8] = pafThreeLineWin[nLine3Off + j+1];
     327                 : 
     328                 :             pafOutputBuf[j] = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
     329                 :                                          afWin, fDstNoDataValue,
     330             119 :                                          pfnAlg, pData, bComputeAtEdges);
     331             119 :             j = nXSize - 1;
     332                 : 
     333             119 :             afWin[0] = pafThreeLineWin[nLine1Off + j-1];
     334             119 :             afWin[1] = pafThreeLineWin[nLine1Off + j];
     335             119 :             afWin[2] = INTERPOL(pafThreeLineWin[nLine1Off + j], pafThreeLineWin[nLine1Off + j-1]);
     336             119 :             afWin[3] = pafThreeLineWin[nLine2Off + j-1];
     337             119 :             afWin[4] = pafThreeLineWin[nLine2Off + j];
     338             119 :             afWin[5] = INTERPOL(pafThreeLineWin[nLine2Off + j], pafThreeLineWin[nLine2Off + j-1]);
     339             119 :             afWin[6] = pafThreeLineWin[nLine3Off + j-1];
     340             119 :             afWin[7] = pafThreeLineWin[nLine3Off + j];
     341             119 :             afWin[8] = INTERPOL(pafThreeLineWin[nLine3Off + j], pafThreeLineWin[nLine3Off + j-1]);
     342                 : 
     343                 :             pafOutputBuf[j] = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
     344                 :                                          afWin, fDstNoDataValue,
     345             119 :                                          pfnAlg, pData, bComputeAtEdges);
     346                 :         }
     347                 :         else
     348                 :         {
     349                 :             // Exclude the edges
     350             455 :             pafOutputBuf[0] = fDstNoDataValue;
     351             455 :             if (nXSize > 1)
     352             455 :                 pafOutputBuf[nXSize - 1] = fDstNoDataValue;
     353                 :         }
     354                 : 
     355           66822 :         for (j = 1; j < nXSize - 1; j++)
     356                 :         {
     357                 :             float afWin[9];
     358           66248 :             afWin[0] = pafThreeLineWin[nLine1Off + j-1];
     359           66248 :             afWin[1] = pafThreeLineWin[nLine1Off + j];
     360           66248 :             afWin[2] = pafThreeLineWin[nLine1Off + j+1];
     361           66248 :             afWin[3] = pafThreeLineWin[nLine2Off + j-1];
     362           66248 :             afWin[4] = pafThreeLineWin[nLine2Off + j];
     363           66248 :             afWin[5] = pafThreeLineWin[nLine2Off + j+1];
     364           66248 :             afWin[6] = pafThreeLineWin[nLine3Off + j-1];
     365           66248 :             afWin[7] = pafThreeLineWin[nLine3Off + j];
     366           66248 :             afWin[8] = pafThreeLineWin[nLine3Off + j+1];
     367                 : 
     368                 :             pafOutputBuf[j] = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
     369                 :                                          afWin, fDstNoDataValue,
     370           66248 :                                          pfnAlg, pData, bComputeAtEdges);
     371                 :         }
     372                 : 
     373                 :         /* -----------------------------------------
     374                 :          * Write Line to Raster
     375                 :          */
     376                 :         eErr = GDALRasterIO(hDstBand, GF_Write, 0, i, nXSize, 1,
     377             574 :                      pafOutputBuf, nXSize, 1, GDT_Float32, 0, 0);
     378             574 :         if (eErr != CE_None)
     379               0 :             goto end;
     380                 : 
     381             574 :         if( !pfnProgress( 1.0 * (i+1) / nYSize, NULL, pProgressData ) )
     382                 :         {
     383               0 :             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
     384               0 :             eErr = CE_Failure;
     385               0 :             goto end;
     386                 :         }
     387                 :         
     388             574 :         int nTemp = nLine1Off;
     389             574 :         nLine1Off = nLine2Off;
     390             574 :         nLine2Off = nLine3Off;
     391             574 :         nLine3Off = nTemp;
     392                 :     }
     393                 : 
     394               5 :     if (bComputeAtEdges && nXSize >= 2 && nYSize >= 2)
     395                 :     {
     396             122 :         for (j = 0; j < nXSize; j++)
     397                 :         {
     398                 :             float afWin[9];
     399             121 :             int jmin = (j == 0) ? j : j - 1;
     400             121 :             int jmax = (j == nXSize - 1) ? j : j + 1;
     401                 : 
     402             121 :             afWin[0] = pafThreeLineWin[nLine1Off + jmin];
     403             121 :             afWin[1] = pafThreeLineWin[nLine1Off + j];
     404             121 :             afWin[2] = pafThreeLineWin[nLine1Off + jmax];
     405             121 :             afWin[3] = pafThreeLineWin[nLine2Off + jmin];
     406             121 :             afWin[4] = pafThreeLineWin[nLine2Off + j];
     407             121 :             afWin[5] = pafThreeLineWin[nLine2Off + jmax];
     408             121 :             afWin[6] = INTERPOL(pafThreeLineWin[nLine2Off + jmin], pafThreeLineWin[nLine1Off + jmin]);
     409             121 :             afWin[7] = INTERPOL(pafThreeLineWin[nLine2Off + j],    pafThreeLineWin[nLine1Off + j]);
     410             121 :             afWin[8] = INTERPOL(pafThreeLineWin[nLine2Off + jmax], pafThreeLineWin[nLine1Off + jmax]);
     411                 : 
     412                 :             pafOutputBuf[j] = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
     413                 :                                          afWin, fDstNoDataValue,
     414             121 :                                          pfnAlg, pData, bComputeAtEdges);
     415                 :         }
     416                 :         GDALRasterIO(hDstBand, GF_Write,
     417                 :                      0, i, nXSize, 1,
     418               1 :                      pafOutputBuf, nXSize, 1, GDT_Float32, 0, 0);
     419                 :     }
     420                 : 
     421               5 :     pfnProgress( 1.0, NULL, pProgressData );
     422               5 :     eErr = CE_None;
     423                 : 
     424               5 : end:
     425               5 :     CPLFree(pafOutputBuf);
     426               5 :     CPLFree(pafThreeLineWin);
     427                 : 
     428               5 :     return eErr;
     429                 : }
     430                 : 
     431                 : 
     432                 : /************************************************************************/
     433                 : /*                         GDALHillshade()                              */
     434                 : /************************************************************************/
     435                 : 
     436                 : typedef struct
     437                 : {
     438                 :     double nsres;
     439                 :     double ewres;
     440                 :     double sin_altRadians;
     441                 :     double cos_altRadians_mul_z_scale_factor;
     442                 :     double azRadians;
     443                 :     double square_z_scale_factor;
     444                 : } GDALHillshadeAlgData;
     445                 : 
     446                 : /* Unoptimized formulas are :
     447                 :     x = psData->z*((afWin[0] + afWin[3] + afWin[3] + afWin[6]) -
     448                 :         (afWin[2] + afWin[5] + afWin[5] + afWin[8])) /
     449                 :         (8.0 * psData->ewres * psData->scale);
     450                 : 
     451                 :     y = psData->z*((afWin[6] + afWin[7] + afWin[7] + afWin[8]) -
     452                 :         (afWin[0] + afWin[1] + afWin[1] + afWin[2])) /
     453                 :         (8.0 * psData->nsres * psData->scale);
     454                 : 
     455                 :     slope = M_PI / 2 - atan(sqrt(x*x + y*y));
     456                 : 
     457                 :     aspect = atan2(y,x);
     458                 : 
     459                 :     cang = sin(alt * degreesToRadians) * sin(slope) +
     460                 :            cos(alt * degreesToRadians) * cos(slope) *
     461                 :            cos(az * degreesToRadians - M_PI/2 - aspect);
     462                 : */
     463                 : 
     464           67208 : float GDALHillshadeAlg (float* afWin, float fDstNoDataValue, void* pData)
     465                 : {
     466           67208 :     GDALHillshadeAlgData* psData = (GDALHillshadeAlgData*)pData;
     467                 :     double x, y, aspect, xx_plus_yy, cang;
     468                 :     
     469                 :     // First Slope ...
     470                 :     x = ((afWin[0] + afWin[3] + afWin[3] + afWin[6]) -
     471           67208 :         (afWin[2] + afWin[5] + afWin[5] + afWin[8])) / psData->ewres;
     472                 : 
     473                 :     y = ((afWin[6] + afWin[7] + afWin[7] + afWin[8]) -
     474           67208 :         (afWin[0] + afWin[1] + afWin[1] + afWin[2])) / psData->nsres;
     475                 : 
     476           67208 :     xx_plus_yy = x * x + y * y;
     477                 : 
     478                 :     // ... then aspect...
     479           67208 :     aspect = atan2(y,x);
     480                 : 
     481                 :     // ... then the shade value
     482                 :     cang = (psData->sin_altRadians -
     483                 :            psData->cos_altRadians_mul_z_scale_factor * sqrt(xx_plus_yy) *
     484                 :            sin(aspect - psData->azRadians)) /
     485           67208 :            sqrt(1 + psData->square_z_scale_factor * xx_plus_yy);
     486                 : 
     487           67208 :     if (cang <= 0.0) 
     488             416 :         cang = 1.0;
     489                 :     else
     490           66792 :         cang = 1.0 + (254.0 * cang);
     491                 :         
     492           67208 :     return cang;
     493                 : }
     494                 : 
     495               0 : float GDALHillshadeZevenbergenThorneAlg (float* afWin, float fDstNoDataValue, void* pData)
     496                 : {
     497               0 :     GDALHillshadeAlgData* psData = (GDALHillshadeAlgData*)pData;
     498                 :     double x, y, aspect, xx_plus_yy, cang;
     499                 :     
     500                 :     // First Slope ...
     501               0 :     x = (afWin[3] - afWin[5]) / psData->ewres;
     502                 : 
     503               0 :     y = (afWin[7] - afWin[1]) / psData->nsres;
     504                 : 
     505               0 :     xx_plus_yy = x * x + y * y;
     506                 : 
     507                 :     // ... then aspect...
     508               0 :     aspect = atan2(y,x);
     509                 : 
     510                 :     // ... then the shade value
     511                 :     cang = (psData->sin_altRadians -
     512                 :            psData->cos_altRadians_mul_z_scale_factor * sqrt(xx_plus_yy) *
     513                 :            sin(aspect - psData->azRadians)) /
     514               0 :            sqrt(1 + psData->square_z_scale_factor * xx_plus_yy);
     515                 : 
     516               0 :     if (cang <= 0.0) 
     517               0 :         cang = 1.0;
     518                 :     else
     519               0 :         cang = 1.0 + (254.0 * cang);
     520                 :         
     521               0 :     return cang;
     522                 : }
     523                 : 
     524                 : void*  GDALCreateHillshadeData(double* adfGeoTransform,
     525                 :                                double z,
     526                 :                                double scale,
     527                 :                                double alt,
     528                 :                                double az,
     529               5 :                                int bZevenbergenThorne)
     530                 : {
     531                 :     GDALHillshadeAlgData* pData =
     532               5 :         (GDALHillshadeAlgData*)CPLMalloc(sizeof(GDALHillshadeAlgData));
     533                 :         
     534               5 :     const double degreesToRadians = M_PI / 180.0;
     535               5 :     pData->nsres = adfGeoTransform[5];
     536               5 :     pData->ewres = adfGeoTransform[1];
     537               5 :     pData->sin_altRadians = sin(alt * degreesToRadians);
     538               5 :     pData->azRadians = az * degreesToRadians;
     539               5 :     double z_scale_factor = z / (((bZevenbergenThorne) ? 2 : 8) * scale);
     540                 :     pData->cos_altRadians_mul_z_scale_factor =
     541               5 :         cos(alt * degreesToRadians) * z_scale_factor;
     542               5 :     pData->square_z_scale_factor = z_scale_factor * z_scale_factor;
     543               5 :     return pData;
     544                 : }
     545                 : 
     546                 : /************************************************************************/
     547                 : /*                         GDALSlope()                                  */
     548                 : /************************************************************************/
     549                 : 
     550                 : typedef struct
     551                 : {
     552                 :     double nsres;
     553                 :     double ewres;
     554                 :     double scale;
     555                 :     int    slopeFormat;
     556                 : } GDALSlopeAlgData;
     557                 : 
     558           14161 : float GDALSlopeHornAlg (float* afWin, float fDstNoDataValue, void* pData)
     559                 : {
     560           14161 :     const double radiansToDegrees = 180.0 / M_PI;
     561           14161 :     GDALSlopeAlgData* psData = (GDALSlopeAlgData*)pData;
     562                 :     double dx, dy, key;
     563                 :     
     564                 :     dx = ((afWin[0] + afWin[3] + afWin[3] + afWin[6]) - 
     565           14161 :           (afWin[2] + afWin[5] + afWin[5] + afWin[8]))/psData->ewres;
     566                 : 
     567                 :     dy = ((afWin[6] + afWin[7] + afWin[7] + afWin[8]) - 
     568           14161 :           (afWin[0] + afWin[1] + afWin[1] + afWin[2]))/psData->nsres;
     569                 : 
     570           14161 :     key = (dx * dx + dy * dy);
     571                 : 
     572           14161 :     if (psData->slopeFormat == 1) 
     573           14161 :         return atan(sqrt(key) / (8*psData->scale)) * radiansToDegrees;
     574                 :     else
     575               0 :         return 100*(sqrt(key) / (8*psData->scale));
     576                 : }
     577                 : 
     578               0 : float GDALSlopeZevenbergenThorneAlg (float* afWin, float fDstNoDataValue, void* pData)
     579                 : {
     580               0 :     const double radiansToDegrees = 180.0 / M_PI;
     581               0 :     GDALSlopeAlgData* psData = (GDALSlopeAlgData*)pData;
     582                 :     double dx, dy, key;
     583                 :     
     584               0 :     dx = (afWin[3] - afWin[5])/psData->ewres;
     585                 : 
     586               0 :     dy = (afWin[7] - afWin[1])/psData->nsres;
     587                 : 
     588               0 :     key = (dx * dx + dy * dy);
     589                 : 
     590               0 :     if (psData->slopeFormat == 1) 
     591               0 :         return atan(sqrt(key) / (2*psData->scale)) * radiansToDegrees;
     592                 :     else
     593               0 :         return 100*(sqrt(key) / (2*psData->scale));
     594                 : }
     595                 : 
     596                 : void*  GDALCreateSlopeData(double* adfGeoTransform,
     597                 :                            double scale,
     598               1 :                            int slopeFormat)
     599                 : {
     600                 :     GDALSlopeAlgData* pData =
     601               1 :         (GDALSlopeAlgData*)CPLMalloc(sizeof(GDALSlopeAlgData));
     602                 :         
     603               1 :     pData->nsres = adfGeoTransform[5];
     604               1 :     pData->ewres = adfGeoTransform[1];
     605               1 :     pData->scale = scale;
     606               1 :     pData->slopeFormat = slopeFormat;
     607               1 :     return pData;
     608                 : }
     609                 : 
     610                 : /************************************************************************/
     611                 : /*                         GDALAspect()                                 */
     612                 : /************************************************************************/
     613                 : 
     614                 : typedef struct
     615                 : {
     616                 :     int bAngleAsAzimuth;
     617                 : } GDALAspectAlgData;
     618                 : 
     619           14161 : float GDALAspectAlg (float* afWin, float fDstNoDataValue, void* pData)
     620                 : {
     621           14161 :     const double degreesToRadians = M_PI / 180.0;
     622           14161 :     GDALAspectAlgData* psData = (GDALAspectAlgData*)pData;
     623                 :     double dx, dy;
     624                 :     float aspect;
     625                 :     
     626                 :     dx = ((afWin[2] + afWin[5] + afWin[5] + afWin[8]) -
     627           14161 :           (afWin[0] + afWin[3] + afWin[3] + afWin[6]));
     628                 : 
     629                 :     dy = ((afWin[6] + afWin[7] + afWin[7] + afWin[8]) - 
     630           14161 :           (afWin[0] + afWin[1] + afWin[1] + afWin[2]));
     631                 : 
     632           14161 :     aspect = atan2(dy,-dx) / degreesToRadians;
     633                 : 
     634           18344 :     if (dx == 0 && dy == 0)
     635                 :     {
     636                 :         /* Flat area */
     637            4183 :         aspect = fDstNoDataValue;
     638                 :     } 
     639            9978 :     else if ( psData->bAngleAsAzimuth )
     640                 :     {
     641            9978 :         if (aspect > 90.0) 
     642            1243 :             aspect = 450.0 - aspect;
     643                 :         else
     644            8735 :             aspect = 90.0 - aspect;
     645                 :     }
     646                 :     else
     647                 :     {
     648               0 :         if (aspect < 0)
     649               0 :             aspect += 360.0;
     650                 :     }
     651                 : 
     652           14161 :     if (aspect == 360.0) 
     653               0 :         aspect = 0.0;
     654                 : 
     655           14161 :     return aspect;
     656                 : }
     657                 : 
     658               0 : float GDALAspectZevenbergenThorneAlg (float* afWin, float fDstNoDataValue, void* pData)
     659                 : {
     660               0 :     const double degreesToRadians = M_PI / 180.0;
     661               0 :     GDALAspectAlgData* psData = (GDALAspectAlgData*)pData;
     662                 :     double dx, dy;
     663                 :     float aspect;
     664                 :     
     665               0 :     dx = (afWin[5] - afWin[3]);
     666                 : 
     667               0 :     dy = (afWin[7] - afWin[1]);
     668                 : 
     669               0 :     aspect = atan2(dy,-dx) / degreesToRadians;
     670                 : 
     671               0 :     if (dx == 0 && dy == 0)
     672                 :     {
     673                 :         /* Flat area */
     674               0 :         aspect = fDstNoDataValue;
     675                 :     } 
     676               0 :     else if ( psData->bAngleAsAzimuth )
     677                 :     {
     678               0 :         if (aspect > 90.0) 
     679               0 :             aspect = 450.0 - aspect;
     680                 :         else
     681               0 :             aspect = 90.0 - aspect;
     682                 :     }
     683                 :     else
     684                 :     {
     685               0 :         if (aspect < 0)
     686               0 :             aspect += 360.0;
     687                 :     }
     688                 : 
     689               0 :     if (aspect == 360.0) 
     690               0 :         aspect = 0.0;
     691                 : 
     692               0 :     return aspect;
     693                 : }
     694               1 : void*  GDALCreateAspectData(int bAngleAsAzimuth)
     695                 : {
     696                 :     GDALAspectAlgData* pData =
     697               1 :         (GDALAspectAlgData*)CPLMalloc(sizeof(GDALAspectAlgData));
     698                 :         
     699               1 :     pData->bAngleAsAzimuth = bAngleAsAzimuth;
     700               1 :     return pData;
     701                 : }
     702                 : 
     703                 : /************************************************************************/
     704                 : /*                      GDALColorRelief()                               */
     705                 : /************************************************************************/
     706                 : 
     707                 : typedef struct
     708                 : {
     709                 :     double dfVal;
     710                 :     int nR;
     711                 :     int nG;
     712                 :     int nB;
     713                 :     int nA;
     714                 : } ColorAssociation;
     715                 : 
     716              77 : static int GDALColorReliefSortColors(const void* pA, const void* pB)
     717                 : {
     718              77 :     ColorAssociation* pC1 = (ColorAssociation*)pA;
     719              77 :     ColorAssociation* pC2 = (ColorAssociation*)pB;
     720                 :     return (pC1->dfVal < pC2->dfVal) ? -1 :
     721              77 :            (pC1->dfVal == pC2->dfVal) ? 0 : 1;
     722                 : }
     723                 : 
     724                 : typedef enum
     725                 : {
     726                 :     COLOR_SELECTION_INTERPOLATE,
     727                 :     COLOR_SELECTION_NEAREST_ENTRY,
     728                 :     COLOR_SELECTION_EXACT_ENTRY
     729                 : } ColorSelectionMode;
     730                 : 
     731                 : static int GDALColorReliefGetRGBA (ColorAssociation* pasColorAssociation,
     732                 :                                    int nColorAssociation,
     733                 :                                    double dfVal,
     734                 :                                    ColorSelectionMode eColorSelectionMode,
     735                 :                                    int* pnR,
     736                 :                                    int* pnG,
     737                 :                                    int* pnB,
     738          131769 :                                    int* pnA)
     739                 : {
     740                 :     int i;
     741          131769 :     int lower = 0;
     742          131769 :     int upper = nColorAssociation - 1;
     743                 :     int mid;
     744                 : 
     745                 :     /* Find the index of the first element in the LUT input array that */
     746                 :     /* is not smaller than the dfVal value. */
     747          288783 :     while(TRUE)
     748                 :     {
     749          420552 :         mid = (lower + upper) / 2;
     750          420552 :         if (upper - lower <= 1)
     751                 :         {
     752          131769 :             if (dfVal < pasColorAssociation[lower].dfVal)
     753               0 :                 i = lower;
     754          131769 :             else if (dfVal < pasColorAssociation[upper].dfVal)
     755           89685 :                 i = upper;
     756                 :             else
     757           42084 :                 i = upper + 1;
     758                 :             break;
     759                 :         }
     760          288783 :         else if (pasColorAssociation[mid].dfVal >= dfVal)
     761                 :         {
     762          173367 :             upper = mid;
     763                 :         }
     764                 :         else
     765                 :         {
     766          115416 :             lower = mid;
     767                 :         }
     768                 :     }
     769                 : 
     770          131769 :     if (i == 0)
     771                 :     {
     772               0 :         if (eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY &&
     773                 :             pasColorAssociation[0].dfVal != dfVal)
     774                 :         {
     775               0 :             *pnR = 0;
     776               0 :             *pnG = 0;
     777               0 :             *pnB = 0;
     778               0 :             *pnA = 0;
     779               0 :             return FALSE;
     780                 :         }
     781                 :         else
     782                 :         {
     783               0 :             *pnR = pasColorAssociation[0].nR;
     784               0 :             *pnG = pasColorAssociation[0].nG;
     785               0 :             *pnB = pasColorAssociation[0].nB;
     786               0 :             *pnA = pasColorAssociation[0].nA;
     787               0 :             return TRUE;
     788                 :         }
     789                 :     }
     790          131769 :     else if (i == nColorAssociation)
     791                 :     {
     792               0 :         if (eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY &&
     793                 :             pasColorAssociation[i-1].dfVal != dfVal)
     794                 :         {
     795               0 :             *pnR = 0;
     796               0 :             *pnG = 0;
     797               0 :             *pnB = 0;
     798               0 :             *pnA = 0;
     799               0 :             return FALSE;
     800                 :         }
     801                 :         else
     802                 :         {
     803               0 :             *pnR = pasColorAssociation[i-1].nR;
     804               0 :             *pnG = pasColorAssociation[i-1].nG;
     805               0 :             *pnB = pasColorAssociation[i-1].nB;
     806               0 :             *pnA = pasColorAssociation[i-1].nA;
     807               0 :             return TRUE;
     808                 :         }
     809                 :     }
     810                 :     else
     811                 :     {
     812          131769 :         if (eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY &&
     813                 :             pasColorAssociation[i-1].dfVal != dfVal)
     814                 :         {
     815               0 :             *pnR = 0;
     816               0 :             *pnG = 0;
     817               0 :             *pnB = 0;
     818               0 :             *pnA = 0;
     819               0 :             return FALSE;
     820                 :         }
     821                 :         
     822          131769 :         if (eColorSelectionMode == COLOR_SELECTION_NEAREST_ENTRY &&
     823                 :             pasColorAssociation[i-1].dfVal != dfVal)
     824                 :         {
     825                 :             int index;
     826            9965 :             if (dfVal - pasColorAssociation[i-1].dfVal <
     827                 :                 pasColorAssociation[i].dfVal - dfVal)
     828            6716 :                 index = i -1;
     829                 :             else
     830            3249 :                 index = i;
     831                 : 
     832            9965 :             *pnR = pasColorAssociation[index].nR;
     833            9965 :             *pnG = pasColorAssociation[index].nG;
     834            9965 :             *pnB = pasColorAssociation[index].nB;
     835            9965 :             *pnA = pasColorAssociation[index].nA;
     836            9965 :             return TRUE;
     837                 :         }
     838                 :         
     839                 :         double dfRatio = (dfVal - pasColorAssociation[i-1].dfVal) /
     840          121804 :             (pasColorAssociation[i].dfVal - pasColorAssociation[i-1].dfVal);
     841                 :         *pnR = (int)(0.45 + pasColorAssociation[i-1].nR + dfRatio *
     842          121804 :                 (pasColorAssociation[i].nR - pasColorAssociation[i-1].nR));
     843          121804 :         if (*pnR < 0) *pnR = 0;
     844          121804 :         else if (*pnR > 255) *pnR = 255;
     845                 :         *pnG = (int)(0.45 + pasColorAssociation[i-1].nG + dfRatio *
     846          121804 :                 (pasColorAssociation[i].nG - pasColorAssociation[i-1].nG));
     847          121804 :         if (*pnG < 0) *pnG = 0;
     848          121804 :         else if (*pnG > 255) *pnG = 255;
     849                 :         *pnB = (int)(0.45 + pasColorAssociation[i-1].nB + dfRatio *
     850          121804 :                 (pasColorAssociation[i].nB - pasColorAssociation[i-1].nB));
     851          121804 :         if (*pnB < 0) *pnB = 0;
     852          121804 :         else if (*pnB > 255) *pnB = 255;
     853                 :         *pnA = (int)(0.45 + pasColorAssociation[i-1].nA + dfRatio *
     854          121804 :                 (pasColorAssociation[i].nA - pasColorAssociation[i-1].nA));
     855          121804 :         if (*pnA < 0) *pnA = 0;
     856          121804 :         else if (*pnA > 255) *pnA = 255;
     857                 :         
     858          121804 :         return TRUE;
     859                 :     }
     860                 : }
     861                 : 
     862                 : /* dfPct : percentage between 0 and 1 */
     863                 : static double GDALColorReliefGetAbsoluteValFromPct(GDALRasterBandH hSrcBand,
     864               0 :                                                    double dfPct)
     865                 : {
     866                 :     double dfMin, dfMax;
     867                 :     int bSuccessMin, bSuccessMax;
     868               0 :     dfMin = GDALGetRasterMinimum(hSrcBand, &bSuccessMin);
     869               0 :     dfMax = GDALGetRasterMaximum(hSrcBand, &bSuccessMax);
     870               0 :     if (!bSuccessMin || !bSuccessMax)
     871                 :     {
     872                 :         double dfMean, dfStdDev;
     873               0 :         fprintf(stderr, "Computing source raster statistics...\n");
     874                 :         GDALComputeRasterStatistics(hSrcBand, FALSE, &dfMin, &dfMax,
     875               0 :                                     &dfMean, &dfStdDev, NULL, NULL);
     876                 :     }
     877               0 :     return dfMin + dfPct * (dfMax - dfMin);
     878                 : }
     879                 : 
     880                 : typedef struct
     881                 : {
     882                 :     const char *name;
     883                 :     float r, g, b;
     884                 : } NamedColor;
     885                 : 
     886                 : static const NamedColor namedColors[] = {
     887                 :     { "white",  1.00, 1.00, 1.00 },
     888                 :     { "black",  0.00, 0.00, 0.00 },
     889                 :     { "red",    1.00, 0.00, 0.00 },
     890                 :     { "green",  0.00, 1.00, 0.00 },
     891                 :     { "blue",   0.00, 0.00, 1.00 },
     892                 :     { "yellow", 1.00, 1.00, 0.00 },
     893                 :     { "magenta",1.00, 0.00, 1.00 },
     894                 :     { "cyan",   0.00, 1.00, 1.00 },
     895                 :     { "aqua",   0.00, 0.75, 0.75 },
     896                 :     { "grey",   0.75, 0.75, 0.75 },
     897                 :     { "gray",   0.75, 0.75, 0.75 },
     898                 :     { "orange", 1.00, 0.50, 0.00 },
     899                 :     { "brown",  0.75, 0.50, 0.25 },
     900                 :     { "purple", 0.50, 0.00, 1.00 },
     901                 :     { "violet", 0.50, 0.00, 1.00 },
     902                 :     { "indigo", 0.00, 0.50, 1.00 },
     903                 : };
     904                 : 
     905                 : static
     906               0 : int GDALColorReliefFindNamedColor(const char *pszColorName, int *pnR, int *pnG, int *pnB)
     907                 : {
     908                 :     unsigned int i;
     909                 : 
     910               0 :     *pnR = *pnG = *pnB = 0;
     911               0 :     for (i = 0; i < sizeof(namedColors) / sizeof(namedColors[0]); i++)
     912                 :     {
     913               0 :         if (EQUAL(pszColorName, namedColors[i].name))
     914                 :         {
     915               0 :             *pnR = (int)(255. * namedColors[i].r);
     916               0 :             *pnG = (int)(255. * namedColors[i].g);
     917               0 :             *pnB = (int)(255. * namedColors[i].b);
     918               0 :             return TRUE;
     919                 :         }
     920                 :     }
     921               0 :     return FALSE;
     922                 : }
     923                 : 
     924                 : static
     925                 : ColorAssociation* GDALColorReliefParseColorFile(GDALRasterBandH hSrcBand,
     926                 :                                                 const char* pszColorFilename,
     927               7 :                                                 int* pnColors)
     928                 : {
     929               7 :     FILE* fpColorFile = VSIFOpenL(pszColorFilename, "rt");
     930               7 :     if (fpColorFile == NULL)
     931                 :     {
     932               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s", pszColorFilename);
     933               0 :         *pnColors = 0;
     934               0 :         return NULL;
     935                 :     }
     936                 : 
     937               7 :     ColorAssociation* pasColorAssociation = NULL;
     938               7 :     int nColorAssociation = 0;
     939                 : 
     940               7 :     int bSrcHasNoData = FALSE;
     941               7 :     double dfSrcNoDataValue = GDALGetRasterNoDataValue(hSrcBand, &bSrcHasNoData);
     942                 : 
     943                 :     const char* pszLine;
     944              63 :     while ((pszLine = CPLReadLineL(fpColorFile)) != NULL)
     945                 :     {
     946                 :         char** papszFields = CSLTokenizeStringComplex(pszLine, " ,\t:", 
     947              49 :                                                       FALSE, FALSE );
     948                 :         /* Skip comment lines */
     949              49 :         int nTokens = CSLCount(papszFields);
     950              49 :         if (nTokens >= 2 &&
     951                 :             papszFields[0][0] != '#' &&
     952                 :             papszFields[0][0] != '/')
     953                 :         {
     954                 :             pasColorAssociation =
     955                 :                     (ColorAssociation*)CPLRealloc(pasColorAssociation,
     956              49 :                            (nColorAssociation + 1) * sizeof(ColorAssociation));
     957              49 :             if (EQUAL(papszFields[0], "nv") && bSrcHasNoData)
     958               0 :                 pasColorAssociation[nColorAssociation].dfVal = dfSrcNoDataValue;
     959              49 :             else if (strlen(papszFields[0]) > 1 && papszFields[0][strlen(papszFields[0])-1] == '%')
     960                 :             {
     961               0 :                 double dfPct = atof(papszFields[0]) / 100.;
     962               0 :                 if (dfPct < 0.0 || dfPct > 1.0)
     963                 :                 {
     964                 :                     CPLError(CE_Failure, CPLE_AppDefined,
     965               0 :                              "Wrong value for a percentage : %s", papszFields[0]);
     966               0 :                     CSLDestroy(papszFields);
     967               0 :                     VSIFCloseL(fpColorFile);
     968               0 :                     CPLFree(pasColorAssociation);
     969               0 :                     *pnColors = 0;
     970               0 :                     return NULL;
     971                 :                 }
     972                 :                 pasColorAssociation[nColorAssociation].dfVal =
     973               0 :                         GDALColorReliefGetAbsoluteValFromPct(hSrcBand, dfPct);
     974                 :             }
     975                 :             else
     976              49 :                 pasColorAssociation[nColorAssociation].dfVal = atof(papszFields[0]);
     977                 : 
     978              49 :             if (nTokens >= 4)
     979                 :             {
     980              49 :                 pasColorAssociation[nColorAssociation].nR = atoi(papszFields[1]);
     981              49 :                 pasColorAssociation[nColorAssociation].nG = atoi(papszFields[2]);
     982              49 :                 pasColorAssociation[nColorAssociation].nB = atoi(papszFields[3]);
     983                 :                 pasColorAssociation[nColorAssociation].nA =
     984              49 :                         (CSLCount(papszFields) >= 5 ) ? atoi(papszFields[4]) : 255;
     985                 :             }
     986                 :             else
     987                 :             {
     988                 :                 int nR, nG, nB;
     989               0 :                 if (!GDALColorReliefFindNamedColor(papszFields[1], &nR, &nG, &nB))
     990                 :                 {
     991                 :                     CPLError(CE_Failure, CPLE_AppDefined,
     992               0 :                              "Unknown color : %s", papszFields[1]);
     993               0 :                     CSLDestroy(papszFields);
     994               0 :                     VSIFCloseL(fpColorFile);
     995               0 :                     CPLFree(pasColorAssociation);
     996               0 :                     *pnColors = 0;
     997               0 :                     return NULL;
     998                 :                 }
     999               0 :                 pasColorAssociation[nColorAssociation].nR = nR;
    1000               0 :                 pasColorAssociation[nColorAssociation].nG = nG;
    1001               0 :                 pasColorAssociation[nColorAssociation].nB = nB;
    1002                 :                             pasColorAssociation[nColorAssociation].nA =
    1003               0 :                     (CSLCount(papszFields) >= 3 ) ? atoi(papszFields[2]) : 255;
    1004                 :             }
    1005                 : 
    1006              49 :             nColorAssociation ++;
    1007                 :         }
    1008              49 :         CSLDestroy(papszFields);
    1009                 :     }
    1010               7 :     VSIFCloseL(fpColorFile);
    1011                 : 
    1012               7 :     if (nColorAssociation == 0)
    1013                 :     {
    1014                 :         CPLError(CE_Failure, CPLE_AppDefined,
    1015               0 :                  "No color association found in %s", pszColorFilename);
    1016               0 :         *pnColors = 0;
    1017               0 :         return NULL;
    1018                 :     }
    1019                 : 
    1020                 :     qsort(pasColorAssociation, nColorAssociation,
    1021               7 :           sizeof(ColorAssociation), GDALColorReliefSortColors);
    1022                 : 
    1023               7 :     *pnColors = nColorAssociation;
    1024               7 :     return pasColorAssociation;
    1025                 : }
    1026                 : 
    1027                 : static
    1028                 : GByte* GDALColorReliefPrecompute(GDALRasterBandH hSrcBand,
    1029                 :                                  ColorAssociation* pasColorAssociation,
    1030                 :                                  int nColorAssociation,
    1031                 :                                  ColorSelectionMode eColorSelectionMode,
    1032               5 :                                  int* pnIndexOffset)
    1033                 : {
    1034               5 :     GDALDataType eDT = GDALGetRasterDataType(hSrcBand);
    1035               5 :     GByte* pabyPrecomputed = NULL;
    1036               5 :     int nIndexOffset = (eDT == GDT_Int16) ? 32768 : 0;
    1037               5 :     *pnIndexOffset = nIndexOffset;
    1038               5 :     int nXSize = GDALGetRasterBandXSize(hSrcBand);
    1039               5 :     int nYSize = GDALGetRasterBandXSize(hSrcBand);
    1040               5 :     if (eDT == GDT_Byte ||
    1041                 :         ((eDT == GDT_Int16 || eDT == GDT_UInt16) && nXSize * nYSize > 65536))
    1042                 :     {
    1043               0 :         int iMax = (eDT == GDT_Byte) ? 256: 65536;
    1044               0 :         pabyPrecomputed = (GByte*) VSIMalloc(4 * iMax);
    1045               0 :         if (pabyPrecomputed)
    1046                 :         {
    1047                 :             int i;
    1048               0 :             for(i=0;i<iMax;i++)
    1049                 :             {
    1050                 :                 int nR, nG, nB, nA;
    1051                 :                 GDALColorReliefGetRGBA  (pasColorAssociation,
    1052                 :                                          nColorAssociation,
    1053                 :                                          i - nIndexOffset,
    1054                 :                                          eColorSelectionMode,
    1055               0 :                                          &nR, &nG, &nB, &nA);
    1056               0 :                 pabyPrecomputed[4 * i] = (GByte) nR;
    1057               0 :                 pabyPrecomputed[4 * i + 1] = (GByte) nG;
    1058               0 :                 pabyPrecomputed[4 * i + 2] = (GByte) nB;
    1059               0 :                 pabyPrecomputed[4 * i + 3] = (GByte) nA;
    1060                 :             }
    1061                 :         }
    1062                 :     }
    1063               5 :     return pabyPrecomputed;
    1064                 : }
    1065                 : 
    1066                 : /************************************************************************/
    1067                 : /* ==================================================================== */
    1068                 : /*                       GDALColorReliefDataset                        */
    1069                 : /* ==================================================================== */
    1070                 : /************************************************************************/
    1071                 : 
    1072                 : class GDALColorReliefRasterBand;
    1073                 : 
    1074                 : class GDALColorReliefDataset : public GDALDataset
    1075                 : {
    1076                 :     friend class GDALColorReliefRasterBand;
    1077                 : 
    1078                 :     GDALDatasetH       hSrcDS;
    1079                 :     GDALRasterBandH    hSrcBand;
    1080                 :     int                nColorAssociation;
    1081                 :     ColorAssociation*  pasColorAssociation;
    1082                 :     ColorSelectionMode eColorSelectionMode;
    1083                 :     GByte*             pabyPrecomputed;
    1084                 :     int                nIndexOffset;
    1085                 :     float*             pafSourceBuf;
    1086                 :     int*               panSourceBuf;
    1087                 :     int                nCurBlockXOff;
    1088                 :     int                nCurBlockYOff;
    1089                 : 
    1090                 :   public:
    1091                 :                         GDALColorReliefDataset(GDALDatasetH hSrcDS,
    1092                 :                                             GDALRasterBandH hSrcBand,
    1093                 :                                             const char* pszColorFilename,
    1094                 :                                             ColorSelectionMode eColorSelectionMode,
    1095                 :                                             int bAlpha);
    1096                 :                        ~GDALColorReliefDataset();
    1097                 : 
    1098                 :     CPLErr      GetGeoTransform( double * padfGeoTransform );
    1099                 :     const char *GetProjectionRef();
    1100                 : };
    1101                 : 
    1102                 : /************************************************************************/
    1103                 : /* ==================================================================== */
    1104                 : /*                    GDALColorReliefRasterBand                       */
    1105                 : /* ==================================================================== */
    1106                 : /************************************************************************/
    1107                 : 
    1108                 : class GDALColorReliefRasterBand : public GDALRasterBand
    1109               6 : {
    1110                 :     friend class GDALColorReliefDataset;
    1111                 : 
    1112                 :     
    1113                 :   public:
    1114                 :                  GDALColorReliefRasterBand( GDALColorReliefDataset *, int );
    1115                 :     
    1116                 :     virtual CPLErr          IReadBlock( int, int, void * );
    1117                 :     virtual GDALColorInterp GetColorInterpretation();
    1118                 : };
    1119                 : 
    1120                 : GDALColorReliefDataset::GDALColorReliefDataset(
    1121                 :                                      GDALDatasetH hSrcDS,
    1122                 :                                      GDALRasterBandH hSrcBand,
    1123                 :                                      const char* pszColorFilename,
    1124                 :                                      ColorSelectionMode eColorSelectionMode,
    1125               2 :                                      int bAlpha)
    1126                 : {
    1127               2 :     this->hSrcDS = hSrcDS;
    1128               2 :     this->hSrcBand = hSrcBand;
    1129               2 :     nColorAssociation = 0;
    1130                 :     pasColorAssociation =
    1131                 :             GDALColorReliefParseColorFile(hSrcBand, pszColorFilename,
    1132               2 :                                           &nColorAssociation);
    1133               2 :     this->eColorSelectionMode = eColorSelectionMode;
    1134                 :     
    1135               2 :     nRasterXSize = GDALGetRasterXSize(hSrcDS);
    1136               2 :     nRasterYSize = GDALGetRasterYSize(hSrcDS);
    1137                 :     
    1138                 :     int nBlockXSize, nBlockYSize;
    1139               2 :     GDALGetBlockSize( hSrcBand, &nBlockXSize, &nBlockYSize);
    1140                 :     
    1141               2 :     nIndexOffset = 0;
    1142                 :     pabyPrecomputed =
    1143                 :         GDALColorReliefPrecompute(hSrcBand,
    1144                 :                                   pasColorAssociation,
    1145                 :                                   nColorAssociation,
    1146                 :                                   eColorSelectionMode,
    1147               2 :                                   &nIndexOffset);
    1148                 :     
    1149                 :     int i;
    1150               8 :     for(i=0;i<((bAlpha) ? 4 : 3);i++)
    1151                 :     {
    1152               6 :         SetBand(i + 1, new GDALColorReliefRasterBand(this, i+1));
    1153                 :     }
    1154                 :     
    1155               2 :     pafSourceBuf = NULL;
    1156               2 :     panSourceBuf = NULL;
    1157               2 :     if (pabyPrecomputed)
    1158               0 :         panSourceBuf = (int *) CPLMalloc(sizeof(int)*nBlockXSize*nBlockYSize);
    1159                 :     else
    1160               2 :         pafSourceBuf = (float *) CPLMalloc(sizeof(float)*nBlockXSize*nBlockYSize);
    1161               2 :     nCurBlockXOff = -1;
    1162               2 :     nCurBlockYOff = -1;
    1163               2 : }
    1164                 : 
    1165               2 : GDALColorReliefDataset::~GDALColorReliefDataset()
    1166                 : {
    1167               2 :     CPLFree(pasColorAssociation);
    1168               2 :     CPLFree(pabyPrecomputed);
    1169               2 :     CPLFree(panSourceBuf);
    1170               2 :     CPLFree(pafSourceBuf);
    1171               2 : }
    1172                 : 
    1173               2 : CPLErr GDALColorReliefDataset::GetGeoTransform( double * padfGeoTransform )
    1174                 : {
    1175               2 :     return GDALGetGeoTransform(hSrcDS, padfGeoTransform);
    1176                 : }
    1177                 : 
    1178               2 : const char *GDALColorReliefDataset::GetProjectionRef()
    1179                 : {
    1180               2 :     return GDALGetProjectionRef(hSrcDS);
    1181                 : }
    1182                 : 
    1183                 : GDALColorReliefRasterBand::GDALColorReliefRasterBand(
    1184               6 :                                     GDALColorReliefDataset * poDS, int nBand)
    1185                 : {
    1186               6 :     this->poDS = poDS;
    1187               6 :     this->nBand = nBand;
    1188               6 :     eDataType = GDT_Byte;
    1189               6 :     GDALGetBlockSize( poDS->hSrcBand, &nBlockXSize, &nBlockYSize);
    1190               6 : }
    1191                 : 
    1192                 : CPLErr GDALColorReliefRasterBand::IReadBlock( int nBlockXOff,
    1193                 :                                               int nBlockYOff,
    1194             387 :                                               void *pImage )
    1195                 : {
    1196             387 :     GDALColorReliefDataset * poGDS = (GDALColorReliefDataset *) poDS;
    1197                 :     int nReqXSize, nReqYSize;
    1198                 : 
    1199             387 :     if ((nBlockXOff + 1) * nBlockXSize >= nRasterXSize)
    1200              27 :         nReqXSize = nRasterXSize - nBlockXOff * nBlockXSize;
    1201                 :     else
    1202             360 :         nReqXSize = nBlockXSize;
    1203                 :         
    1204             387 :     if ((nBlockYOff + 1) * nBlockYSize >= nRasterYSize)
    1205             366 :         nReqYSize = nRasterYSize - nBlockYOff * nBlockYSize;
    1206                 :     else
    1207              21 :         nReqYSize = nBlockYSize;
    1208                 : 
    1209             387 :     int nCount = nReqXSize * nReqYSize;
    1210             387 :     if ( poGDS->nCurBlockXOff != nBlockXOff ||
    1211                 :          poGDS->nCurBlockYOff != nBlockYOff )
    1212                 :     {
    1213             371 :         poGDS->nCurBlockXOff = nBlockXOff;
    1214             371 :         poGDS->nCurBlockYOff = nBlockYOff;
    1215                 :         
    1216                 :         CPLErr eErr = GDALRasterIO( poGDS->hSrcBand,
    1217                 :                             GF_Read,
    1218                 :                             nBlockXOff * nBlockXSize,
    1219                 :                             nBlockYOff * nBlockYSize,
    1220                 :                             nReqXSize, nReqYSize,
    1221                 :                             (poGDS->panSourceBuf) ?
    1222                 :                                 (void*) poGDS->panSourceBuf :
    1223                 :                                 (void* )poGDS->pafSourceBuf,
    1224                 :                             nReqXSize, nReqYSize,
    1225                 :                             (poGDS->panSourceBuf) ? GDT_Int32 : GDT_Float32,
    1226             371 :                             0, 0);
    1227             371 :         if (eErr != CE_None)
    1228                 :         {
    1229               0 :             memset(pImage, 0, nCount);
    1230               0 :             return eErr;
    1231                 :         }
    1232                 :     }
    1233                 : 
    1234                 :     int j;
    1235             387 :     if (poGDS->panSourceBuf)
    1236                 :     {
    1237               0 :         for ( j = 0; j < nCount; j++)
    1238                 :         {
    1239               0 :             int nIndex = poGDS->panSourceBuf[j] + poGDS->nIndexOffset;
    1240               0 :             ((GByte*)pImage)[j] = poGDS->pabyPrecomputed[4*nIndex + nBand-1];
    1241                 :         }
    1242                 :     }
    1243                 :     else
    1244                 :     {
    1245                 :         int anComponents[4];
    1246           88233 :         for ( j = 0; j < nCount; j++)
    1247                 :         {
    1248                 :             GDALColorReliefGetRGBA  (poGDS->pasColorAssociation,
    1249                 :                                      poGDS->nColorAssociation,
    1250                 :                                      poGDS->pafSourceBuf[j],
    1251                 :                                      poGDS->eColorSelectionMode,
    1252                 :                                      &anComponents[0],
    1253                 :                                      &anComponents[1],
    1254                 :                                      &anComponents[2],
    1255           87846 :                                      &anComponents[3]);
    1256           87846 :             ((GByte*)pImage)[j] = (GByte) anComponents[nBand-1];
    1257                 :         }
    1258                 :     }
    1259                 :     
    1260             387 :     return CE_None;
    1261                 : }
    1262                 : 
    1263              12 : GDALColorInterp GDALColorReliefRasterBand::GetColorInterpretation()
    1264                 : {
    1265              12 :     return (GDALColorInterp)(GCI_RedBand + nBand - 1);
    1266                 : }
    1267                 : 
    1268                 : 
    1269                 : CPLErr GDALColorRelief (GDALRasterBandH hSrcBand,
    1270                 :                         GDALRasterBandH hDstBand1,
    1271                 :                         GDALRasterBandH hDstBand2,
    1272                 :                         GDALRasterBandH hDstBand3,
    1273                 :                         GDALRasterBandH hDstBand4,
    1274                 :                         const char* pszColorFilename,
    1275                 :                         ColorSelectionMode eColorSelectionMode,
    1276                 :                         GDALProgressFunc pfnProgress,
    1277               3 :                         void * pProgressData)
    1278                 : {
    1279                 :     CPLErr eErr;
    1280                 :     
    1281               3 :     if (hSrcBand == NULL || hDstBand1 == NULL || hDstBand2 == NULL ||
    1282                 :         hDstBand3 == NULL)
    1283               0 :         return CE_Failure;
    1284                 : 
    1285               3 :     int nColorAssociation = 0;
    1286                 :     ColorAssociation* pasColorAssociation =
    1287                 :             GDALColorReliefParseColorFile(hSrcBand, pszColorFilename,
    1288               3 :                                           &nColorAssociation);
    1289               3 :     if (pasColorAssociation == NULL)
    1290               0 :         return CE_Failure;
    1291                 : 
    1292               3 :     int nXSize = GDALGetRasterBandXSize(hSrcBand);
    1293               3 :     int nYSize = GDALGetRasterBandYSize(hSrcBand);
    1294                 : 
    1295               3 :     if (pfnProgress == NULL)
    1296               0 :         pfnProgress = GDALDummyProgress;
    1297                 :         
    1298               3 :     int nR = 0, nG = 0, nB = 0, nA = 0;
    1299                 :     
    1300                 : /* -------------------------------------------------------------------- */
    1301                 : /*      Precompute the map from values to RGBA quadruplets              */
    1302                 : /*      for GDT_Byte, GDT_Int16 or GDT_UInt16                           */
    1303                 : /* -------------------------------------------------------------------- */
    1304               3 :     int nIndexOffset = 0;
    1305                 :     GByte* pabyPrecomputed =
    1306                 :         GDALColorReliefPrecompute(hSrcBand,
    1307                 :                                   pasColorAssociation,
    1308                 :                                   nColorAssociation,
    1309                 :                                   eColorSelectionMode,
    1310               3 :                                   &nIndexOffset);
    1311                 : 
    1312                 : /* -------------------------------------------------------------------- */
    1313                 : /*      Initialize progress counter.                                    */
    1314                 : /* -------------------------------------------------------------------- */
    1315                 : 
    1316               3 :     float* pafSourceBuf = NULL;
    1317               3 :     int* panSourceBuf = NULL;
    1318               3 :     if (pabyPrecomputed)
    1319               0 :         panSourceBuf = (int *) CPLMalloc(sizeof(int)*nXSize);
    1320                 :     else
    1321               3 :         pafSourceBuf = (float *) CPLMalloc(sizeof(float)*nXSize);
    1322               3 :     GByte* pabyDestBuf1  = (GByte*) CPLMalloc( 4 * nXSize );
    1323               3 :     GByte* pabyDestBuf2  =  pabyDestBuf1 + nXSize;
    1324               3 :     GByte* pabyDestBuf3  =  pabyDestBuf2 + nXSize;
    1325               3 :     GByte* pabyDestBuf4  =  pabyDestBuf3 + nXSize;
    1326                 :     int i, j;
    1327                 : 
    1328               3 :     if( !pfnProgress( 0.0, NULL, pProgressData ) )
    1329                 :     {
    1330               0 :         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    1331               0 :         eErr = CE_Failure;
    1332               0 :         goto end;
    1333                 :     }
    1334                 : 
    1335             366 :     for ( i = 0; i < nYSize; i++)
    1336                 :     {
    1337                 :         /* Read source buffer */
    1338                 :         eErr = GDALRasterIO(   hSrcBand,
    1339                 :                         GF_Read,
    1340                 :                         0, i,
    1341                 :                         nXSize, 1,
    1342                 :                         (panSourceBuf) ? (void*) panSourceBuf : (void* )pafSourceBuf,
    1343                 :                         nXSize, 1,
    1344                 :                         (panSourceBuf) ? GDT_Int32 : GDT_Float32,
    1345             363 :                         0, 0);
    1346             363 :         if (eErr != CE_None)
    1347               0 :             goto end;
    1348                 : 
    1349             363 :         if (panSourceBuf)
    1350                 :         {
    1351               0 :             for ( j = 0; j < nXSize; j++)
    1352                 :             {
    1353               0 :                 int nIndex = panSourceBuf[j] + nIndexOffset;
    1354               0 :                 pabyDestBuf1[j] = pabyPrecomputed[4 * nIndex];
    1355               0 :                 pabyDestBuf2[j] = pabyPrecomputed[4 * nIndex + 1];
    1356               0 :                 pabyDestBuf3[j] = pabyPrecomputed[4 * nIndex + 2];
    1357               0 :                 pabyDestBuf4[j] = pabyPrecomputed[4 * nIndex + 3];
    1358                 :             }
    1359                 :         }
    1360                 :         else
    1361                 :         {
    1362           44286 :             for ( j = 0; j < nXSize; j++)
    1363                 :             {
    1364                 :                 GDALColorReliefGetRGBA  (pasColorAssociation,
    1365                 :                                          nColorAssociation,
    1366                 :                                          pafSourceBuf[j],
    1367                 :                                          eColorSelectionMode,
    1368                 :                                          &nR,
    1369                 :                                          &nG,
    1370                 :                                          &nB,
    1371           43923 :                                          &nA);
    1372           43923 :                 pabyDestBuf1[j] = (GByte) nR;
    1373           43923 :                 pabyDestBuf2[j] = (GByte) nG;
    1374           43923 :                 pabyDestBuf3[j] = (GByte) nB;
    1375           43923 :                 pabyDestBuf4[j] = (GByte) nA;
    1376                 :             }
    1377                 :         }
    1378                 :         
    1379                 :         /* -----------------------------------------
    1380                 :          * Write Line to Raster
    1381                 :          */
    1382                 :         eErr = GDALRasterIO(hDstBand1,
    1383                 :                       GF_Write,
    1384                 :                       0, i, nXSize,
    1385             363 :                       1, pabyDestBuf1, nXSize, 1, GDT_Byte, 0, 0);
    1386             363 :         if (eErr != CE_None)
    1387               0 :             goto end;
    1388                 : 
    1389                 :         eErr = GDALRasterIO(hDstBand2,
    1390                 :                       GF_Write,
    1391                 :                       0, i, nXSize,
    1392             363 :                       1, pabyDestBuf2, nXSize, 1, GDT_Byte, 0, 0);
    1393             363 :         if (eErr != CE_None)
    1394               0 :             goto end;
    1395                 :             
    1396                 :         eErr = GDALRasterIO(hDstBand3,
    1397                 :                       GF_Write,
    1398                 :                       0, i, nXSize,
    1399             363 :                       1, pabyDestBuf3, nXSize, 1, GDT_Byte, 0, 0);
    1400             363 :         if (eErr != CE_None)
    1401               0 :             goto end;
    1402                 :             
    1403             363 :         if (hDstBand4)
    1404                 :         {
    1405                 :             eErr = GDALRasterIO(hDstBand4,
    1406                 :                         GF_Write,
    1407                 :                         0, i, nXSize,
    1408               0 :                         1, pabyDestBuf4, nXSize, 1, GDT_Byte, 0, 0);
    1409               0 :             if (eErr != CE_None)
    1410               0 :                 goto end;
    1411                 :         }
    1412                 : 
    1413             363 :         if( !pfnProgress( 1.0 * (i+1) / nYSize, NULL, pProgressData ) )
    1414                 :         {
    1415               0 :             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    1416               0 :             eErr = CE_Failure;
    1417               0 :             goto end;
    1418                 :         }
    1419                 :     }
    1420               3 :     pfnProgress( 1.0, NULL, pProgressData );
    1421               3 :     eErr = CE_None;
    1422                 : 
    1423               3 : end:
    1424               3 :     VSIFree(pabyPrecomputed);
    1425               3 :     CPLFree(pafSourceBuf);
    1426               3 :     CPLFree(panSourceBuf);
    1427               3 :     CPLFree(pabyDestBuf1);
    1428               3 :     CPLFree(pasColorAssociation);
    1429                 : 
    1430               3 :     return eErr;
    1431                 : }
    1432                 : 
    1433                 : /************************************************************************/
    1434                 : /*                     GDALGenerateVRTColorRelief()                     */
    1435                 : /************************************************************************/
    1436                 : 
    1437                 : CPLErr GDALGenerateVRTColorRelief(const char* pszDstFilename,
    1438                 :                                GDALDatasetH hSrcDataset,
    1439                 :                                GDALRasterBandH hSrcBand,
    1440                 :                                const char* pszColorFilename,
    1441                 :                                ColorSelectionMode eColorSelectionMode,
    1442               2 :                                int bAddAlpha)
    1443                 : {
    1444                 : 
    1445               2 :     int nColorAssociation = 0;
    1446                 :     ColorAssociation* pasColorAssociation =
    1447                 :             GDALColorReliefParseColorFile(hSrcBand, pszColorFilename,
    1448               2 :                                           &nColorAssociation);
    1449               2 :     if (pasColorAssociation == NULL)
    1450               0 :         return CE_Failure;
    1451                 : 
    1452               2 :     int nXSize = GDALGetRasterBandXSize(hSrcBand);
    1453               2 :     int nYSize = GDALGetRasterBandYSize(hSrcBand);
    1454                 : 
    1455               2 :     FILE* fp = VSIFOpenL(pszDstFilename, "wt");
    1456               2 :     if (fp == NULL)
    1457                 :     {
    1458               0 :         CPLFree(pasColorAssociation);
    1459               0 :         return CE_Failure;
    1460                 :     }
    1461                 : 
    1462               2 :     VSIFPrintfL(fp, "<VRTDataset rasterXSize=\"%d\" rasterYSize=\"%d\">\n", nXSize, nYSize);
    1463               2 :     const char* pszProjectionRef = GDALGetProjectionRef(hSrcDataset);
    1464               2 :     if (pszProjectionRef && pszProjectionRef[0] != '\0')
    1465                 :     {
    1466               2 :         char* pszEscapedString = CPLEscapeString(pszProjectionRef, -1, CPLES_XML);
    1467               2 :         VSIFPrintfL(fp, "  <SRS>%s</SRS>\n", pszEscapedString);
    1468               2 :         VSIFree(pszEscapedString);
    1469                 :     }
    1470                 :     double adfGT[6];
    1471               2 :     if (GDALGetGeoTransform(hSrcDataset, adfGT) == CE_None)
    1472                 :     {
    1473                 :         VSIFPrintfL(fp, "  <GeoTransform> %.16g, %.16g, %.16g, "
    1474                 :                         "%.16g, %.16g, %.16g</GeoTransform>\n",
    1475               2 :                         adfGT[0], adfGT[1], adfGT[2], adfGT[3], adfGT[4], adfGT[5]);
    1476                 :     }
    1477               2 :     int nBands = 3 + (bAddAlpha ? 1 : 0);
    1478                 :     int iBand;
    1479                 : 
    1480                 :     int nBlockXSize, nBlockYSize;
    1481               2 :     GDALGetBlockSize(hSrcBand, &nBlockXSize, &nBlockYSize);
    1482                 :     
    1483                 :     int bRelativeToVRT;
    1484               2 :     CPLString osPath = CPLGetPath(pszDstFilename);
    1485                 :     char* pszSourceFilename = CPLStrdup(
    1486                 :         CPLExtractRelativePath( osPath.c_str(), GDALGetDescription(hSrcDataset), 
    1487               2 :                                 &bRelativeToVRT ));
    1488                 : 
    1489               8 :     for(iBand = 0; iBand < nBands; iBand++)
    1490                 :     {
    1491               6 :         VSIFPrintfL(fp, "  <VRTRasterBand dataType=\"Byte\" band=\"%d\">\n", iBand + 1);
    1492                 :         VSIFPrintfL(fp, "    <ColorInterp>%s</ColorInterp>\n",
    1493               6 :                     GDALGetColorInterpretationName((GDALColorInterp)(GCI_RedBand + iBand)));
    1494               6 :         VSIFPrintfL(fp, "    <ComplexSource>\n");
    1495                 :         VSIFPrintfL(fp, "      <SourceFilename relativeToVRT=\"%d\">%s</SourceFilename>\n",
    1496               6 :                         bRelativeToVRT, pszSourceFilename);
    1497               6 :         VSIFPrintfL(fp, "      <SourceBand>%d</SourceBand>\n", GDALGetBandNumber(hSrcBand));
    1498                 :         VSIFPrintfL(fp, "      <SourceProperties RasterXSize=\"%d\" "
    1499                 :                         "RasterYSize=\"%d\" DataType=\"%s\" "
    1500                 :                         "BlockXSize=\"%d\" BlockYSize=\"%d\"/>\n",
    1501                 :                         nXSize, nYSize,
    1502                 :                         GDALGetDataTypeName(GDALGetRasterDataType(hSrcBand)),
    1503               6 :                         nBlockXSize, nBlockYSize);
    1504                 :         VSIFPrintfL(fp, "      <SrcRect xOff=\"0\" yOff=\"0\" xSize=\"%d\" ySize=\"%d\"/>\n",
    1505               6 :                         nXSize, nYSize);
    1506                 :         VSIFPrintfL(fp, "      <DstRect xOff=\"0\" yOff=\"0\" xSize=\"%d\" ySize=\"%d\"/>\n",
    1507               6 :                         nXSize, nYSize);
    1508                 : 
    1509               6 :         VSIFPrintfL(fp, "      <LUT>");
    1510                 :         int iColor;
    1511                 : #define EPSILON 1e-8
    1512              48 :         for(iColor=0;iColor<nColorAssociation;iColor++)
    1513                 :         {
    1514              42 :             if (eColorSelectionMode == COLOR_SELECTION_NEAREST_ENTRY)
    1515                 :             {
    1516              21 :                 if (iColor > 1)
    1517              15 :                     VSIFPrintfL(fp, ",");
    1518                 :             }
    1519              21 :             else if (iColor > 0)
    1520              18 :                 VSIFPrintfL(fp, ",");
    1521                 : 
    1522              42 :             double dfVal = pasColorAssociation[iColor].dfVal;
    1523                 : 
    1524              42 :             if (eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY)
    1525                 :             {
    1526               0 :                 VSIFPrintfL(fp, "%.12g:0,", dfVal - EPSILON);
    1527                 :             }
    1528              42 :             else if (iColor > 0 &&
    1529                 :                      eColorSelectionMode == COLOR_SELECTION_NEAREST_ENTRY)
    1530                 :             {
    1531              18 :                 double dfMidVal = (dfVal + pasColorAssociation[iColor-1].dfVal) / 2;
    1532                 :                 VSIFPrintfL(fp, "%.12g:%d", dfMidVal - EPSILON,
    1533                 :                         (iBand == 0) ? pasColorAssociation[iColor-1].nR :
    1534                 :                         (iBand == 1) ? pasColorAssociation[iColor-1].nG :
    1535                 :                         (iBand == 2) ? pasColorAssociation[iColor-1].nB :
    1536              18 :                                        pasColorAssociation[iColor-1].nA);
    1537                 :                 VSIFPrintfL(fp, ",%.12g:%d", dfMidVal ,
    1538                 :                         (iBand == 0) ? pasColorAssociation[iColor].nR :
    1539                 :                         (iBand == 1) ? pasColorAssociation[iColor].nG :
    1540                 :                         (iBand == 2) ? pasColorAssociation[iColor].nB :
    1541              18 :                                        pasColorAssociation[iColor].nA);
    1542                 : 
    1543                 :             }
    1544                 : 
    1545              42 :             if (eColorSelectionMode != COLOR_SELECTION_NEAREST_ENTRY)
    1546                 :             {
    1547              21 :                 if (dfVal != (double)(int)dfVal)
    1548               0 :                     VSIFPrintfL(fp, "%.12g", dfVal);
    1549                 :                 else
    1550              21 :                     VSIFPrintfL(fp, "%d", (int)dfVal);
    1551                 :                 VSIFPrintfL(fp, ":%d",
    1552                 :                             (iBand == 0) ? pasColorAssociation[iColor].nR :
    1553                 :                             (iBand == 1) ? pasColorAssociation[iColor].nG :
    1554                 :                             (iBand == 2) ? pasColorAssociation[iColor].nB :
    1555              21 :                                            pasColorAssociation[iColor].nA);
    1556                 :             }
    1557                 : 
    1558              42 :             if (eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY)
    1559                 :             {
    1560               0 :                 VSIFPrintfL(fp, ",%.12g:0", dfVal + EPSILON);
    1561                 :             }
    1562                 : 
    1563                 :         }
    1564               6 :         VSIFPrintfL(fp, "</LUT>\n");
    1565                 : 
    1566               6 :         VSIFPrintfL(fp, "    </ComplexSource>\n");
    1567               6 :         VSIFPrintfL(fp, "  </VRTRasterBand>\n");
    1568                 :     }
    1569                 : 
    1570               2 :     CPLFree(pszSourceFilename);
    1571                 : 
    1572               2 :     VSIFPrintfL(fp, "</VRTDataset>\n");
    1573                 : 
    1574               2 :     VSIFCloseL(fp);
    1575                 : 
    1576               2 :     CPLFree(pasColorAssociation);
    1577                 : 
    1578               2 :     return CE_None;
    1579                 : }
    1580                 : 
    1581                 : 
    1582                 : /************************************************************************/
    1583                 : /*                         GDALTRIAlg()                                 */
    1584                 : /************************************************************************/
    1585                 : 
    1586               0 : float GDALTRIAlg (float* afWin, float fDstNoDataValue, void* pData)
    1587                 : {
    1588                 :     // Terrain Ruggedness is average difference in height
    1589                 :     return (fabs(afWin[0]-afWin[4]) +
    1590                 :             fabs(afWin[1]-afWin[4]) +
    1591                 :             fabs(afWin[2]-afWin[4]) +
    1592                 :             fabs(afWin[3]-afWin[4]) +
    1593                 :             fabs(afWin[5]-afWin[4]) +
    1594                 :             fabs(afWin[6]-afWin[4]) +
    1595                 :             fabs(afWin[7]-afWin[4]) +
    1596               0 :             fabs(afWin[8]-afWin[4]))/8;
    1597                 : }
    1598                 : 
    1599                 : 
    1600                 : /************************************************************************/
    1601                 : /*                         GDALTPIAlg()                                 */
    1602                 : /************************************************************************/
    1603                 : 
    1604               0 : float GDALTPIAlg (float* afWin, float fDstNoDataValue, void* pData)
    1605                 : {
    1606                 :     // Terrain Position is the difference between
    1607                 :     // The central cell and the mean of the surrounding cells
    1608                 :     return afWin[4] - 
    1609                 :             ((afWin[0]+
    1610                 :               afWin[1]+
    1611                 :               afWin[2]+
    1612                 :               afWin[3]+
    1613                 :               afWin[5]+
    1614                 :               afWin[6]+
    1615                 :               afWin[7]+
    1616               0 :               afWin[8])/8);
    1617                 : }
    1618                 : 
    1619                 : /************************************************************************/
    1620                 : /*                     GDALRoughnessAlg()                               */
    1621                 : /************************************************************************/
    1622                 : 
    1623               0 : float GDALRoughnessAlg (float* afWin, float fDstNoDataValue, void* pData)
    1624                 : {
    1625                 :     // Roughness is the largest difference
    1626                 :     //  between any two cells
    1627                 : 
    1628               0 :     float pafRoughnessMin = afWin[0];
    1629               0 :     float pafRoughnessMax = afWin[0];
    1630                 : 
    1631               0 :     for ( int k = 1; k < 9; k++)
    1632                 :     {
    1633               0 :         if (afWin[k] > pafRoughnessMax)
    1634                 :         {
    1635               0 :             pafRoughnessMax=afWin[k];
    1636                 :         }
    1637               0 :         if (afWin[k] < pafRoughnessMin)
    1638                 :         {
    1639               0 :             pafRoughnessMin=afWin[k];
    1640                 :         }
    1641                 :     }
    1642               0 :     return pafRoughnessMax - pafRoughnessMin;
    1643                 : }
    1644                 : 
    1645                 : /************************************************************************/
    1646                 : /* ==================================================================== */
    1647                 : /*                       GDALGeneric3x3Dataset                        */
    1648                 : /* ==================================================================== */
    1649                 : /************************************************************************/
    1650                 : 
    1651                 : class GDALGeneric3x3RasterBand;
    1652                 : 
    1653                 : class GDALGeneric3x3Dataset : public GDALDataset
    1654                 : {
    1655                 :     friend class GDALGeneric3x3RasterBand;
    1656                 : 
    1657                 :     GDALGeneric3x3ProcessingAlg pfnAlg;
    1658                 :     void*              pAlgData;
    1659                 :     GDALDatasetH       hSrcDS;
    1660                 :     GDALRasterBandH    hSrcBand;
    1661                 :     float*             apafSourceBuf[3];
    1662                 :     int                bDstHasNoData;
    1663                 :     double             dfDstNoDataValue;
    1664                 :     int                nCurLine;
    1665                 :     int                bComputeAtEdges;
    1666                 : 
    1667                 :   public:
    1668                 :                         GDALGeneric3x3Dataset(GDALDatasetH hSrcDS,
    1669                 :                                               GDALRasterBandH hSrcBand,
    1670                 :                                               GDALDataType eDstDataType,
    1671                 :                                               int bDstHasNoData,
    1672                 :                                               double dfDstNoDataValue,
    1673                 :                                               GDALGeneric3x3ProcessingAlg pfnAlg,
    1674                 :                                               void* pAlgData,
    1675                 :                                               int bComputeAtEdges);
    1676                 :                        ~GDALGeneric3x3Dataset();
    1677                 : 
    1678                 :     CPLErr      GetGeoTransform( double * padfGeoTransform );
    1679                 :     const char *GetProjectionRef();
    1680                 : };
    1681                 : 
    1682                 : /************************************************************************/
    1683                 : /* ==================================================================== */
    1684                 : /*                    GDALGeneric3x3RasterBand                       */
    1685                 : /* ==================================================================== */
    1686                 : /************************************************************************/
    1687                 : 
    1688                 : class GDALGeneric3x3RasterBand : public GDALRasterBand
    1689               2 : {
    1690                 :     friend class GDALGeneric3x3Dataset;
    1691                 :     int bSrcHasNoData;
    1692                 :     float fSrcNoDataValue;
    1693                 :     
    1694                 :     void                    InitWidthNoData(void* pImage);
    1695                 :     
    1696                 :   public:
    1697                 :                  GDALGeneric3x3RasterBand( GDALGeneric3x3Dataset *poDS,
    1698                 :                                            GDALDataType eDstDataType );
    1699                 :     
    1700                 :     virtual CPLErr          IReadBlock( int, int, void * );
    1701                 :     virtual double          GetNoDataValue( int* pbHasNoData );
    1702                 : };
    1703                 : 
    1704                 : GDALGeneric3x3Dataset::GDALGeneric3x3Dataset(
    1705                 :                                      GDALDatasetH hSrcDS,
    1706                 :                                      GDALRasterBandH hSrcBand,
    1707                 :                                      GDALDataType eDstDataType,
    1708                 :                                      int bDstHasNoData,
    1709                 :                                      double dfDstNoDataValue,
    1710                 :                                      GDALGeneric3x3ProcessingAlg pfnAlg,
    1711                 :                                      void* pAlgData,
    1712               2 :                                      int bComputeAtEdges)
    1713                 : {
    1714               2 :     this->hSrcDS = hSrcDS;
    1715               2 :     this->hSrcBand = hSrcBand;
    1716               2 :     this->pfnAlg = pfnAlg;
    1717               2 :     this->pAlgData = pAlgData;
    1718               2 :     this->bDstHasNoData = bDstHasNoData;
    1719               2 :     this->dfDstNoDataValue = dfDstNoDataValue;
    1720               2 :     this->bComputeAtEdges = bComputeAtEdges;
    1721                 :     
    1722               2 :     CPLAssert(eDstDataType == GDT_Byte || eDstDataType == GDT_Float32);
    1723                 : 
    1724               2 :     nRasterXSize = GDALGetRasterXSize(hSrcDS);
    1725               2 :     nRasterYSize = GDALGetRasterYSize(hSrcDS);
    1726                 :     
    1727               2 :     SetBand(1, new GDALGeneric3x3RasterBand(this, eDstDataType));
    1728                 :     
    1729               2 :     apafSourceBuf[0] = (float *) CPLMalloc(sizeof(float)*nRasterXSize);
    1730               2 :     apafSourceBuf[1] = (float *) CPLMalloc(sizeof(float)*nRasterXSize);
    1731               2 :     apafSourceBuf[2] = (float *) CPLMalloc(sizeof(float)*nRasterXSize);
    1732                 : 
    1733               2 :     nCurLine = -1;
    1734               2 : }
    1735                 : 
    1736               2 : GDALGeneric3x3Dataset::~GDALGeneric3x3Dataset()
    1737                 : {
    1738               2 :     CPLFree(apafSourceBuf[0]);
    1739               2 :     CPLFree(apafSourceBuf[1]);
    1740               2 :     CPLFree(apafSourceBuf[2]);
    1741               2 : }
    1742                 : 
    1743               2 : CPLErr GDALGeneric3x3Dataset::GetGeoTransform( double * padfGeoTransform )
    1744                 : {
    1745               2 :     return GDALGetGeoTransform(hSrcDS, padfGeoTransform);
    1746                 : }
    1747                 : 
    1748               2 : const char *GDALGeneric3x3Dataset::GetProjectionRef()
    1749                 : {
    1750               2 :     return GDALGetProjectionRef(hSrcDS);
    1751                 : }
    1752                 : 
    1753                 : GDALGeneric3x3RasterBand::GDALGeneric3x3RasterBand(GDALGeneric3x3Dataset *poDS,
    1754               2 :                                                    GDALDataType eDstDataType)
    1755                 : {
    1756               2 :     this->poDS = poDS;
    1757               2 :     this->nBand = 1;
    1758               2 :     eDataType = eDstDataType;
    1759               2 :     nBlockXSize = poDS->GetRasterXSize();
    1760               2 :     nBlockYSize = 1;
    1761                 : 
    1762               2 :     bSrcHasNoData = FALSE;
    1763                 :     fSrcNoDataValue = (float)GDALGetRasterNoDataValue(poDS->hSrcBand,
    1764               2 :                                                       &bSrcHasNoData);
    1765               2 : }
    1766                 : 
    1767               2 : void   GDALGeneric3x3RasterBand::InitWidthNoData(void* pImage)
    1768                 : {
    1769                 :     int j;
    1770               2 :     GDALGeneric3x3Dataset * poGDS = (GDALGeneric3x3Dataset *) poDS;
    1771               2 :     if (eDataType == GDT_Byte)
    1772                 :     {
    1773             244 :         for(j=0;j<nBlockXSize;j++)
    1774             242 :             ((GByte*)pImage)[j] = (GByte) poGDS->dfDstNoDataValue;
    1775                 :     }
    1776                 :     else
    1777                 :     {
    1778               0 :         for(j=0;j<nBlockXSize;j++)
    1779               0 :             ((float*)pImage)[j] = (float) poGDS->dfDstNoDataValue;
    1780                 :     }
    1781               2 : }
    1782                 : 
    1783                 : CPLErr GDALGeneric3x3RasterBand::IReadBlock( int nBlockXOff,
    1784                 :                                              int nBlockYOff,
    1785             242 :                                              void *pImage )
    1786                 : {
    1787                 :     int i, j;
    1788                 :     float fVal;
    1789             242 :     GDALGeneric3x3Dataset * poGDS = (GDALGeneric3x3Dataset *) poDS;
    1790                 : 
    1791             361 :     if (poGDS->bComputeAtEdges && nRasterXSize >= 2 && nRasterYSize >= 2)
    1792                 :     {
    1793             121 :         if (nBlockYOff == 0)
    1794                 :         {
    1795               3 :             for(i=0;i<2;i++)
    1796                 :             {
    1797                 :                 CPLErr eErr = GDALRasterIO( poGDS->hSrcBand,
    1798                 :                                     GF_Read,
    1799                 :                                     0, i, nBlockXSize, 1,
    1800                 :                                     poGDS->apafSourceBuf[i+1],
    1801                 :                                     nBlockXSize, 1,
    1802                 :                                     GDT_Float32,
    1803               2 :                                     0, 0);
    1804               2 :                 if (eErr != CE_None)
    1805                 :                 {
    1806               0 :                     InitWidthNoData(pImage);
    1807               0 :                     return eErr;
    1808                 :                 }
    1809                 :             }
    1810               1 :             poGDS->nCurLine = 0;
    1811                 : 
    1812             122 :             for (j = 0; j < nRasterXSize; j++)
    1813                 :             {
    1814                 :                 float afWin[9];
    1815             121 :                 int jmin = (j == 0) ? j : j - 1;
    1816             121 :                 int jmax = (j == nRasterXSize - 1) ? j : j + 1;
    1817                 : 
    1818             121 :                 afWin[0] = INTERPOL(poGDS->apafSourceBuf[1][jmin], poGDS->apafSourceBuf[2][jmin]);
    1819             121 :                 afWin[1] = INTERPOL(poGDS->apafSourceBuf[1][j],    poGDS->apafSourceBuf[2][j]);
    1820             121 :                 afWin[2] = INTERPOL(poGDS->apafSourceBuf[1][jmax], poGDS->apafSourceBuf[2][jmax]);
    1821             121 :                 afWin[3] = poGDS->apafSourceBuf[1][jmin];
    1822             121 :                 afWin[4] = poGDS->apafSourceBuf[1][j];
    1823             121 :                 afWin[5] = poGDS->apafSourceBuf[1][jmax];
    1824             121 :                 afWin[6] = poGDS->apafSourceBuf[2][jmin];
    1825             121 :                 afWin[7] = poGDS->apafSourceBuf[2][j];
    1826             121 :                 afWin[8] = poGDS->apafSourceBuf[2][jmax];
    1827                 : 
    1828                 :                 fVal = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
    1829                 :                                     afWin, poGDS->dfDstNoDataValue,
    1830                 :                                     poGDS->pfnAlg,
    1831                 :                                     poGDS->pAlgData,
    1832             121 :                                     poGDS->bComputeAtEdges);
    1833                 : 
    1834             121 :                 if (eDataType == GDT_Byte)
    1835             121 :                     ((GByte*)pImage)[j] = (GByte) (fVal + 0.5);
    1836                 :                 else
    1837               0 :                     ((float*)pImage)[j] = fVal;
    1838                 :             }
    1839                 : 
    1840               1 :             return CE_None;
    1841                 :         }
    1842             120 :         else if (nBlockYOff == nRasterYSize - 1)
    1843                 :         {
    1844               1 :             if (poGDS->nCurLine != nRasterYSize - 2)
    1845                 :             {
    1846               0 :                 for(i=0;i<2;i++)
    1847                 :                 {
    1848                 :                     CPLErr eErr = GDALRasterIO( poGDS->hSrcBand,
    1849                 :                                         GF_Read,
    1850                 :                                         0, nRasterYSize - 2 + i, nBlockXSize, 1,
    1851                 :                                         poGDS->apafSourceBuf[i+1],
    1852                 :                                         nBlockXSize, 1,
    1853                 :                                         GDT_Float32,
    1854               0 :                                         0, 0);
    1855               0 :                     if (eErr != CE_None)
    1856                 :                     {
    1857               0 :                         InitWidthNoData(pImage);
    1858               0 :                         return eErr;
    1859                 :                     }
    1860                 :                 }
    1861                 :             }
    1862                 : 
    1863             122 :             for (j = 0; j < nRasterXSize; j++)
    1864                 :             {
    1865                 :                 float afWin[9];
    1866             121 :                 int jmin = (j == 0) ? j : j - 1;
    1867             121 :                 int jmax = (j == nRasterXSize - 1) ? j : j + 1;
    1868                 : 
    1869             121 :                 afWin[0] = poGDS->apafSourceBuf[1][jmin];
    1870             121 :                 afWin[1] = poGDS->apafSourceBuf[1][j];
    1871             121 :                 afWin[2] = poGDS->apafSourceBuf[1][jmax];
    1872             121 :                 afWin[3] = poGDS->apafSourceBuf[2][jmin];
    1873             121 :                 afWin[4] = poGDS->apafSourceBuf[2][j];
    1874             121 :                 afWin[5] = poGDS->apafSourceBuf[2][jmax];
    1875             121 :                 afWin[6] = INTERPOL(poGDS->apafSourceBuf[2][jmin], poGDS->apafSourceBuf[1][jmin]);
    1876             121 :                 afWin[7] = INTERPOL(poGDS->apafSourceBuf[2][j],    poGDS->apafSourceBuf[1][j]);
    1877             121 :                 afWin[8] = INTERPOL(poGDS->apafSourceBuf[2][jmax], poGDS->apafSourceBuf[1][jmax]);
    1878                 : 
    1879                 :                 fVal = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
    1880                 :                                     afWin, poGDS->dfDstNoDataValue,
    1881                 :                                     poGDS->pfnAlg,
    1882                 :                                     poGDS->pAlgData,
    1883             121 :                                     poGDS->bComputeAtEdges);
    1884                 : 
    1885             121 :                 if (eDataType == GDT_Byte)
    1886             121 :                     ((GByte*)pImage)[j] = (GByte) (fVal + 0.5);
    1887                 :                 else
    1888               0 :                     ((float*)pImage)[j] = fVal;
    1889                 :             }
    1890                 : 
    1891               1 :             return CE_None;
    1892                 :         }
    1893                 :     }
    1894             121 :     else if ( nBlockYOff == 0 || nBlockYOff == nRasterYSize - 1)
    1895                 :     {
    1896               2 :         InitWidthNoData(pImage);
    1897               2 :         return CE_None;
    1898                 :     }
    1899                 : 
    1900             238 :     if ( poGDS->nCurLine != nBlockYOff )
    1901                 :     {
    1902             238 :         if (poGDS->nCurLine + 1 == nBlockYOff)
    1903                 :         {
    1904             237 :             float* pafTmp =  poGDS->apafSourceBuf[0];
    1905             237 :             poGDS->apafSourceBuf[0] = poGDS->apafSourceBuf[1];
    1906             237 :             poGDS->apafSourceBuf[1] = poGDS->apafSourceBuf[2];
    1907             237 :             poGDS->apafSourceBuf[2] = pafTmp;
    1908                 : 
    1909                 :             CPLErr eErr = GDALRasterIO( poGDS->hSrcBand,
    1910                 :                                     GF_Read,
    1911                 :                                     0, nBlockYOff + 1, nBlockXSize, 1,
    1912                 :                                     poGDS->apafSourceBuf[2],
    1913                 :                                     nBlockXSize, 1,
    1914                 :                                     GDT_Float32,
    1915             237 :                                     0, 0);
    1916                 : 
    1917             237 :             if (eErr != CE_None)
    1918                 :             {
    1919               0 :                 InitWidthNoData(pImage);
    1920               0 :                 return eErr;
    1921                 :             }
    1922                 :         }
    1923                 :         else
    1924                 :         {
    1925               4 :             for(i=0;i<3;i++)
    1926                 :             {
    1927                 :                 CPLErr eErr = GDALRasterIO( poGDS->hSrcBand,
    1928                 :                                     GF_Read,
    1929                 :                                     0, nBlockYOff + i - 1, nBlockXSize, 1,
    1930                 :                                     poGDS->apafSourceBuf[i],
    1931                 :                                     nBlockXSize, 1,
    1932                 :                                     GDT_Float32,
    1933               3 :                                     0, 0);
    1934               3 :                 if (eErr != CE_None)
    1935                 :                 {
    1936               0 :                     InitWidthNoData(pImage);
    1937               0 :                     return eErr;
    1938                 :                 }
    1939                 :             }
    1940                 :         }
    1941                 : 
    1942             238 :         poGDS->nCurLine = nBlockYOff;
    1943                 :     }
    1944                 : 
    1945             357 :     if (poGDS->bComputeAtEdges && nRasterXSize >= 2)
    1946                 :     {
    1947                 :         float afWin[9];
    1948                 : 
    1949             119 :         j = 0;
    1950             119 :         afWin[0] = INTERPOL(poGDS->apafSourceBuf[0][j], poGDS->apafSourceBuf[0][j+1]);
    1951             119 :         afWin[1] = poGDS->apafSourceBuf[0][j];
    1952             119 :         afWin[2] = poGDS->apafSourceBuf[0][j+1];
    1953             119 :         afWin[3] = INTERPOL(poGDS->apafSourceBuf[1][j], poGDS->apafSourceBuf[1][j+1]);
    1954             119 :         afWin[4] = poGDS->apafSourceBuf[1][j];
    1955             119 :         afWin[5] = poGDS->apafSourceBuf[1][j+1];
    1956             119 :         afWin[6] = INTERPOL(poGDS->apafSourceBuf[2][j], poGDS->apafSourceBuf[2][j+1]);
    1957             119 :         afWin[7] = poGDS->apafSourceBuf[2][j];
    1958             119 :         afWin[8] = poGDS->apafSourceBuf[2][j+1];
    1959                 : 
    1960                 :         fVal = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
    1961                 :                                     afWin, poGDS->dfDstNoDataValue,
    1962                 :                                     poGDS->pfnAlg,
    1963                 :                                     poGDS->pAlgData,
    1964             119 :                                     poGDS->bComputeAtEdges);
    1965                 : 
    1966             119 :         if (eDataType == GDT_Byte)
    1967             119 :             ((GByte*)pImage)[j] = (GByte) (fVal + 0.5);
    1968                 :         else
    1969               0 :             ((float*)pImage)[j] = fVal;
    1970                 : 
    1971             119 :         j = nRasterXSize - 1;
    1972                 : 
    1973             119 :         afWin[0] = poGDS->apafSourceBuf[0][j-1];
    1974             119 :         afWin[1] = poGDS->apafSourceBuf[0][j];
    1975             119 :         afWin[2] = INTERPOL(poGDS->apafSourceBuf[0][j], poGDS->apafSourceBuf[0][j-1]);
    1976             119 :         afWin[3] = poGDS->apafSourceBuf[1][j-1];
    1977             119 :         afWin[4] = poGDS->apafSourceBuf[1][j];
    1978             119 :         afWin[5] = INTERPOL(poGDS->apafSourceBuf[1][j], poGDS->apafSourceBuf[1][j-1]);
    1979             119 :         afWin[6] = poGDS->apafSourceBuf[2][j-1];
    1980             119 :         afWin[7] = poGDS->apafSourceBuf[2][j];
    1981             119 :         afWin[8] = INTERPOL(poGDS->apafSourceBuf[2][j], poGDS->apafSourceBuf[2][j-1]);
    1982                 : 
    1983                 :         fVal = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
    1984                 :                                     afWin, poGDS->dfDstNoDataValue,
    1985                 :                                     poGDS->pfnAlg,
    1986                 :                                     poGDS->pAlgData,
    1987             119 :                                     poGDS->bComputeAtEdges);
    1988                 : 
    1989             119 :         if (eDataType == GDT_Byte)
    1990             119 :             ((GByte*)pImage)[j] = (GByte) (fVal + 0.5);
    1991                 :         else
    1992               0 :             ((float*)pImage)[j] = fVal;
    1993                 :     }
    1994                 :     else
    1995                 :     {
    1996             119 :         if (eDataType == GDT_Byte)
    1997                 :         {
    1998             119 :             ((GByte*)pImage)[0] = (GByte) poGDS->dfDstNoDataValue;
    1999             119 :             if (nBlockXSize > 1)
    2000             119 :                 ((GByte*)pImage)[nBlockXSize - 1] = (GByte) poGDS->dfDstNoDataValue;
    2001                 :         }
    2002                 :         else
    2003                 :         {
    2004               0 :             ((float*)pImage)[0] = (float) poGDS->dfDstNoDataValue;
    2005               0 :             if (nBlockXSize > 1)
    2006               0 :                 ((float*)pImage)[nBlockXSize - 1] = (float) poGDS->dfDstNoDataValue;
    2007                 :         }
    2008                 :     }
    2009                 : 
    2010                 : 
    2011           28560 :     for(j=1;j<nBlockXSize - 1;j++)
    2012                 :     {
    2013                 :         float afWin[9];
    2014           28322 :         afWin[0] = poGDS->apafSourceBuf[0][j-1];
    2015           28322 :         afWin[1] = poGDS->apafSourceBuf[0][j];
    2016           28322 :         afWin[2] = poGDS->apafSourceBuf[0][j+1];
    2017           28322 :         afWin[3] = poGDS->apafSourceBuf[1][j-1];
    2018           28322 :         afWin[4] = poGDS->apafSourceBuf[1][j];
    2019           28322 :         afWin[5] = poGDS->apafSourceBuf[1][j+1];
    2020           28322 :         afWin[6] = poGDS->apafSourceBuf[2][j-1];
    2021           28322 :         afWin[7] = poGDS->apafSourceBuf[2][j];
    2022           28322 :         afWin[8] = poGDS->apafSourceBuf[2][j+1];
    2023                 : 
    2024                 :         fVal = ComputeVal(bSrcHasNoData, fSrcNoDataValue,
    2025                 :                                 afWin, poGDS->dfDstNoDataValue,
    2026                 :                                 poGDS->pfnAlg,
    2027                 :                                 poGDS->pAlgData,
    2028           28322 :                                 poGDS->bComputeAtEdges);
    2029                 : 
    2030           28322 :         if (eDataType == GDT_Byte)
    2031           28322 :             ((GByte*)pImage)[j] = (GByte) (fVal + 0.5);
    2032                 :         else
    2033               0 :             ((float*)pImage)[j] = fVal;
    2034                 : 
    2035                 :     }
    2036                 : 
    2037             238 :     return CE_None;
    2038                 : }
    2039                 : 
    2040               8 : double GDALGeneric3x3RasterBand::GetNoDataValue( int* pbHasNoData )
    2041                 : {
    2042               8 :     GDALGeneric3x3Dataset * poGDS = (GDALGeneric3x3Dataset *) poDS;
    2043               8 :     if (pbHasNoData)
    2044               6 :         *pbHasNoData = poGDS->bDstHasNoData;
    2045               8 :     return poGDS->dfDstNoDataValue;
    2046                 : }
    2047                 : 
    2048                 : /************************************************************************/
    2049                 : /*                                main()                                */
    2050                 : /************************************************************************/
    2051                 : 
    2052                 : typedef enum
    2053                 : {
    2054                 :     HILL_SHADE,
    2055                 :     SLOPE,
    2056                 :     ASPECT,
    2057                 :     COLOR_RELIEF,
    2058                 :     TRI,
    2059                 :     TPI,
    2060                 :     ROUGHNESS
    2061                 : } Algorithm;
    2062                 : 
    2063              15 : int main( int argc, char ** argv )
    2064                 : 
    2065                 : {
    2066                 :     Algorithm eUtilityMode;
    2067              15 :     double z = 1.0;
    2068              15 :     double scale = 1.0;
    2069              15 :     double az = 315.0;
    2070              15 :     double alt = 45.0;
    2071                 :     // 0 = 'percent' or 1 = 'degrees'
    2072              15 :     int slopeFormat = 1; 
    2073              15 :     int bAddAlpha = FALSE;
    2074              15 :     int bZeroForFlat = FALSE;
    2075              15 :     int bAngleAsAzimuth = TRUE;
    2076              15 :     ColorSelectionMode eColorSelectionMode = COLOR_SELECTION_INTERPOLATE;
    2077                 :     
    2078              15 :     int nBand = 1;
    2079                 :     double  adfGeoTransform[6];
    2080                 : 
    2081              15 :     const char *pszSrcFilename = NULL;
    2082              15 :     const char *pszDstFilename = NULL;
    2083              15 :     const char *pszColorFilename = NULL;
    2084              15 :     const char *pszFormat = "GTiff";
    2085              15 :     char **papszCreateOptions = NULL;
    2086                 :     
    2087              15 :     GDALDatasetH hSrcDataset = NULL;
    2088              15 :     GDALDatasetH hDstDataset = NULL;
    2089              15 :     GDALRasterBandH hSrcBand = NULL;
    2090              15 :     GDALRasterBandH hDstBand = NULL;
    2091              15 :     GDALDriverH hDriver = NULL;
    2092                 : 
    2093              15 :     GDALProgressFunc pfnProgress = GDALTermProgress;
    2094                 :     
    2095              15 :     int nXSize = 0;
    2096              15 :     int nYSize = 0;
    2097                 :     
    2098              15 :     int bComputeAtEdges = FALSE;
    2099              15 :     int bZevenbergenThorne = FALSE;
    2100                 :     
    2101                 :     /* Check strict compilation and runtime library version as we use C++ API */
    2102              15 :     if (! GDAL_CHECK_VERSION(argv[0]))
    2103               0 :         exit(1);
    2104                 : 
    2105              15 :     argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
    2106              15 :     if( argc < 2 )
    2107                 :     {
    2108               0 :         fprintf(stderr, "Not enough arguments\n");
    2109               0 :         Usage();
    2110               0 :         exit( 1 );
    2111                 :     }
    2112                 : 
    2113              15 :     if( EQUAL(argv[1], "--utility_version") || EQUAL(argv[1], "--utility-version") )
    2114                 :     {
    2115                 :         printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
    2116               1 :                 argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
    2117               1 :         return 0;
    2118                 :     }
    2119              19 :     else if ( EQUAL(argv[1], "shade") || EQUAL(argv[1], "hillshade") )
    2120                 :     {
    2121               5 :         eUtilityMode = HILL_SHADE;
    2122                 :     }
    2123               9 :     else if ( EQUAL(argv[1], "slope") )
    2124                 :     {
    2125               1 :         eUtilityMode = SLOPE;
    2126                 :     }
    2127               8 :     else if ( EQUAL(argv[1], "aspect") )
    2128                 :     {
    2129               1 :         eUtilityMode = ASPECT;
    2130                 :     }
    2131               7 :     else if ( EQUAL(argv[1], "color-relief") )
    2132                 :     {
    2133               7 :         eUtilityMode = COLOR_RELIEF;
    2134                 :     }
    2135               0 :     else if ( EQUAL(argv[1], "TRI") )
    2136                 :     {
    2137               0 :         eUtilityMode = TRI;
    2138                 :     }
    2139               0 :     else if ( EQUAL(argv[1], "TPI") )
    2140                 :     {
    2141               0 :         eUtilityMode = TPI;
    2142                 :     }
    2143               0 :     else if ( EQUAL(argv[1], "roughness") )
    2144                 :     {
    2145               0 :         eUtilityMode = ROUGHNESS;
    2146                 :     }
    2147                 :     else
    2148                 :     {
    2149               0 :         fprintf(stderr, "Missing valid sub-utility mention\n");
    2150               0 :         Usage();
    2151               0 :         exit( 1 );
    2152                 :     }
    2153                 : 
    2154                 : /* -------------------------------------------------------------------- */
    2155                 : /*      Parse arguments.                                                */
    2156                 : /* -------------------------------------------------------------------- */
    2157              72 :     for(int i = 2; i < argc; i++ )
    2158                 :     {
    2159              63 :         if( eUtilityMode == HILL_SHADE && i + 1 < argc &&
    2160                 :             (EQUAL(argv[i], "--z") || EQUAL(argv[i], "-z")))
    2161                 :         {
    2162               5 :             z = atof(argv[++i]);
    2163                 :         }
    2164              53 :         else if ( eUtilityMode == SLOPE && EQUAL(argv[i], "-p"))
    2165                 :         {
    2166               0 :             slopeFormat = 0;
    2167                 :         }
    2168              53 :         else if ( (eUtilityMode == HILL_SHADE || eUtilityMode == SLOPE ||
    2169                 :                    eUtilityMode == ASPECT) && EQUAL(argv[i], "-alg") && i + 1 < argc)
    2170                 :         {
    2171               0 :             i ++;
    2172               0 :             if (EQUAL(argv[i], "ZevenbergenThorne"))
    2173               0 :                 bZevenbergenThorne = TRUE;
    2174               0 :             else if (!EQUAL(argv[i], "Horn"))
    2175                 :             {
    2176               0 :                 fprintf(stderr, "Wrong value for alg : %s\n", argv[i]);
    2177               0 :                 Usage();
    2178                 :             }
    2179                 :         }
    2180              53 :         else if ( eUtilityMode == ASPECT && EQUAL(argv[i], "-trigonometric"))
    2181                 :         {
    2182               0 :             bAngleAsAzimuth = FALSE;
    2183                 :         }
    2184              53 :         else if ( eUtilityMode == ASPECT && EQUAL(argv[i], "-zero_for_flat"))
    2185                 :         {
    2186               0 :             bZeroForFlat = TRUE;
    2187                 :         }
    2188              53 :         else if ( eUtilityMode == COLOR_RELIEF && EQUAL(argv[i], "-exact_color_entry"))
    2189                 :         {
    2190               0 :             eColorSelectionMode = COLOR_SELECTION_EXACT_ENTRY;
    2191                 :         }
    2192              55 :         else if ( eUtilityMode == COLOR_RELIEF && EQUAL(argv[i], "-nearest_color_entry"))
    2193                 :         {
    2194               2 :             eColorSelectionMode = COLOR_SELECTION_NEAREST_ENTRY;
    2195                 :         }
    2196              57 :         else if( i + 1 < argc &&
    2197                 :             (EQUAL(argv[i], "--s") || 
    2198                 :              EQUAL(argv[i], "-s") ||
    2199                 :              EQUAL(argv[i], "--scale") ||
    2200                 :              EQUAL(argv[i], "-scale"))
    2201                 :           )
    2202                 :         {
    2203               6 :             scale = atof(argv[++i]);
    2204                 :         }
    2205              46 :         else if( eUtilityMode == HILL_SHADE && i + 1 < argc &&
    2206                 :             (EQUAL(argv[i], "--az") || 
    2207                 :              EQUAL(argv[i], "-az") ||
    2208                 :              EQUAL(argv[i], "--azimuth") ||
    2209                 :              EQUAL(argv[i], "-azimuth"))
    2210                 :           )
    2211                 :         {
    2212               1 :             az = atof(argv[++i]);
    2213                 :         }
    2214              44 :         else if( eUtilityMode == HILL_SHADE && i + 1 < argc &&
    2215                 :             (EQUAL(argv[i], "--alt") || 
    2216                 :              EQUAL(argv[i], "-alt") ||
    2217                 :              EQUAL(argv[i], "--alt") ||
    2218                 :              EQUAL(argv[i], "-alt"))
    2219                 :           )
    2220                 :         {
    2221               0 :             alt = atof(argv[++i]);
    2222                 :         }
    2223              44 :         else if( eUtilityMode == COLOR_RELIEF &&
    2224                 :                  EQUAL(argv[i], "-alpha"))
    2225                 :         {
    2226               0 :             bAddAlpha = TRUE;
    2227                 :         }
    2228              46 :         else if( eUtilityMode != COLOR_RELIEF &&
    2229                 :                  EQUAL(argv[i], "-compute_edges"))
    2230                 :         {
    2231               2 :             bComputeAtEdges = TRUE;
    2232                 :         }
    2233              42 :         else if( i + 1 < argc &&
    2234                 :             (EQUAL(argv[i], "--b") || 
    2235                 :              EQUAL(argv[i], "-b"))
    2236                 :           )
    2237                 :         {
    2238               0 :             nBand = atoi(argv[++i]);
    2239                 :         }
    2240              42 :         else if ( EQUAL(argv[i], "-q") || EQUAL(argv[i], "-quiet") )
    2241                 :         {
    2242               0 :             pfnProgress = GDALDummyProgress;
    2243                 :         }
    2244              43 :         else if( EQUAL(argv[i],"-co") && i < argc-1 )
    2245                 :         {
    2246               1 :             papszCreateOptions = CSLAddString( papszCreateOptions, argv[++i] );
    2247                 :         }
    2248              47 :         else if( EQUAL(argv[i],"-of") && i < argc-1 )
    2249                 :         {
    2250               6 :             pszFormat = argv[++i];
    2251                 :         }
    2252              35 :         else if( argv[i][0] == '-' )
    2253                 :         {
    2254                 :             fprintf( stderr, "Option %s incomplete, or not recognised.\n\n", 
    2255               0 :                     argv[i] );
    2256               0 :             Usage();
    2257               0 :             GDALDestroyDriverManager();
    2258               0 :             exit( 2 );
    2259                 :         }
    2260              35 :         else if( pszSrcFilename == NULL )
    2261                 :         {
    2262              14 :             pszSrcFilename = argv[i];
    2263                 :         }
    2264              28 :         else if( eUtilityMode == COLOR_RELIEF && pszColorFilename == NULL )
    2265                 :         {
    2266               7 :             pszColorFilename = argv[i];
    2267                 :         }
    2268              14 :         else if( pszDstFilename == NULL )
    2269                 :         {
    2270              14 :             pszDstFilename = argv[i];
    2271                 :         }
    2272                 :         else
    2273               0 :             Usage();
    2274                 :     }
    2275                 : 
    2276              14 :     if( pszSrcFilename == NULL )
    2277                 :     {
    2278               0 :         fprintf( stderr, "Missing source.\n\n" );
    2279               0 :         Usage();
    2280                 :     }
    2281              14 :     if ( eUtilityMode == COLOR_RELIEF && pszColorFilename == NULL )
    2282                 :     {
    2283               0 :         fprintf( stderr, "Missing color file.\n\n" );
    2284               0 :         Usage();
    2285                 :     }
    2286              14 :     if( pszDstFilename == NULL )
    2287                 :     {
    2288               0 :         fprintf( stderr, "Missing destination.\n\n" );
    2289               0 :         Usage();
    2290                 :     }
    2291                 : 
    2292              14 :     GDALAllRegister();
    2293                 : 
    2294                 :     // Open Dataset and get raster band
    2295              14 :     hSrcDataset = GDALOpen( pszSrcFilename, GA_ReadOnly );
    2296                 :     
    2297              14 :     if( hSrcDataset == NULL )
    2298                 :     {
    2299                 :         fprintf( stderr,
    2300                 :                  "GDALOpen failed - %d\n%s\n",
    2301               0 :                  CPLGetLastErrorNo(), CPLGetLastErrorMsg() );
    2302               0 :         GDALDestroyDriverManager();
    2303               0 :         exit( 1 );
    2304                 :     }
    2305                 : 
    2306              14 :     nXSize = GDALGetRasterXSize(hSrcDataset);
    2307              14 :     nYSize = GDALGetRasterYSize(hSrcDataset);
    2308                 : 
    2309              14 :     if( nBand <= 0 || nBand > GDALGetRasterCount(hSrcDataset) )
    2310                 :     {
    2311                 :         fprintf( stderr,
    2312               0 :                  "Unable to fetch band #%d\n", nBand );
    2313               0 :         GDALDestroyDriverManager();
    2314               0 :         exit( 1 );
    2315                 :     }
    2316              14 :     hSrcBand = GDALGetRasterBand( hSrcDataset, nBand );
    2317                 : 
    2318              14 :     GDALGetGeoTransform(hSrcDataset, adfGeoTransform);
    2319                 : 
    2320              14 :     hDriver = GDALGetDriverByName(pszFormat);
    2321              14 :     if( hDriver == NULL 
    2322                 :         || (GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL &&
    2323                 :             GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, NULL ) == NULL))
    2324                 :     {
    2325                 :         int iDr;
    2326                 : 
    2327                 :         fprintf( stderr, "Output driver `%s' not recognised to have\n", 
    2328               0 :                  pszFormat );
    2329                 :         fprintf( stderr, "output support.  The following format drivers are configured\n"
    2330               0 :                 "and support output:\n" );
    2331                 : 
    2332               0 :         for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
    2333                 :         {
    2334               0 :             GDALDriverH hDriver = GDALGetDriver(iDr);
    2335                 : 
    2336               0 :             if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) != NULL ||
    2337                 :                 GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, NULL ) != NULL )
    2338                 :             {
    2339                 :                 printf( "  %s: %s\n",
    2340                 :                         GDALGetDriverShortName( hDriver  ),
    2341               0 :                         GDALGetDriverLongName( hDriver ) );
    2342                 :             }
    2343                 :         }
    2344               0 :         GDALDestroyDriverManager();
    2345               0 :         exit( 1 );
    2346                 :     }
    2347                 : 
    2348              14 :     double dfDstNoDataValue = 0;
    2349              14 :     int bDstHasNoData = FALSE;
    2350              14 :     void* pData = NULL;
    2351              14 :     GDALGeneric3x3ProcessingAlg pfnAlg = NULL;
    2352                 : 
    2353              14 :     if (eUtilityMode == HILL_SHADE)
    2354                 :     {
    2355               5 :         dfDstNoDataValue = 0;
    2356               5 :         bDstHasNoData = TRUE;
    2357                 :         pData = GDALCreateHillshadeData   (adfGeoTransform,
    2358                 :                                            z,
    2359                 :                                            scale,
    2360                 :                                            alt,
    2361                 :                                            az,
    2362               5 :                                            bZevenbergenThorne);
    2363               5 :         if (bZevenbergenThorne)
    2364               0 :             pfnAlg = GDALHillshadeZevenbergenThorneAlg;
    2365                 :         else
    2366               5 :             pfnAlg = GDALHillshadeAlg;
    2367                 :     }
    2368               9 :     else if (eUtilityMode == SLOPE)
    2369                 :     {
    2370               1 :         dfDstNoDataValue = -9999;
    2371               1 :         bDstHasNoData = TRUE;
    2372                 : 
    2373               1 :         pData = GDALCreateSlopeData(adfGeoTransform, scale, slopeFormat);
    2374               1 :         if (bZevenbergenThorne)
    2375               0 :             pfnAlg = GDALSlopeZevenbergenThorneAlg;
    2376                 :         else
    2377               1 :             pfnAlg = GDALSlopeHornAlg;
    2378                 :     }
    2379                 : 
    2380               8 :     else if (eUtilityMode == ASPECT)
    2381                 :     {
    2382               1 :         if (!bZeroForFlat)
    2383                 :         {
    2384               1 :             dfDstNoDataValue = -9999;
    2385               1 :             bDstHasNoData = TRUE;
    2386                 :         }
    2387                 : 
    2388               1 :         pData = GDALCreateAspectData(bAngleAsAzimuth);
    2389               1 :         if (bZevenbergenThorne)
    2390               0 :             pfnAlg = GDALAspectZevenbergenThorneAlg;
    2391                 :         else
    2392               1 :             pfnAlg = GDALAspectAlg;
    2393                 :     }
    2394               7 :     else if (eUtilityMode == TRI)
    2395                 :     {
    2396               0 :         dfDstNoDataValue = -9999;
    2397               0 :         bDstHasNoData = TRUE;
    2398               0 :         pfnAlg = GDALTRIAlg;
    2399                 :     }
    2400               7 :     else if (eUtilityMode == TPI)
    2401                 :     {
    2402               0 :         dfDstNoDataValue = -9999;
    2403               0 :         bDstHasNoData = TRUE;
    2404               0 :         pfnAlg = GDALTPIAlg;
    2405                 :     }
    2406               7 :     else if (eUtilityMode == ROUGHNESS)
    2407                 :     {
    2408               0 :         dfDstNoDataValue = -9999;
    2409               0 :         bDstHasNoData = TRUE;
    2410               0 :         pfnAlg = GDALRoughnessAlg;
    2411                 :     }
    2412                 :     
    2413                 :     GDALDataType eDstDataType = (eUtilityMode == HILL_SHADE ||
    2414                 :                                  eUtilityMode == COLOR_RELIEF) ? GDT_Byte :
    2415              14 :                                                                GDT_Float32;
    2416                 : 
    2417              14 :     if( EQUAL(pszFormat, "VRT") )
    2418                 :     {
    2419               2 :         if (eUtilityMode == COLOR_RELIEF)
    2420                 :         {
    2421                 :             GDALGenerateVRTColorRelief(pszDstFilename,
    2422                 :                                        hSrcDataset,
    2423                 :                                        hSrcBand,
    2424                 :                                        pszColorFilename,
    2425                 :                                        eColorSelectionMode,
    2426               2 :                                        bAddAlpha);
    2427               2 :             GDALClose(hSrcDataset);
    2428                 :         
    2429               2 :             CPLFree(pData);
    2430                 : 
    2431               2 :             GDALDestroyDriverManager();
    2432               2 :             CSLDestroy( argv );
    2433               2 :             CSLDestroy( papszCreateOptions );
    2434                 :         
    2435               2 :             return 0;
    2436                 :         }
    2437                 :         else
    2438                 :         {
    2439               0 :             fprintf(stderr, "VRT driver can only be used with color-relief utility\n");
    2440               0 :             GDALDestroyDriverManager();
    2441                 : 
    2442               0 :             exit(1);
    2443                 :         }
    2444                 :     }
    2445                 :     
    2446              12 :     if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL &&
    2447                 :         GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, NULL ) != NULL)
    2448                 :     {
    2449                 :         GDALDatasetH hIntermediateDataset;
    2450                 :         
    2451               4 :         if (eUtilityMode == COLOR_RELIEF)
    2452                 :             hIntermediateDataset = (GDALDatasetH)
    2453                 :                 new GDALColorReliefDataset (hSrcDataset,
    2454                 :                                             hSrcBand,
    2455                 :                                             pszColorFilename,
    2456                 :                                             eColorSelectionMode,
    2457               2 :                                             bAddAlpha);
    2458                 :         else
    2459                 :             hIntermediateDataset = (GDALDatasetH)
    2460                 :                 new GDALGeneric3x3Dataset(hSrcDataset, hSrcBand,
    2461                 :                                           eDstDataType,
    2462                 :                                           bDstHasNoData,
    2463                 :                                           dfDstNoDataValue,
    2464                 :                                           pfnAlg,
    2465                 :                                           pData,
    2466               2 :                                           bComputeAtEdges);
    2467                 : 
    2468                 :         GDALDatasetH hOutDS = GDALCreateCopy(
    2469                 :                                  hDriver, pszDstFilename, hIntermediateDataset, 
    2470                 :                                  TRUE, papszCreateOptions, 
    2471               4 :                                  pfnProgress, NULL );
    2472                 : 
    2473               4 :         if( hOutDS != NULL )
    2474               4 :             GDALClose( hOutDS );
    2475               4 :         GDALClose(hIntermediateDataset);
    2476               4 :         GDALClose(hSrcDataset);
    2477                 :         
    2478               4 :         CPLFree(pData);
    2479                 : 
    2480               4 :         GDALDestroyDriverManager();
    2481               4 :         CSLDestroy( argv );
    2482               4 :         CSLDestroy( papszCreateOptions );
    2483                 :         
    2484               4 :         return 0;
    2485                 :     }
    2486                 : 
    2487                 :     int nDstBands;
    2488               8 :     if (eUtilityMode == COLOR_RELIEF)
    2489               3 :         nDstBands = (bAddAlpha) ? 4 : 3;
    2490                 :     else
    2491               5 :         nDstBands = 1;
    2492                 : 
    2493                 :     hDstDataset = GDALCreate(   hDriver,
    2494                 :                                 pszDstFilename,
    2495                 :                                 nXSize,
    2496                 :                                 nYSize,
    2497                 :                                 nDstBands,
    2498                 :                                 eDstDataType,
    2499               8 :                                 papszCreateOptions);
    2500                 : 
    2501               8 :     if( hDstDataset == NULL )
    2502                 :     {
    2503                 :         fprintf( stderr,
    2504                 :                  "Unable to create dataset %s %d\n%s\n", pszDstFilename,
    2505               0 :                  CPLGetLastErrorNo(), CPLGetLastErrorMsg() );
    2506               0 :         GDALDestroyDriverManager();
    2507               0 :         exit( 1 );
    2508                 :     }
    2509                 :     
    2510               8 :     hDstBand = GDALGetRasterBand( hDstDataset, 1 );
    2511                 : 
    2512               8 :     GDALSetGeoTransform(hDstDataset, adfGeoTransform);
    2513               8 :     GDALSetProjection(hDstDataset, GDALGetProjectionRef(hSrcDataset));
    2514                 :     
    2515               8 :     if (eUtilityMode == COLOR_RELIEF)
    2516                 :     {
    2517                 :         GDALColorRelief (hSrcBand, 
    2518                 :                          GDALGetRasterBand(hDstDataset, 1),
    2519                 :                          GDALGetRasterBand(hDstDataset, 2),
    2520                 :                          GDALGetRasterBand(hDstDataset, 3),
    2521                 :                          (bAddAlpha) ? GDALGetRasterBand(hDstDataset, 4) : NULL,
    2522                 :                          pszColorFilename,
    2523                 :                          eColorSelectionMode,
    2524               3 :                          pfnProgress, NULL);
    2525                 :     }
    2526                 :     else
    2527                 :     {
    2528               5 :         if (bDstHasNoData)
    2529               5 :             GDALSetRasterNoDataValue(hDstBand, dfDstNoDataValue);
    2530                 :         
    2531                 :         GDALGeneric3x3Processing(hSrcBand, hDstBand,
    2532                 :                                  pfnAlg, pData,
    2533                 :                                  bComputeAtEdges,
    2534               5 :                                  pfnProgress, NULL);
    2535                 :                                     
    2536                 :     }
    2537                 : 
    2538               8 :     GDALClose(hSrcDataset);
    2539               8 :     GDALClose(hDstDataset);
    2540               8 :     CPLFree(pData);
    2541                 : 
    2542               8 :     GDALDestroyDriverManager();
    2543               8 :     CSLDestroy( argv );
    2544               8 :     CSLDestroy( papszCreateOptions );
    2545                 : 
    2546               8 :     return 0;
    2547                 : }
    2548                 : 

Generated by: LTP GCOV extension version 1.5