LCOV - code coverage report
Current view: directory - apps - gdaldem.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 790 546 69.1 %
Date: 2010-01-09 Functions: 40 33 82.5 %

       1                 : /******************************************************************************
       2                 :  * $Id: gdaldem.cpp 18306 2009-12-15 18:57:11Z 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 18306 2009-12-15 18:57:11Z rouault $");
      94                 : 
      95                 : #ifndef M_PI
      96                 : # define M_PI  3.1415926535897932384626433832795
      97                 : #endif
      98                 : 
      99                 : /************************************************************************/
     100                 : /*                               Usage()                                */
     101                 : /************************************************************************/
     102                 : 
     103               0 : static void Usage()
     104                 : 
     105                 : {
     106                 :     printf( " Usage: \n"
     107                 :             " - To generate a shaded relief map from any GDAL-supported elevation raster : \n\n"
     108                 :             "     gdaldem hillshade input_dem output_hillshade \n"
     109                 :             "                 [-z ZFactor (default=1)] [-s scale* (default=1)] \n"
     110                 :             "                 [-az Azimuth (default=315)] [-alt Altitude (default=45)]\n"
     111                 :             "                 [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
     112                 :             "\n"
     113                 :             " - To generates a slope map from any GDAL-supported elevation raster :\n\n"
     114                 :             "     gdaldem slope input_dem output_slope_map \n"
     115                 :             "                 [-p use percent slope (default=degrees)] [-s scale* (default=1)]\n"
     116                 :             "                 [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
     117                 :             "\n"
     118                 :             " - To generate an aspect map from any GDAL-supported elevation raster\n"
     119                 :             "   Outputs a 32-bit float tiff with pixel values from 0-360 indicating azimuth :\n\n"
     120                 :             "     gdaldem aspect input_dem output_aspect_map \n"
     121                 :             "                 [-trigonometric] [-zero_for_flat]\n"
     122                 :             "                 [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
     123                 :             "\n"
     124                 :             " - To generate a color relief map from any GDAL-supported elevation raster\n"
     125                 :             "     gdaldem color-relief input_dem color_text_file output_color_relief_map\n"
     126                 :             "                 [-alpha] [-exact_color_entry | -nearest_color_entry]\n"
     127                 :             "                 [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
     128                 :             "     where color_text_file contains lines of the format \"elevation_value red green blue\"\n"
     129                 :             "\n"
     130                 :             " - To generate a Terrain Ruggedness Index (TRI) map from any GDAL-supported elevation raster\n"
     131                 :             "     gdaldem TRI input_dem output_TRI_map\n"
     132                 :             "                 [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
     133                 :             "\n"
     134                 :             " - To generate a Topographic Position Index (TPI) map from any GDAL-supported elevation raster\n"
     135                 :             "     gdaldem TPI input_dem output_TPI_map\n"
     136                 :             "                 [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
     137                 :             "\n"
     138                 :             " - To generate a roughness map from any GDAL-supported elevation raster\n"
     139                 :             "     gdaldem roughness input_dem output_roughness_map\n"
     140                 :             "                 [-b Band (default=1)] [-of format] [-co \"NAME=VALUE\"]* [-q]\n"
     141                 :             "\n"
     142                 :             " Notes : \n"
     143                 :             "   Scale is the ratio of vertical units to horizontal\n"
     144               0 :             "    for Feet:Latlong use scale=370400, for Meters:LatLong use scale=111120 \n\n");
     145               0 :     exit( 1 );
     146                 : }
     147                 : 
     148                 : /************************************************************************/
     149                 : /*                  GDALGeneric3x3Processing()                          */
     150                 : /************************************************************************/
     151                 : 
     152                 : typedef float (*GDALGeneric3x3ProcessingAlg) (float* pafWindow, float fDstNoDataValue, void* pData);
     153                 : 
     154               3 : CPLErr GDALGeneric3x3Processing  ( GDALRasterBandH hSrcBand,
     155                 :                                    GDALRasterBandH hDstBand,
     156                 :                                    GDALGeneric3x3ProcessingAlg pfnAlg,
     157                 :                                    void* pData,
     158                 :                                    GDALProgressFunc pfnProgress,
     159                 :                                    void * pProgressData)
     160                 : {
     161                 :     CPLErr eErr;
     162                 :     float *pafThreeLineWin; /* 3 line rotating source buffer */
     163                 :     float *pafOutputBuf;     /* 1 line destination buffer */
     164                 :     int i, j;
     165                 : 
     166                 :     int bSrcHasNoData, bDstHasNoData;
     167               3 :     float fSrcNoDataValue = 0.0, fDstNoDataValue = 0.0;
     168                 : 
     169               3 :     int nXSize = GDALGetRasterBandXSize(hSrcBand);
     170               3 :     int nYSize = GDALGetRasterBandYSize(hSrcBand);
     171                 : 
     172               3 :     if (pfnProgress == NULL)
     173               0 :         pfnProgress = GDALDummyProgress;
     174                 : 
     175                 : /* -------------------------------------------------------------------- */
     176                 : /*      Initialize progress counter.                                    */
     177                 : /* -------------------------------------------------------------------- */
     178               3 :     if( !pfnProgress( 0.0, NULL, pProgressData ) )
     179                 :     {
     180               0 :         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
     181               0 :         return CE_Failure;
     182                 :     }
     183                 : 
     184               3 :     pafOutputBuf = (float *) CPLMalloc(sizeof(float)*nXSize);
     185               3 :     pafThreeLineWin  = (float *) CPLMalloc(3*sizeof(float)*(nXSize+1));
     186                 : 
     187               3 :     fSrcNoDataValue = (float) GDALGetRasterNoDataValue(hSrcBand, &bSrcHasNoData);
     188               3 :     fDstNoDataValue = (float) GDALGetRasterNoDataValue(hDstBand, &bDstHasNoData);
     189               3 :     if (!bDstHasNoData)
     190               0 :         fDstNoDataValue = 0.0;
     191                 : 
     192                 :     // Move a 3x3 pafWindow over each cell 
     193                 :     // (where the cell in question is #4)
     194                 :     // 
     195                 :     //      0 1 2
     196                 :     //      3 4 5
     197                 :     //      6 7 8
     198                 : 
     199                 :     /* Preload the first 2 lines */
     200               9 :     for ( i = 0; i < 2 && i < nYSize; i++)
     201                 :     {
     202                 :         GDALRasterIO(   hSrcBand,
     203                 :                         GF_Read,
     204                 :                         0, i,
     205                 :                         nXSize, 1,
     206                 :                         pafThreeLineWin + i * nXSize,
     207                 :                         nXSize, 1,
     208                 :                         GDT_Float32,
     209               6 :                         0, 0);
     210                 :     }
     211                 :     
     212                 :     // Exclude the edges
     213             366 :     for (j = 0; j < nXSize; j++)
     214                 :     {
     215             363 :         pafOutputBuf[j] = fDstNoDataValue;
     216                 :     }
     217                 :     GDALRasterIO(hDstBand, GF_Write,
     218                 :                  0, 0, nXSize, 1,
     219               3 :                  pafOutputBuf, nXSize, 1, GDT_Float32, 0, 0);
     220                 : 
     221               3 :     if (nYSize > 1)
     222                 :     {
     223                 :         GDALRasterIO(hDstBand, GF_Write,
     224                 :                      0, nYSize - 1, nXSize, 1,
     225               3 :                      pafOutputBuf, nXSize, 1, GDT_Float32, 0, 0);
     226                 :     }
     227                 :     
     228               3 :     int nLine1Off = 0*nXSize;
     229               3 :     int nLine2Off = 1*nXSize;
     230               3 :     int nLine3Off = 2*nXSize;
     231                 : 
     232             360 :     for ( i = 1; i < nYSize-1; i++)
     233                 :     {
     234                 :         /* Read third line of the line buffer */
     235                 :         eErr = GDALRasterIO(   hSrcBand,
     236                 :                         GF_Read,
     237                 :                         0, i+1,
     238                 :                         nXSize, 1,
     239                 :                         pafThreeLineWin + nLine3Off,
     240                 :                         nXSize, 1,
     241                 :                         GDT_Float32,
     242             357 :                         0, 0);
     243             357 :         if (eErr != CE_None)
     244               0 :             goto end;
     245                 : 
     246                 :         // Exclude the edges
     247             357 :         pafOutputBuf[0] = fDstNoDataValue;
     248             357 :         if (nXSize > 1)
     249             357 :             pafOutputBuf[nXSize - 1] = fDstNoDataValue;
     250                 :         
     251           42840 :         for (j = 1; j < nXSize - 1; j++)
     252                 :         {
     253                 :             float afWin[9];
     254           42483 :             afWin[0] = pafThreeLineWin[nLine1Off + j-1];
     255           42483 :             afWin[1] = pafThreeLineWin[nLine1Off + j];
     256           42483 :             afWin[2] = pafThreeLineWin[nLine1Off + j+1];
     257           42483 :             afWin[3] = pafThreeLineWin[nLine2Off + j-1];
     258           42483 :             afWin[4] = pafThreeLineWin[nLine2Off + j];
     259           42483 :             afWin[5] = pafThreeLineWin[nLine2Off + j+1];
     260           42483 :             afWin[6] = pafThreeLineWin[nLine3Off + j-1];
     261           42483 :             afWin[7] = pafThreeLineWin[nLine3Off + j];
     262           42483 :             afWin[8] = pafThreeLineWin[nLine3Off + j+1];
     263                 : 
     264          424830 :             if (bSrcHasNoData && (
     265           42483 :                    afWin[0] == fSrcNoDataValue ||
     266           42483 :                    afWin[1] == fSrcNoDataValue ||
     267           42483 :                    afWin[2] == fSrcNoDataValue ||
     268           42483 :                    afWin[3] == fSrcNoDataValue ||
     269           42483 :                    afWin[4] == fSrcNoDataValue ||
     270           42483 :                    afWin[5] == fSrcNoDataValue ||
     271           42483 :                    afWin[6] == fSrcNoDataValue ||
     272           42483 :                    afWin[7] == fSrcNoDataValue ||
     273           42483 :                    afWin[8] == fSrcNoDataValue))
     274                 :             {
     275                 :                 // We have nulls so write nullValue and move on
     276               0 :                 pafOutputBuf[j] = fDstNoDataValue;
     277                 :             }
     278                 :             else
     279                 :             {
     280                 :                 // We have a valid 3x3 window.
     281           42483 :                 pafOutputBuf[j] = pfnAlg(afWin, fDstNoDataValue, pData);
     282                 :             }
     283                 :         }
     284                 : 
     285                 :         /* -----------------------------------------
     286                 :          * Write Line to Raster
     287                 :          */
     288                 :         eErr = GDALRasterIO(hDstBand, GF_Write, 0, i, nXSize, 1,
     289             357 :                      pafOutputBuf, nXSize, 1, GDT_Float32, 0, 0);
     290             357 :         if (eErr != CE_None)
     291               0 :             goto end;
     292                 : 
     293             357 :         if( !pfnProgress( 1.0 * (i+1) / nYSize, NULL, pProgressData ) )
     294                 :         {
     295               0 :             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
     296               0 :             eErr = CE_Failure;
     297               0 :             goto end;
     298                 :         }
     299                 :         
     300             357 :         int nTemp = nLine1Off;
     301             357 :         nLine1Off = nLine2Off;
     302             357 :         nLine2Off = nLine3Off;
     303             357 :         nLine3Off = nTemp;
     304                 :     }
     305                 : 
     306               3 :     pfnProgress( 1.0, NULL, pProgressData );
     307               3 :     eErr = CE_None;
     308                 : 
     309                 : end:
     310               3 :     CPLFree(pafOutputBuf);
     311               3 :     CPLFree(pafThreeLineWin);
     312                 : 
     313               3 :     return eErr;
     314                 : }
     315                 : 
     316                 : 
     317                 : /************************************************************************/
     318                 : /*                         GDALHillshade()                              */
     319                 : /************************************************************************/
     320                 : 
     321                 : typedef struct
     322                 : {
     323                 :     double nsres;
     324                 :     double ewres;
     325                 :     double sin_altRadians;
     326                 :     double cos_altRadians_mul_z_scale_factor;
     327                 :     double azRadians;
     328                 :     double square_z_scale_factor;
     329                 : } GDALHillshadeAlgData;
     330                 : 
     331                 : /* Unoptimized formulas are :
     332                 :     x = psData->z*((afWin[0] + afWin[3] + afWin[3] + afWin[6]) -
     333                 :         (afWin[2] + afWin[5] + afWin[5] + afWin[8])) /
     334                 :         (8.0 * psData->ewres * psData->scale);
     335                 : 
     336                 :     y = psData->z*((afWin[6] + afWin[7] + afWin[7] + afWin[8]) -
     337                 :         (afWin[0] + afWin[1] + afWin[1] + afWin[2])) /
     338                 :         (8.0 * psData->nsres * psData->scale);
     339                 : 
     340                 :     slope = M_PI / 2 - atan(sqrt(x*x + y*y));
     341                 : 
     342                 :     aspect = atan2(x,y);
     343                 : 
     344                 :     cang = sin(alt * degreesToRadians) * sin(slope) +
     345                 :            cos(alt * degreesToRadians) * cos(slope) *
     346                 :            cos(az * degreesToRadians - M_PI/2 - aspect);
     347                 : */
     348                 : 
     349           28322 : float GDALHillshadeAlg (float* afWin, float fDstNoDataValue, void* pData)
     350                 : {
     351           28322 :     GDALHillshadeAlgData* psData = (GDALHillshadeAlgData*)pData;
     352                 :     double x, y, aspect, xx_plus_yy, cang;
     353                 :     
     354                 :     // First Slope ...
     355           84966 :     x = ((afWin[0] + afWin[3] + afWin[3] + afWin[6]) -
     356           84966 :         (afWin[2] + afWin[5] + afWin[5] + afWin[8])) / psData->ewres;
     357                 : 
     358           84966 :     y = ((afWin[6] + afWin[7] + afWin[7] + afWin[8]) -
     359           84966 :         (afWin[0] + afWin[1] + afWin[1] + afWin[2])) / psData->nsres;
     360                 : 
     361           28322 :     xx_plus_yy = x * x + y * y;
     362                 : 
     363                 :     // ... then aspect...
     364           28322 :     aspect = atan2(x,y);
     365                 : 
     366                 :     // ... then the shade value
     367                 :     cang = (psData->sin_altRadians -
     368                 :            psData->cos_altRadians_mul_z_scale_factor * sqrt(xx_plus_yy) *
     369                 :            sin(aspect - psData->azRadians)) /
     370           28322 :            sqrt(1 + psData->square_z_scale_factor * xx_plus_yy);
     371                 : 
     372           28322 :     if (cang <= 0.0) 
     373             202 :         cang = 1.0;
     374                 :     else
     375           28120 :         cang = 1.0 + (254.0 * cang);
     376                 :         
     377           28322 :     return cang;
     378                 : }
     379                 : 
     380               2 : void*  GDALCreateHillshadeData(double* adfGeoTransform,
     381                 :                                double z,
     382                 :                                double scale,
     383                 :                                double alt,
     384                 :                                double az)
     385                 : {
     386                 :     GDALHillshadeAlgData* pData =
     387               2 :         (GDALHillshadeAlgData*)CPLMalloc(sizeof(GDALHillshadeAlgData));
     388                 :         
     389               2 :     const double degreesToRadians = M_PI / 180.0;
     390               2 :     pData->nsres = adfGeoTransform[5];
     391               2 :     pData->ewres = adfGeoTransform[1];
     392               2 :     pData->sin_altRadians = sin(alt * degreesToRadians);
     393               2 :     pData->azRadians = az * degreesToRadians;
     394               2 :     double z_scale_factor = z / (8 * scale);
     395                 :     pData->cos_altRadians_mul_z_scale_factor =
     396               2 :         cos(alt * degreesToRadians) * z_scale_factor;
     397               2 :     pData->square_z_scale_factor = z_scale_factor * z_scale_factor;
     398               2 :     return pData;
     399                 : }
     400                 : 
     401                 : /************************************************************************/
     402                 : /*                         GDALSlope()                                  */
     403                 : /************************************************************************/
     404                 : 
     405                 : typedef struct
     406                 : {
     407                 :     double nsres;
     408                 :     double ewres;
     409                 :     double scale;
     410                 :     int    slopeFormat;
     411                 : } GDALSlopeAlgData;
     412                 : 
     413           14161 : float GDALSlopeAlg (float* afWin, float fDstNoDataValue, void* pData)
     414                 : {
     415           14161 :     const double radiansToDegrees = 180.0 / M_PI;
     416           14161 :     GDALSlopeAlgData* psData = (GDALSlopeAlgData*)pData;
     417                 :     double dx, dy, key;
     418                 :     
     419           42483 :     dx = ((afWin[0] + afWin[3] + afWin[3] + afWin[6]) - 
     420           42483 :           (afWin[2] + afWin[5] + afWin[5] + afWin[8]))/psData->ewres;
     421                 : 
     422           42483 :     dy = ((afWin[6] + afWin[7] + afWin[7] + afWin[8]) - 
     423           42483 :           (afWin[0] + afWin[1] + afWin[1] + afWin[2]))/psData->nsres;
     424                 : 
     425           14161 :     key = (dx * dx + dy * dy);
     426                 : 
     427           14161 :     if (psData->slopeFormat == 1) 
     428           14161 :         return atan(sqrt(key) / (8*psData->scale)) * radiansToDegrees;
     429                 :     else
     430               0 :         return 100*(sqrt(key) / (8*psData->scale));
     431                 : }
     432                 : 
     433               1 : void*  GDALCreateSlopeData(double* adfGeoTransform,
     434                 :                            double scale,
     435                 :                            int slopeFormat)
     436                 : {
     437                 :     GDALSlopeAlgData* pData =
     438               1 :         (GDALSlopeAlgData*)CPLMalloc(sizeof(GDALSlopeAlgData));
     439                 :         
     440               1 :     pData->nsres = adfGeoTransform[5];
     441               1 :     pData->ewres = adfGeoTransform[1];
     442               1 :     pData->scale = scale;
     443               1 :     pData->slopeFormat = slopeFormat;
     444               1 :     return pData;
     445                 : }
     446                 : 
     447                 : /************************************************************************/
     448                 : /*                         GDALAspect()                                 */
     449                 : /************************************************************************/
     450                 : 
     451                 : typedef struct
     452                 : {
     453                 :     int bAngleAsAzimuth;
     454                 : } GDALAspectAlgData;
     455                 : 
     456           14161 : float GDALAspectAlg (float* afWin, float fDstNoDataValue, void* pData)
     457                 : {
     458           14161 :     const double degreesToRadians = M_PI / 180.0;
     459           14161 :     GDALAspectAlgData* psData = (GDALAspectAlgData*)pData;
     460                 :     double dx, dy;
     461                 :     float aspect;
     462                 :     
     463           42483 :     dx = ((afWin[2] + afWin[5] + afWin[5] + afWin[8]) -
     464           42483 :           (afWin[0] + afWin[3] + afWin[3] + afWin[6]));
     465                 : 
     466           42483 :     dy = ((afWin[6] + afWin[7] + afWin[7] + afWin[8]) - 
     467           42483 :           (afWin[0] + afWin[1] + afWin[1] + afWin[2]));
     468                 : 
     469           14161 :     aspect = atan2(dy,-dx) / degreesToRadians;
     470                 : 
     471           18344 :     if (dx == 0 && dy == 0)
     472                 :     {
     473                 :         /* Flat area */
     474            4183 :         aspect = fDstNoDataValue;
     475                 :     } 
     476            9978 :     else if ( psData->bAngleAsAzimuth )
     477                 :     {
     478            9978 :         if (aspect > 90.0) 
     479            1243 :             aspect = 450.0 - aspect;
     480                 :         else
     481            8735 :             aspect = 90.0 - aspect;
     482                 :     }
     483                 :     else
     484                 :     {
     485               0 :         if (aspect < 0)
     486               0 :             aspect += 360.0;
     487                 :     }
     488                 : 
     489           14161 :     if (aspect == 360.0) 
     490               0 :         aspect = 0.0;
     491                 : 
     492           14161 :     return aspect;
     493                 : }
     494                 : 
     495               1 : void*  GDALCreateAspectData(int bAngleAsAzimuth)
     496                 : {
     497                 :     GDALAspectAlgData* pData =
     498               1 :         (GDALAspectAlgData*)CPLMalloc(sizeof(GDALAspectAlgData));
     499                 :         
     500               1 :     pData->bAngleAsAzimuth = bAngleAsAzimuth;
     501               1 :     return pData;
     502                 : }
     503                 : 
     504                 : /************************************************************************/
     505                 : /*                      GDALColorRelief()                               */
     506                 : /************************************************************************/
     507                 : 
     508                 : typedef struct
     509                 : {
     510                 :     double dfVal;
     511                 :     int nR;
     512                 :     int nG;
     513                 :     int nB;
     514                 :     int nA;
     515                 : } ColorAssociation;
     516                 : 
     517              55 : static int GDALColorReliefSortColors(const void* pA, const void* pB)
     518                 : {
     519              55 :     ColorAssociation* pC1 = (ColorAssociation*)pA;
     520              55 :     ColorAssociation* pC2 = (ColorAssociation*)pB;
     521                 :     return (pC1->dfVal < pC2->dfVal) ? -1 :
     522              55 :            (pC1->dfVal == pC2->dfVal) ? 0 : 1;
     523                 : }
     524                 : 
     525                 : typedef enum
     526                 : {
     527                 :     COLOR_SELECTION_INTERPOLATE,
     528                 :     COLOR_SELECTION_NEAREST_ENTRY,
     529                 :     COLOR_SELECTION_EXACT_ENTRY
     530                 : } ColorSelectionMode;
     531                 : 
     532          131769 : static int GDALColorReliefGetRGBA (ColorAssociation* pasColorAssociation,
     533                 :                                    int nColorAssociation,
     534                 :                                    double dfVal,
     535                 :                                    ColorSelectionMode eColorSelectionMode,
     536                 :                                    int* pnR,
     537                 :                                    int* pnG,
     538                 :                                    int* pnB,
     539                 :                                    int* pnA)
     540                 : {
     541                 :     int i;
     542          131769 :     int lower = 0;
     543          131769 :     int upper = nColorAssociation - 1;
     544                 :     int mid;
     545                 : 
     546                 :     /* Find the index of the first element in the LUT input array that */
     547                 :     /* is not smaller than the dfVal value. */
     548          288783 :     while(TRUE)
     549                 :     {
     550          420552 :         mid = (lower + upper) / 2;
     551          420552 :         if (upper - lower <= 1)
     552                 :         {
     553          131769 :             if (dfVal < pasColorAssociation[lower].dfVal)
     554               0 :                 i = lower;
     555          131769 :             else if (dfVal < pasColorAssociation[upper].dfVal)
     556           89685 :                 i = upper;
     557                 :             else
     558           42084 :                 i = upper + 1;
     559                 :             break;
     560                 :         }
     561          288783 :         else if (pasColorAssociation[mid].dfVal >= dfVal)
     562                 :         {
     563          173367 :             upper = mid;
     564                 :         }
     565                 :         else
     566                 :         {
     567          115416 :             lower = mid;
     568                 :         }
     569                 :     }
     570                 : 
     571          131769 :     if (i == 0)
     572                 :     {
     573               0 :         if (eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY &&
     574                 :             pasColorAssociation[0].dfVal != dfVal)
     575                 :         {
     576               0 :             *pnR = 0;
     577               0 :             *pnG = 0;
     578               0 :             *pnB = 0;
     579               0 :             *pnA = 0;
     580               0 :             return FALSE;
     581                 :         }
     582                 :         else
     583                 :         {
     584               0 :             *pnR = pasColorAssociation[0].nR;
     585               0 :             *pnG = pasColorAssociation[0].nG;
     586               0 :             *pnB = pasColorAssociation[0].nB;
     587               0 :             *pnA = pasColorAssociation[0].nA;
     588               0 :             return TRUE;
     589                 :         }
     590                 :     }
     591          131769 :     else if (i == nColorAssociation)
     592                 :     {
     593               0 :         if (eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY &&
     594               0 :             pasColorAssociation[i-1].dfVal != dfVal)
     595                 :         {
     596               0 :             *pnR = 0;
     597               0 :             *pnG = 0;
     598               0 :             *pnB = 0;
     599               0 :             *pnA = 0;
     600               0 :             return FALSE;
     601                 :         }
     602                 :         else
     603                 :         {
     604               0 :             *pnR = pasColorAssociation[i-1].nR;
     605               0 :             *pnG = pasColorAssociation[i-1].nG;
     606               0 :             *pnB = pasColorAssociation[i-1].nB;
     607               0 :             *pnA = pasColorAssociation[i-1].nA;
     608               0 :             return TRUE;
     609                 :         }
     610                 :     }
     611                 :     else
     612                 :     {
     613          131769 :         if (eColorSelectionMode == COLOR_SELECTION_EXACT_ENTRY &&
     614               0 :             pasColorAssociation[i-1].dfVal != dfVal)
     615                 :         {
     616               0 :             *pnR = 0;
     617               0 :             *pnG = 0;
     618               0 :             *pnB = 0;
     619               0 :             *pnA = 0;
     620               0 :             return FALSE;
     621                 :         }
     622                 :         
     623          146410 :         if (eColorSelectionMode == COLOR_SELECTION_NEAREST_ENTRY &&
     624           14641 :             pasColorAssociation[i-1].dfVal != dfVal)
     625                 :         {
     626                 :             int index;
     627           19930 :             if (dfVal - pasColorAssociation[i-1].dfVal <
     628            9965 :                 pasColorAssociation[i].dfVal - dfVal)
     629            6716 :                 index = i -1;
     630                 :             else
     631            3249 :                 index = i;
     632                 : 
     633            9965 :             *pnR = pasColorAssociation[index].nR;
     634            9965 :             *pnG = pasColorAssociation[index].nG;
     635            9965 :             *pnB = pasColorAssociation[index].nB;
     636            9965 :             *pnA = pasColorAssociation[index].nA;
     637            9965 :             return TRUE;
     638                 :         }
     639                 :         
     640          121804 :         double dfRatio = (dfVal - pasColorAssociation[i-1].dfVal) /
     641          121804 :             (pasColorAssociation[i].dfVal - pasColorAssociation[i-1].dfVal);
     642          121804 :         *pnR = (int)(0.45 + pasColorAssociation[i-1].nR + dfRatio *
     643          121804 :                 (pasColorAssociation[i].nR - pasColorAssociation[i-1].nR));
     644          121804 :         if (*pnR < 0) *pnR = 0;
     645          121804 :         else if (*pnR > 255) *pnR = 255;
     646          121804 :         *pnG = (int)(0.45 + pasColorAssociation[i-1].nG + dfRatio *
     647          121804 :                 (pasColorAssociation[i].nG - pasColorAssociation[i-1].nG));
     648          121804 :         if (*pnG < 0) *pnG = 0;
     649          121804 :         else if (*pnG > 255) *pnG = 255;
     650          121804 :         *pnB = (int)(0.45 + pasColorAssociation[i-1].nB + dfRatio *
     651          121804 :                 (pasColorAssociation[i].nB - pasColorAssociation[i-1].nB));
     652          121804 :         if (*pnB < 0) *pnB = 0;
     653          121804 :         else if (*pnB > 255) *pnB = 255;
     654          121804 :         *pnA = (int)(0.45 + pasColorAssociation[i-1].nA + dfRatio *
     655          121804 :                 (pasColorAssociation[i].nA - pasColorAssociation[i-1].nA));
     656          121804 :         if (*pnA < 0) *pnA = 0;
     657          121804 :         else if (*pnA > 255) *pnA = 255;
     658                 :         
     659          121804 :         return TRUE;
     660                 :     }
     661                 : }
     662                 : 
     663                 : /* dfPct : percentage between 0 and 1 */
     664               0 : static double GDALColorReliefGetAbsoluteValFromPct(GDALRasterBandH hSrcBand,
     665                 :                                                    double dfPct)
     666                 : {
     667                 :     double dfMin, dfMax;
     668                 :     int bSuccessMin, bSuccessMax;
     669               0 :     dfMin = GDALGetRasterMinimum(hSrcBand, &bSuccessMin);
     670               0 :     dfMax = GDALGetRasterMaximum(hSrcBand, &bSuccessMax);
     671               0 :     if (!bSuccessMin || !bSuccessMax)
     672                 :     {
     673                 :         double dfMean, dfStdDev;
     674               0 :         fprintf(stderr, "Computing source raster statistics...\n");
     675                 :         GDALComputeRasterStatistics(hSrcBand, FALSE, &dfMin, &dfMax,
     676               0 :                                     &dfMean, &dfStdDev, NULL, NULL);
     677                 :     }
     678               0 :     return dfMin + dfPct * (dfMax - dfMin);
     679                 : }
     680                 : 
     681                 : typedef struct
     682                 : {
     683                 :     const char *name;
     684                 :     float r, g, b;
     685                 : } NamedColor;
     686                 : 
     687                 : static const NamedColor namedColors[] = {
     688                 :     { "white",  1.00, 1.00, 1.00 },
     689                 :     { "black",  0.00, 0.00, 0.00 },
     690                 :     { "red",    1.00, 0.00, 0.00 },
     691                 :     { "green",  0.00, 1.00, 0.00 },
     692                 :     { "blue",   0.00, 0.00, 1.00 },
     693                 :     { "yellow", 1.00, 1.00, 0.00 },
     694                 :     { "magenta",1.00, 0.00, 1.00 },
     695                 :     { "cyan",   0.00, 1.00, 1.00 },
     696                 :     { "aqua",   0.00, 0.75, 0.75 },
     697                 :     { "grey",   0.75, 0.75, 0.75 },
     698                 :     { "gray",   0.75, 0.75, 0.75 },
     699                 :     { "orange", 1.00, 0.50, 0.00 },
     700                 :     { "brown",  0.75, 0.50, 0.25 },
     701                 :     { "purple", 0.50, 0.00, 1.00 },
     702                 :     { "violet", 0.50, 0.00, 1.00 },
     703                 :     { "indigo", 0.00, 0.50, 1.00 },
     704                 : };
     705                 : 
     706                 : static
     707               0 : int GDALColorReliefFindNamedColor(const char *pszColorName, int *pnR, int *pnG, int *pnB)
     708                 : {
     709                 :     unsigned int i;
     710                 : 
     711               0 :     *pnR = *pnG = *pnB = 0;
     712               0 :     for (i = 0; i < sizeof(namedColors) / sizeof(namedColors[0]); i++)
     713                 :     {
     714               0 :         if (EQUAL(pszColorName, namedColors[i].name))
     715                 :         {
     716               0 :             *pnR = (int)(255. * namedColors[i].r);
     717               0 :             *pnG = (int)(255. * namedColors[i].g);
     718               0 :             *pnB = (int)(255. * namedColors[i].b);
     719               0 :             return TRUE;
     720                 :         }
     721                 :     }
     722               0 :     return FALSE;
     723                 : }
     724                 : 
     725                 : static
     726               5 : ColorAssociation* GDALColorReliefParseColorFile(GDALRasterBandH hSrcBand,
     727                 :                                                 const char* pszColorFilename,
     728                 :                                                 int* pnColors)
     729                 : {
     730               5 :     FILE* fpColorFile = VSIFOpen(pszColorFilename, "rt");
     731               5 :     if (fpColorFile == NULL)
     732                 :     {
     733               0 :         CPLError(CE_Failure, CPLE_AppDefined, "Cannot find %s", pszColorFilename);
     734               0 :         *pnColors = 0;
     735               0 :         return NULL;
     736                 :     }
     737                 : 
     738               5 :     ColorAssociation* pasColorAssociation = NULL;
     739               5 :     int nColorAssociation = 0;
     740                 : 
     741               5 :     int bSrcHasNoData = FALSE;
     742               5 :     double dfSrcNoDataValue = GDALGetRasterNoDataValue(hSrcBand, &bSrcHasNoData);
     743                 : 
     744                 :     const char* pszLine;
     745              45 :     while ((pszLine = CPLReadLine(fpColorFile)) != NULL)
     746                 :     {
     747                 :         char** papszFields = CSLTokenizeStringComplex(pszLine, " ,\t:", 
     748              35 :                                                       FALSE, FALSE );
     749                 :         /* Skip comment lines */
     750              35 :         int nTokens = CSLCount(papszFields);
     751             105 :         if (nTokens >= 2 &&
     752              35 :             papszFields[0][0] != '#' &&
     753              35 :             papszFields[0][0] != '/')
     754                 :         {
     755                 :             pasColorAssociation =
     756                 :                     (ColorAssociation*)CPLRealloc(pasColorAssociation,
     757              35 :                            (nColorAssociation + 1) * sizeof(ColorAssociation));
     758              35 :             if (EQUAL(papszFields[0], "nv") && bSrcHasNoData)
     759               0 :                 pasColorAssociation[nColorAssociation].dfVal = dfSrcNoDataValue;
     760              35 :             else if (strlen(papszFields[0]) > 1 && papszFields[0][strlen(papszFields[0])-1] == '%')
     761                 :             {
     762               0 :                 double dfPct = atof(papszFields[0]) / 100.;
     763               0 :                 if (dfPct < 0.0 || dfPct > 1.0)
     764                 :                 {
     765                 :                     CPLError(CE_Failure, CPLE_AppDefined,
     766               0 :                              "Wrong value for a percentage : %s", papszFields[0]);
     767               0 :                     CSLDestroy(papszFields);
     768               0 :                     VSIFClose(fpColorFile);
     769               0 :                     CPLFree(pasColorAssociation);
     770               0 :                     *pnColors = 0;
     771               0 :                     return NULL;
     772                 :                 }
     773               0 :                 pasColorAssociation[nColorAssociation].dfVal =
     774               0 :                         GDALColorReliefGetAbsoluteValFromPct(hSrcBand, dfPct);
     775                 :             }
     776                 :             else
     777              35 :                 pasColorAssociation[nColorAssociation].dfVal = atof(papszFields[0]);
     778                 : 
     779              35 :             if (nTokens >= 4)
     780                 :             {
     781              35 :                 pasColorAssociation[nColorAssociation].nR = atoi(papszFields[1]);
     782              35 :                 pasColorAssociation[nColorAssociation].nG = atoi(papszFields[2]);
     783              35 :                 pasColorAssociation[nColorAssociation].nB = atoi(papszFields[3]);
     784              35 :                 pasColorAssociation[nColorAssociation].nA =
     785              35 :                         (CSLCount(papszFields) >= 5 ) ? atoi(papszFields[4]) : 255;
     786                 :             }
     787                 :             else
     788                 :             {
     789                 :                 int nR, nG, nB;
     790               0 :                 if (!GDALColorReliefFindNamedColor(papszFields[1], &nR, &nG, &nB))
     791                 :                 {
     792                 :                     CPLError(CE_Failure, CPLE_AppDefined,
     793               0 :                              "Unknown color : %s", papszFields[1]);
     794               0 :                     CSLDestroy(papszFields);
     795               0 :                     VSIFClose(fpColorFile);
     796               0 :                     CPLFree(pasColorAssociation);
     797               0 :                     *pnColors = 0;
     798               0 :                     return NULL;
     799                 :                 }
     800               0 :                 pasColorAssociation[nColorAssociation].nR = nR;
     801               0 :                 pasColorAssociation[nColorAssociation].nG = nG;
     802               0 :                 pasColorAssociation[nColorAssociation].nB = nB;
     803               0 :                             pasColorAssociation[nColorAssociation].nA =
     804               0 :                     (CSLCount(papszFields) >= 3 ) ? atoi(papszFields[2]) : 255;
     805                 :             }
     806                 : 
     807              35 :             nColorAssociation ++;
     808                 :         }
     809              35 :         CSLDestroy(papszFields);
     810                 :     }
     811               5 :     VSIFClose(fpColorFile);
     812                 : 
     813               5 :     if (nColorAssociation == 0)
     814                 :     {
     815                 :         CPLError(CE_Failure, CPLE_AppDefined,
     816               0 :                  "No color association found in %s", pszColorFilename);
     817               0 :         *pnColors = 0;
     818               0 :         return NULL;
     819                 :     }
     820                 : 
     821                 :     qsort(pasColorAssociation, nColorAssociation,
     822               5 :           sizeof(ColorAssociation), GDALColorReliefSortColors);
     823                 : 
     824               5 :     *pnColors = nColorAssociation;
     825               5 :     return pasColorAssociation;
     826                 : }
     827                 : 
     828                 : static
     829               5 : GByte* GDALColorReliefPrecompute(GDALRasterBandH hSrcBand,
     830                 :                                  ColorAssociation* pasColorAssociation,
     831                 :                                  int nColorAssociation,
     832                 :                                  ColorSelectionMode eColorSelectionMode,
     833                 :                                  int* pnIndexOffset)
     834                 : {
     835               5 :     GDALDataType eDT = GDALGetRasterDataType(hSrcBand);
     836               5 :     GByte* pabyPrecomputed = NULL;
     837               5 :     int nIndexOffset = (eDT == GDT_Int16) ? 32768 : 0;
     838               5 :     *pnIndexOffset = nIndexOffset;
     839               5 :     int nXSize = GDALGetRasterBandXSize(hSrcBand);
     840               5 :     int nYSize = GDALGetRasterBandXSize(hSrcBand);
     841               5 :     if (eDT == GDT_Byte ||
     842                 :         ((eDT == GDT_Int16 || eDT == GDT_UInt16) && nXSize * nYSize > 65536))
     843                 :     {
     844               0 :         int iMax = (eDT == GDT_Byte) ? 256: 65536;
     845               0 :         pabyPrecomputed = (GByte*) VSIMalloc(4 * iMax);
     846               0 :         if (pabyPrecomputed)
     847                 :         {
     848                 :             int i;
     849               0 :             for(i=0;i<iMax;i++)
     850                 :             {
     851                 :                 int nR, nG, nB, nA;
     852                 :                 GDALColorReliefGetRGBA  (pasColorAssociation,
     853                 :                                          nColorAssociation,
     854                 :                                          i - nIndexOffset,
     855                 :                                          eColorSelectionMode,
     856               0 :                                          &nR, &nG, &nB, &nA);
     857               0 :                 pabyPrecomputed[4 * i] = (GByte) nR;
     858               0 :                 pabyPrecomputed[4 * i + 1] = (GByte) nG;
     859               0 :                 pabyPrecomputed[4 * i + 2] = (GByte) nB;
     860               0 :                 pabyPrecomputed[4 * i + 3] = (GByte) nA;
     861                 :             }
     862                 :         }
     863                 :     }
     864               5 :     return pabyPrecomputed;
     865                 : }
     866                 : 
     867                 : /************************************************************************/
     868                 : /* ==================================================================== */
     869                 : /*                       GDALColorReliefDataset                        */
     870                 : /* ==================================================================== */
     871                 : /************************************************************************/
     872                 : 
     873                 : class GDALColorReliefRasterBand;
     874                 : 
     875                 : class GDALColorReliefDataset : public GDALDataset
     876                 : {
     877                 :     friend class GDALColorReliefRasterBand;
     878                 : 
     879                 :     GDALDatasetH       hSrcDS;
     880                 :     GDALRasterBandH    hSrcBand;
     881                 :     int                nColorAssociation;
     882                 :     ColorAssociation*  pasColorAssociation;
     883                 :     ColorSelectionMode eColorSelectionMode;
     884                 :     GByte*             pabyPrecomputed;
     885                 :     int                nIndexOffset;
     886                 :     float*             pafSourceBuf;
     887                 :     int*               panSourceBuf;
     888                 :     int                nCurBlockXOff;
     889                 :     int                nCurBlockYOff;
     890                 : 
     891                 :   public:
     892                 :                         GDALColorReliefDataset(GDALDatasetH hSrcDS,
     893                 :                                             GDALRasterBandH hSrcBand,
     894                 :                                             const char* pszColorFilename,
     895                 :                                             ColorSelectionMode eColorSelectionMode,
     896                 :                                             int bAlpha);
     897                 :                        ~GDALColorReliefDataset();
     898                 : 
     899                 :     CPLErr      GetGeoTransform( double * padfGeoTransform );
     900                 :     const char *GetProjectionRef();
     901                 : };
     902                 : 
     903                 : /************************************************************************/
     904                 : /* ==================================================================== */
     905                 : /*                    GDALColorReliefRasterBand                       */
     906                 : /* ==================================================================== */
     907                 : /************************************************************************/
     908                 : 
     909                 : class GDALColorReliefRasterBand : public GDALRasterBand
     910              12 : {
     911                 :     friend class GDALColorReliefDataset;
     912                 : 
     913                 :     
     914                 :   public:
     915                 :                  GDALColorReliefRasterBand( GDALColorReliefDataset *, int );
     916                 :     
     917                 :     virtual CPLErr          IReadBlock( int, int, void * );
     918                 :     virtual GDALColorInterp GetColorInterpretation();
     919                 : };
     920                 : 
     921               2 : GDALColorReliefDataset::GDALColorReliefDataset(
     922                 :                                      GDALDatasetH hSrcDS,
     923                 :                                      GDALRasterBandH hSrcBand,
     924                 :                                      const char* pszColorFilename,
     925                 :                                      ColorSelectionMode eColorSelectionMode,
     926               2 :                                      int bAlpha)
     927                 : {
     928               2 :     this->hSrcDS = hSrcDS;
     929               2 :     this->hSrcBand = hSrcBand;
     930               2 :     nColorAssociation = 0;
     931                 :     pasColorAssociation =
     932                 :             GDALColorReliefParseColorFile(hSrcBand, pszColorFilename,
     933               2 :                                           &nColorAssociation);
     934               2 :     this->eColorSelectionMode = eColorSelectionMode;
     935                 :     
     936               2 :     nRasterXSize = GDALGetRasterXSize(hSrcDS);
     937               2 :     nRasterYSize = GDALGetRasterYSize(hSrcDS);
     938                 :     
     939                 :     int nBlockXSize, nBlockYSize;
     940               2 :     GDALGetBlockSize( hSrcBand, &nBlockXSize, &nBlockYSize);
     941                 :     
     942               2 :     nIndexOffset = 0;
     943                 :     pabyPrecomputed =
     944                 :         GDALColorReliefPrecompute(hSrcBand,
     945                 :                                   pasColorAssociation,
     946                 :                                   nColorAssociation,
     947                 :                                   eColorSelectionMode,
     948               2 :                                   &nIndexOffset);
     949                 :     
     950                 :     int i;
     951               8 :     for(i=0;i<((bAlpha) ? 4 : 3);i++)
     952                 :     {
     953               6 :         SetBand(i + 1, new GDALColorReliefRasterBand(this, i+1));
     954                 :     }
     955                 :     
     956               2 :     pafSourceBuf = NULL;
     957               2 :     panSourceBuf = NULL;
     958               2 :     if (pabyPrecomputed)
     959               0 :         panSourceBuf = (int *) CPLMalloc(sizeof(int)*nBlockXSize*nBlockYSize);
     960                 :     else
     961               2 :         pafSourceBuf = (float *) CPLMalloc(sizeof(float)*nBlockXSize*nBlockYSize);
     962               2 :     nCurBlockXOff = -1;
     963               2 :     nCurBlockYOff = -1;
     964               2 : }
     965                 : 
     966               4 : GDALColorReliefDataset::~GDALColorReliefDataset()
     967                 : {
     968               2 :     CPLFree(pasColorAssociation);
     969               2 :     CPLFree(pabyPrecomputed);
     970               2 :     CPLFree(panSourceBuf);
     971               2 :     CPLFree(pafSourceBuf);
     972               4 : }
     973                 : 
     974               2 : CPLErr GDALColorReliefDataset::GetGeoTransform( double * padfGeoTransform )
     975                 : {
     976               2 :     return GDALGetGeoTransform(hSrcDS, padfGeoTransform);
     977                 : }
     978                 : 
     979               2 : const char *GDALColorReliefDataset::GetProjectionRef()
     980                 : {
     981               2 :     return GDALGetProjectionRef(hSrcDS);
     982                 : }
     983                 : 
     984               6 : GDALColorReliefRasterBand::GDALColorReliefRasterBand(
     985               6 :                                     GDALColorReliefDataset * poDS, int nBand)
     986                 : {
     987               6 :     this->poDS = poDS;
     988               6 :     this->nBand = nBand;
     989               6 :     eDataType = GDT_Byte;
     990               6 :     GDALGetBlockSize( poDS->hSrcBand, &nBlockXSize, &nBlockYSize);
     991               6 : }
     992                 : 
     993             387 : CPLErr GDALColorReliefRasterBand::IReadBlock( int nBlockXOff,
     994                 :                                               int nBlockYOff,
     995                 :                                               void *pImage )
     996                 : {
     997             387 :     GDALColorReliefDataset * poGDS = (GDALColorReliefDataset *) poDS;
     998                 :     int nReqXSize, nReqYSize;
     999                 : 
    1000             387 :     if ((nBlockXOff + 1) * nBlockXSize >= nRasterXSize)
    1001              27 :         nReqXSize = nRasterXSize - nBlockXOff * nBlockXSize;
    1002                 :     else
    1003             360 :         nReqXSize = nBlockXSize;
    1004                 :         
    1005             387 :     if ((nBlockYOff + 1) * nBlockYSize >= nRasterYSize)
    1006             366 :         nReqYSize = nRasterYSize - nBlockYOff * nBlockYSize;
    1007                 :     else
    1008              21 :         nReqYSize = nBlockYSize;
    1009                 : 
    1010             387 :     int nCount = nReqXSize * nReqYSize;
    1011             387 :     if ( poGDS->nCurBlockXOff != nBlockXOff ||
    1012                 :          poGDS->nCurBlockYOff != nBlockYOff )
    1013                 :     {
    1014             371 :         poGDS->nCurBlockXOff = nBlockXOff;
    1015             371 :         poGDS->nCurBlockYOff = nBlockYOff;
    1016                 :         
    1017                 :         CPLErr eErr = GDALRasterIO( poGDS->hSrcBand,
    1018                 :                             GF_Read,
    1019                 :                             nBlockXOff * nBlockXSize,
    1020                 :                             nBlockYOff * nBlockYSize,
    1021                 :                             nReqXSize, nReqYSize,
    1022                 :                             (poGDS->panSourceBuf) ?
    1023                 :                                 (void*) poGDS->panSourceBuf :
    1024                 :                                 (void* )poGDS->pafSourceBuf,
    1025                 :                             nReqXSize, nReqYSize,
    1026                 :                             (poGDS->panSourceBuf) ? GDT_Int32 : GDT_Float32,
    1027             371 :                             0, 0);
    1028             371 :         if (eErr != CE_None)
    1029                 :         {
    1030               0 :             memset(pImage, 0, nCount);
    1031               0 :             return eErr;
    1032                 :         }
    1033                 :     }
    1034                 : 
    1035                 :     int j;
    1036             387 :     if (poGDS->panSourceBuf)
    1037                 :     {
    1038               0 :         for ( j = 0; j < nCount; j++)
    1039                 :         {
    1040               0 :             int nIndex = poGDS->panSourceBuf[j] + poGDS->nIndexOffset;
    1041               0 :             ((GByte*)pImage)[j] = poGDS->pabyPrecomputed[4*nIndex + nBand-1];
    1042                 :         }
    1043                 :     }
    1044                 :     else
    1045                 :     {
    1046                 :         int anComponents[4];
    1047           88233 :         for ( j = 0; j < nCount; j++)
    1048                 :         {
    1049                 :             GDALColorReliefGetRGBA  (poGDS->pasColorAssociation,
    1050                 :                                      poGDS->nColorAssociation,
    1051           87846 :                                      poGDS->pafSourceBuf[j],
    1052                 :                                      poGDS->eColorSelectionMode,
    1053                 :                                      &anComponents[0],
    1054                 :                                      &anComponents[1],
    1055                 :                                      &anComponents[2],
    1056          175692 :                                      &anComponents[3]);
    1057           87846 :             ((GByte*)pImage)[j] = (GByte) anComponents[nBand-1];
    1058                 :         }
    1059                 :     }
    1060                 :     
    1061             387 :     return CE_None;
    1062                 : }
    1063                 : 
    1064              12 : GDALColorInterp GDALColorReliefRasterBand::GetColorInterpretation()
    1065                 : {
    1066              12 :     return (GDALColorInterp)(GCI_RedBand + nBand - 1);
    1067                 : }
    1068                 : 
    1069                 : 
    1070               3 : CPLErr GDALColorRelief (GDALRasterBandH hSrcBand,
    1071                 :                         GDALRasterBandH hDstBand1,
    1072                 :                         GDALRasterBandH hDstBand2,
    1073                 :                         GDALRasterBandH hDstBand3,
    1074                 :                         GDALRasterBandH hDstBand4,
    1075                 :                         const char* pszColorFilename,
    1076                 :                         ColorSelectionMode eColorSelectionMode,
    1077                 :                         GDALProgressFunc pfnProgress,
    1078                 :                         void * pProgressData)
    1079                 : {
    1080                 :     CPLErr eErr;
    1081                 :     
    1082               3 :     if (hSrcBand == NULL || hDstBand1 == NULL || hDstBand2 == NULL ||
    1083                 :         hDstBand3 == NULL)
    1084               0 :         return CE_Failure;
    1085                 : 
    1086               3 :     int nColorAssociation = 0;
    1087                 :     ColorAssociation* pasColorAssociation =
    1088                 :             GDALColorReliefParseColorFile(hSrcBand, pszColorFilename,
    1089               3 :                                           &nColorAssociation);
    1090               3 :     if (pasColorAssociation == NULL)
    1091               0 :         return CE_Failure;
    1092                 : 
    1093               3 :     int nXSize = GDALGetRasterBandXSize(hSrcBand);
    1094               3 :     int nYSize = GDALGetRasterBandYSize(hSrcBand);
    1095                 : 
    1096               3 :     if (pfnProgress == NULL)
    1097               0 :         pfnProgress = GDALDummyProgress;
    1098                 :         
    1099               3 :     int nR = 0, nG = 0, nB = 0, nA = 0;
    1100                 :     
    1101                 : /* -------------------------------------------------------------------- */
    1102                 : /*      Precompute the map from values to RGBA quadruplets              */
    1103                 : /*      for GDT_Byte, GDT_Int16 or GDT_UInt16                           */
    1104                 : /* -------------------------------------------------------------------- */
    1105               3 :     int nIndexOffset = 0;
    1106                 :     GByte* pabyPrecomputed =
    1107                 :         GDALColorReliefPrecompute(hSrcBand,
    1108                 :                                   pasColorAssociation,
    1109                 :                                   nColorAssociation,
    1110                 :                                   eColorSelectionMode,
    1111               3 :                                   &nIndexOffset);
    1112                 : 
    1113                 : /* -------------------------------------------------------------------- */
    1114                 : /*      Initialize progress counter.                                    */
    1115                 : /* -------------------------------------------------------------------- */
    1116                 : 
    1117               3 :     float* pafSourceBuf = NULL;
    1118               3 :     int* panSourceBuf = NULL;
    1119               3 :     if (pabyPrecomputed)
    1120               0 :         panSourceBuf = (int *) CPLMalloc(sizeof(int)*nXSize);
    1121                 :     else
    1122               3 :         pafSourceBuf = (float *) CPLMalloc(sizeof(float)*nXSize);
    1123               3 :     GByte* pabyDestBuf1  = (GByte*) CPLMalloc( 4 * nXSize );
    1124               3 :     GByte* pabyDestBuf2  =  pabyDestBuf1 + nXSize;
    1125               3 :     GByte* pabyDestBuf3  =  pabyDestBuf2 + nXSize;
    1126               3 :     GByte* pabyDestBuf4  =  pabyDestBuf3 + nXSize;
    1127                 :     int i, j;
    1128                 : 
    1129               3 :     if( !pfnProgress( 0.0, NULL, pProgressData ) )
    1130                 :     {
    1131               0 :         CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    1132               0 :         eErr = CE_Failure;
    1133               0 :         goto end;
    1134                 :     }
    1135                 : 
    1136             366 :     for ( i = 0; i < nYSize; i++)
    1137                 :     {
    1138                 :         /* Read source buffer */
    1139                 :         eErr = GDALRasterIO(   hSrcBand,
    1140                 :                         GF_Read,
    1141                 :                         0, i,
    1142                 :                         nXSize, 1,
    1143                 :                         (panSourceBuf) ? (void*) panSourceBuf : (void* )pafSourceBuf,
    1144                 :                         nXSize, 1,
    1145                 :                         (panSourceBuf) ? GDT_Int32 : GDT_Float32,
    1146             363 :                         0, 0);
    1147             363 :         if (eErr != CE_None)
    1148               0 :             goto end;
    1149                 : 
    1150             363 :         if (panSourceBuf)
    1151                 :         {
    1152               0 :             for ( j = 0; j < nXSize; j++)
    1153                 :             {
    1154               0 :                 int nIndex = panSourceBuf[j] + nIndexOffset;
    1155               0 :                 pabyDestBuf1[j] = pabyPrecomputed[4 * nIndex];
    1156               0 :                 pabyDestBuf2[j] = pabyPrecomputed[4 * nIndex + 1];
    1157               0 :                 pabyDestBuf3[j] = pabyPrecomputed[4 * nIndex + 2];
    1158               0 :                 pabyDestBuf4[j] = pabyPrecomputed[4 * nIndex + 3];
    1159                 :             }
    1160                 :         }
    1161                 :         else
    1162                 :         {
    1163           44286 :             for ( j = 0; j < nXSize; j++)
    1164                 :             {
    1165                 :                 GDALColorReliefGetRGBA  (pasColorAssociation,
    1166                 :                                          nColorAssociation,
    1167           43923 :                                          pafSourceBuf[j],
    1168                 :                                          eColorSelectionMode,
    1169                 :                                          &nR,
    1170                 :                                          &nG,
    1171                 :                                          &nB,
    1172           43923 :                                          &nA);
    1173           43923 :                 pabyDestBuf1[j] = (GByte) nR;
    1174           43923 :                 pabyDestBuf2[j] = (GByte) nG;
    1175           43923 :                 pabyDestBuf3[j] = (GByte) nB;
    1176           43923 :                 pabyDestBuf4[j] = (GByte) nA;
    1177                 :             }
    1178                 :         }
    1179                 :         
    1180                 :         /* -----------------------------------------
    1181                 :          * Write Line to Raster
    1182                 :          */
    1183                 :         eErr = GDALRasterIO(hDstBand1,
    1184                 :                       GF_Write,
    1185                 :                       0, i, nXSize,
    1186             363 :                       1, pabyDestBuf1, nXSize, 1, GDT_Byte, 0, 0);
    1187             363 :         if (eErr != CE_None)
    1188               0 :             goto end;
    1189                 : 
    1190                 :         eErr = GDALRasterIO(hDstBand2,
    1191                 :                       GF_Write,
    1192                 :                       0, i, nXSize,
    1193             363 :                       1, pabyDestBuf2, nXSize, 1, GDT_Byte, 0, 0);
    1194             363 :         if (eErr != CE_None)
    1195               0 :             goto end;
    1196                 :             
    1197                 :         eErr = GDALRasterIO(hDstBand3,
    1198                 :                       GF_Write,
    1199                 :                       0, i, nXSize,
    1200             363 :                       1, pabyDestBuf3, nXSize, 1, GDT_Byte, 0, 0);
    1201             363 :         if (eErr != CE_None)
    1202               0 :             goto end;
    1203                 :             
    1204             363 :         if (hDstBand4)
    1205                 :         {
    1206                 :             eErr = GDALRasterIO(hDstBand4,
    1207                 :                         GF_Write,
    1208                 :                         0, i, nXSize,
    1209               0 :                         1, pabyDestBuf4, nXSize, 1, GDT_Byte, 0, 0);
    1210               0 :             if (eErr != CE_None)
    1211               0 :                 goto end;
    1212                 :         }
    1213                 : 
    1214             363 :         if( !pfnProgress( 1.0 * (i+1) / nYSize, NULL, pProgressData ) )
    1215                 :         {
    1216               0 :             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    1217               0 :             eErr = CE_Failure;
    1218               0 :             goto end;
    1219                 :         }
    1220                 :     }
    1221               3 :     pfnProgress( 1.0, NULL, pProgressData );
    1222               3 :     eErr = CE_None;
    1223                 : 
    1224                 : end:
    1225               3 :     VSIFree(pabyPrecomputed);
    1226               3 :     CPLFree(pafSourceBuf);
    1227               3 :     CPLFree(panSourceBuf);
    1228               3 :     CPLFree(pabyDestBuf1);
    1229               3 :     CPLFree(pasColorAssociation);
    1230                 : 
    1231               3 :     return eErr;
    1232                 : }
    1233                 : 
    1234                 : /************************************************************************/
    1235                 : /*                         GDALTRI()                                  */
    1236                 : /************************************************************************/
    1237                 : 
    1238               0 : float GDALTRIAlg (float* afWin, float fDstNoDataValue, void* pData)
    1239                 : {
    1240                 :     // Terrain Ruggedness is average difference in height
    1241               0 :     return (fabs(afWin[0]-afWin[4]) +
    1242               0 :             fabs(afWin[1]-afWin[4]) +
    1243               0 :             fabs(afWin[2]-afWin[4]) +
    1244               0 :             fabs(afWin[3]-afWin[4]) +
    1245               0 :             fabs(afWin[5]-afWin[4]) +
    1246               0 :             fabs(afWin[6]-afWin[4]) +
    1247               0 :             fabs(afWin[7]-afWin[4]) +
    1248               0 :             fabs(afWin[8]-afWin[4]))/8;
    1249                 : }
    1250                 : 
    1251               0 : CPLErr GDALTRI  ( GDALRasterBandH hSrcBand,
    1252                 :                   GDALRasterBandH hDstBand,
    1253                 :                   GDALProgressFunc pfnProgress,
    1254                 :                   void * pProgressData)
    1255                 : {
    1256                 :     return GDALGeneric3x3Processing(hSrcBand, hDstBand,
    1257                 :                                     GDALTRIAlg, NULL,
    1258               0 :                                     pfnProgress, pProgressData);
    1259                 : }
    1260                 : 
    1261                 : /************************************************************************/
    1262                 : /*                         GDALTPI()                                  */
    1263                 : /************************************************************************/
    1264                 : 
    1265               0 : float GDALTPIAlg (float* afWin, float fDstNoDataValue, void* pData)
    1266                 : {
    1267                 :     // Terrain Position is the difference between
    1268                 :     // The central cell and the mean of the surrounding cells
    1269               0 :     return afWin[4] - 
    1270               0 :             ((afWin[0]+
    1271               0 :               afWin[1]+
    1272               0 :               afWin[2]+
    1273               0 :               afWin[3]+
    1274               0 :               afWin[5]+
    1275               0 :               afWin[6]+
    1276               0 :               afWin[7]+
    1277               0 :               afWin[8])/8);
    1278                 : }
    1279                 : 
    1280                 : /************************************************************************/
    1281                 : /*                      GDALRoughness()                                */
    1282                 : /************************************************************************/
    1283                 : 
    1284               0 : float GDALRoughnessAlg (float* afWin, float fDstNoDataValue, void* pData)
    1285                 : {
    1286                 :     // Roughness is the largest difference
    1287                 :     //  between any two cells
    1288                 : 
    1289               0 :     float pafRoughnessMin = afWin[0];
    1290               0 :     float pafRoughnessMax = afWin[0];
    1291                 : 
    1292               0 :     for ( int k = 1; k < 9; k++)
    1293                 :     {
    1294               0 :         if (afWin[k] > pafRoughnessMax)
    1295                 :         {
    1296               0 :             pafRoughnessMax=afWin[k];
    1297                 :         }
    1298               0 :         if (afWin[k] < pafRoughnessMin)
    1299                 :         {
    1300               0 :             pafRoughnessMin=afWin[k];
    1301                 :         }
    1302                 :     }
    1303               0 :     return pafRoughnessMax - pafRoughnessMin;
    1304                 : }
    1305                 : 
    1306                 : /************************************************************************/
    1307                 : /* ==================================================================== */
    1308                 : /*                       GDALGeneric3x3Dataset                        */
    1309                 : /* ==================================================================== */
    1310                 : /************************************************************************/
    1311                 : 
    1312                 : class GDALGeneric3x3RasterBand;
    1313                 : 
    1314                 : class GDALGeneric3x3Dataset : public GDALDataset
    1315                 : {
    1316                 :     friend class GDALGeneric3x3RasterBand;
    1317                 : 
    1318                 :     GDALGeneric3x3ProcessingAlg pfnAlg;
    1319                 :     void*              pAlgData;
    1320                 :     GDALDatasetH       hSrcDS;
    1321                 :     GDALRasterBandH    hSrcBand;
    1322                 :     float*             apafSourceBuf[3];
    1323                 :     int                bDstHasNoData;
    1324                 :     double             dfDstNoDataValue;
    1325                 :     int                nCurLine;
    1326                 : 
    1327                 :   public:
    1328                 :                         GDALGeneric3x3Dataset(GDALDatasetH hSrcDS,
    1329                 :                                               GDALRasterBandH hSrcBand,
    1330                 :                                               GDALDataType eDstDataType,
    1331                 :                                               int bDstHasNoData,
    1332                 :                                               double dfDstNoDataValue,
    1333                 :                                               GDALGeneric3x3ProcessingAlg pfnAlg,
    1334                 :                                               void* pAlgData);
    1335                 :                        ~GDALGeneric3x3Dataset();
    1336                 : 
    1337                 :     CPLErr      GetGeoTransform( double * padfGeoTransform );
    1338                 :     const char *GetProjectionRef();
    1339                 : };
    1340                 : 
    1341                 : /************************************************************************/
    1342                 : /* ==================================================================== */
    1343                 : /*                    GDALGeneric3x3RasterBand                       */
    1344                 : /* ==================================================================== */
    1345                 : /************************************************************************/
    1346                 : 
    1347                 : class GDALGeneric3x3RasterBand : public GDALRasterBand
    1348               2 : {
    1349                 :     friend class GDALGeneric3x3Dataset;
    1350                 : 
    1351                 :     
    1352                 :   public:
    1353                 :                  GDALGeneric3x3RasterBand( GDALGeneric3x3Dataset *poDS,
    1354                 :                                            GDALDataType eDstDataType );
    1355                 :     
    1356                 :     virtual CPLErr          IReadBlock( int, int, void * );
    1357                 :     virtual double          GetNoDataValue( int* pbHasNoData );
    1358                 : };
    1359                 : 
    1360               1 : GDALGeneric3x3Dataset::GDALGeneric3x3Dataset(
    1361                 :                                      GDALDatasetH hSrcDS,
    1362                 :                                      GDALRasterBandH hSrcBand,
    1363                 :                                      GDALDataType eDstDataType,
    1364                 :                                      int bDstHasNoData,
    1365                 :                                      double dfDstNoDataValue,
    1366                 :                                      GDALGeneric3x3ProcessingAlg pfnAlg,
    1367               1 :                                      void* pAlgData)
    1368                 : {
    1369               1 :     this->hSrcDS = hSrcDS;
    1370               1 :     this->hSrcBand = hSrcBand;
    1371               1 :     this->pfnAlg = pfnAlg;
    1372               1 :     this->pAlgData = pAlgData;
    1373               1 :     this->bDstHasNoData = bDstHasNoData;
    1374               1 :     this->dfDstNoDataValue = dfDstNoDataValue;
    1375                 :     
    1376                 :     CPLAssert(eDstDataType == GDT_Byte || eDstDataType == GDT_Float32);
    1377                 : 
    1378               1 :     nRasterXSize = GDALGetRasterXSize(hSrcDS);
    1379               1 :     nRasterYSize = GDALGetRasterYSize(hSrcDS);
    1380                 :     
    1381               1 :     SetBand(1, new GDALGeneric3x3RasterBand(this, eDstDataType));
    1382                 :     
    1383               1 :     apafSourceBuf[0] = (float *) CPLMalloc(sizeof(float)*nRasterXSize);
    1384               1 :     apafSourceBuf[1] = (float *) CPLMalloc(sizeof(float)*nRasterXSize);
    1385               1 :     apafSourceBuf[2] = (float *) CPLMalloc(sizeof(float)*nRasterXSize);
    1386                 :     
    1387               1 :     nCurLine = -1;
    1388               1 : }
    1389                 : 
    1390               2 : GDALGeneric3x3Dataset::~GDALGeneric3x3Dataset()
    1391                 : {
    1392               1 :     CPLFree(apafSourceBuf[0]);
    1393               1 :     CPLFree(apafSourceBuf[1]);
    1394               1 :     CPLFree(apafSourceBuf[2]);
    1395               2 : }
    1396                 : 
    1397               1 : CPLErr GDALGeneric3x3Dataset::GetGeoTransform( double * padfGeoTransform )
    1398                 : {
    1399               1 :     return GDALGetGeoTransform(hSrcDS, padfGeoTransform);
    1400                 : }
    1401                 : 
    1402               1 : const char *GDALGeneric3x3Dataset::GetProjectionRef()
    1403                 : {
    1404               1 :     return GDALGetProjectionRef(hSrcDS);
    1405                 : }
    1406                 : 
    1407               1 : GDALGeneric3x3RasterBand::GDALGeneric3x3RasterBand(GDALGeneric3x3Dataset *poDS,
    1408               1 :                                                    GDALDataType eDstDataType)
    1409                 : {
    1410               1 :     this->poDS = poDS;
    1411               1 :     this->nBand = 1;
    1412               1 :     eDataType = eDstDataType;
    1413               1 :     nBlockXSize = poDS->GetRasterXSize();
    1414               1 :     nBlockYSize = 1;
    1415               1 : }
    1416                 : 
    1417             121 : CPLErr GDALGeneric3x3RasterBand::IReadBlock( int nBlockXOff,
    1418                 :                                              int nBlockYOff,
    1419                 :                                              void *pImage )
    1420                 : {
    1421             121 :     GDALGeneric3x3Dataset * poGDS = (GDALGeneric3x3Dataset *) poDS;
    1422                 :     
    1423             121 :     if ( nBlockYOff == 0 || nBlockYOff == nRasterYSize - 1)
    1424                 :     {
    1425                 :         int j;
    1426               2 :         if (eDataType == GDT_Byte)
    1427                 :         {
    1428             244 :             for(j=0;j<nBlockXSize;j++)
    1429             242 :                 ((GByte*)pImage)[j] = (GByte) poGDS->dfDstNoDataValue;
    1430                 :         }
    1431                 :         else
    1432                 :         {
    1433               0 :             for(j=0;j<nBlockXSize;j++)
    1434               0 :                 ((float*)pImage)[j] = (float) poGDS->dfDstNoDataValue;
    1435                 :         }
    1436                 :             
    1437               2 :         return CE_None;
    1438                 :     }
    1439                 : 
    1440             119 :     if ( poGDS->nCurLine != nBlockYOff )
    1441                 :     {
    1442             119 :         if (nBlockYOff != 1 &&
    1443                 :             poGDS->nCurLine == nBlockYOff + 1)
    1444                 :         {
    1445               0 :             float* pafTmp =  poGDS->apafSourceBuf[0];
    1446               0 :             poGDS->apafSourceBuf[0] = poGDS->apafSourceBuf[1];
    1447               0 :             poGDS->apafSourceBuf[1] = poGDS->apafSourceBuf[2];
    1448               0 :             poGDS->apafSourceBuf[2] = pafTmp;
    1449                 :             
    1450               0 :             poGDS->nCurLine = nBlockYOff;
    1451                 :             
    1452                 :             CPLErr eErr = GDALRasterIO( poGDS->hSrcBand,
    1453                 :                                     GF_Read,
    1454                 :                                     0, nBlockYOff + 1, nBlockXSize, 1,
    1455               0 :                                     poGDS->apafSourceBuf[2],
    1456                 :                                     nBlockXSize, 1,
    1457                 :                                     GDT_Float32,
    1458               0 :                                     0, 0);
    1459                 :                                     
    1460               0 :             if (eErr != CE_None)
    1461                 :             {
    1462               0 :                 memset(pImage, 0, nBlockXSize * sizeof(float));
    1463               0 :                 return eErr;
    1464                 :             }
    1465                 :         }
    1466                 :         else
    1467                 :         {
    1468             119 :             poGDS->nCurLine = nBlockYOff;
    1469                 :             int i;
    1470             476 :             for(i=0;i<3;i++)
    1471                 :             {
    1472                 :                 CPLErr eErr = GDALRasterIO( poGDS->hSrcBand,
    1473                 :                                     GF_Read,
    1474                 :                                     0, nBlockYOff + i - 1, nBlockXSize, 1,
    1475             357 :                                     poGDS->apafSourceBuf[i],
    1476                 :                                     nBlockXSize, 1,
    1477                 :                                     GDT_Float32,
    1478             714 :                                     0, 0);
    1479             357 :                 if (eErr != CE_None)
    1480                 :                 {
    1481               0 :                     memset(pImage, 0, nBlockXSize * sizeof(float));
    1482               0 :                     return eErr;
    1483                 :                 }
    1484                 :             }
    1485                 :         }
    1486                 :     }
    1487                 : 
    1488                 :     int j;
    1489                 :     
    1490             119 :     if (eDataType == GDT_Byte)
    1491                 :     {
    1492             119 :         ((GByte*)pImage)[0] = (GByte) poGDS->dfDstNoDataValue;
    1493             119 :         if (nBlockXSize > 1)
    1494             119 :             ((GByte*)pImage)[nBlockXSize - 1] = (GByte) poGDS->dfDstNoDataValue;
    1495                 :     }
    1496                 :     else
    1497                 :     {
    1498               0 :         ((float*)pImage)[0] = (float) poGDS->dfDstNoDataValue;
    1499               0 :         if (nBlockXSize > 1)
    1500               0 :             ((float*)pImage)[nBlockXSize - 1] = (float) poGDS->dfDstNoDataValue;
    1501                 :     }
    1502                 :     
    1503                 :     int bSrcHasNoData;
    1504                 :     double dfSrcNoDataValue = GDALGetRasterNoDataValue(poGDS->hSrcBand,
    1505             119 :                                                        &bSrcHasNoData);
    1506                 : 
    1507           14280 :     for(j=1;j<nBlockXSize - 1;j++)
    1508                 :     {
    1509                 :         float afWin[9];
    1510           14161 :         afWin[0] = poGDS->apafSourceBuf[0][j-1];
    1511           14161 :         afWin[1] = poGDS->apafSourceBuf[0][j];
    1512           14161 :         afWin[2] = poGDS->apafSourceBuf[0][j+1];
    1513           14161 :         afWin[3] = poGDS->apafSourceBuf[1][j-1];
    1514           14161 :         afWin[4] = poGDS->apafSourceBuf[1][j];
    1515           14161 :         afWin[5] = poGDS->apafSourceBuf[1][j+1];
    1516           14161 :         afWin[6] = poGDS->apafSourceBuf[2][j-1];
    1517           14161 :         afWin[7] = poGDS->apafSourceBuf[2][j];
    1518           14161 :         afWin[8] = poGDS->apafSourceBuf[2][j+1];
    1519                 : 
    1520                 :         // Check if afWin has null value
    1521           14161 :         int bContainsNull = FALSE;
    1522           14161 :         if (bSrcHasNoData)
    1523                 :         {
    1524          141610 :             for ( int n = 0; n <= 8; n++)
    1525                 :             {
    1526          127449 :                 if(afWin[n] == dfSrcNoDataValue)
    1527                 :                 {
    1528               0 :                     bContainsNull = TRUE;
    1529               0 :                     break;
    1530                 :                 }
    1531                 :             }
    1532                 :         }
    1533                 : 
    1534           14161 :         if (bContainsNull)
    1535                 :         {
    1536                 :             // We have nulls so write nullValue and move on
    1537               0 :             if (eDataType == GDT_Byte)
    1538               0 :                 ((GByte*)pImage)[j] = (GByte) poGDS->dfDstNoDataValue;
    1539                 :             else
    1540               0 :                 ((float*)pImage)[j] = (float) poGDS->dfDstNoDataValue;
    1541                 :         } else {
    1542                 :             // We have a valid 3x3 window.
    1543           14161 :             if (eDataType == GDT_Byte)
    1544           14161 :                 ((GByte*)pImage)[j] = (GByte) (poGDS->pfnAlg(
    1545           14161 :                         afWin, poGDS->dfDstNoDataValue, poGDS->pAlgData) + 0.5);
    1546                 :             else
    1547               0 :                 ((float*)pImage)[j] = (float) poGDS->pfnAlg(
    1548               0 :                         afWin, poGDS->dfDstNoDataValue, poGDS->pAlgData);
    1549                 :         }
    1550                 :     }
    1551                 :     
    1552             119 :     return CE_None;
    1553                 : }
    1554                 : 
    1555               4 : double GDALGeneric3x3RasterBand::GetNoDataValue( int* pbHasNoData )
    1556                 : {
    1557               4 :     GDALGeneric3x3Dataset * poGDS = (GDALGeneric3x3Dataset *) poDS;
    1558               4 :     if (pbHasNoData)
    1559               3 :         *pbHasNoData = poGDS->bDstHasNoData;
    1560               4 :     return poGDS->dfDstNoDataValue;
    1561                 : }
    1562                 : 
    1563                 : /************************************************************************/
    1564                 : /*                                main()                                */
    1565                 : /************************************************************************/
    1566                 : 
    1567                 : typedef enum
    1568                 : {
    1569                 :     HILL_SHADE,
    1570                 :     SLOPE,
    1571                 :     ASPECT,
    1572                 :     COLOR_RELIEF,
    1573                 :     TRI,
    1574                 :     TPI,
    1575                 :     ROUGHNESS
    1576                 : } Algorithm;
    1577                 : 
    1578              10 : int main( int argc, char ** argv )
    1579                 : 
    1580                 : {
    1581                 :     Algorithm eUtilityMode;
    1582              10 :     double z = 1.0;
    1583              10 :     double scale = 1.0;
    1584              10 :     double az = 315.0;
    1585              10 :     double alt = 45.0;
    1586                 :     // 0 = 'percent' or 1 = 'degrees'
    1587              10 :     int slopeFormat = 1; 
    1588              10 :     int bAddAlpha = FALSE;
    1589              10 :     int bZeroForFlat = FALSE;
    1590              10 :     int bAngleAsAzimuth = TRUE;
    1591              10 :     ColorSelectionMode eColorSelectionMode = COLOR_SELECTION_INTERPOLATE;
    1592                 :     
    1593              10 :     int nBand = 1;
    1594                 :     double  adfGeoTransform[6];
    1595                 : 
    1596              10 :     const char *pszSrcFilename = NULL;
    1597              10 :     const char *pszDstFilename = NULL;
    1598              10 :     const char *pszColorFilename = NULL;
    1599              10 :     const char *pszFormat = "GTiff";
    1600              10 :     char **papszCreateOptions = NULL;
    1601                 :     
    1602              10 :     GDALDatasetH hSrcDataset = NULL;
    1603              10 :     GDALDatasetH hDstDataset = NULL;
    1604              10 :     GDALRasterBandH hSrcBand = NULL;
    1605              10 :     GDALRasterBandH hDstBand = NULL;
    1606              10 :     GDALDriverH hDriver = NULL;
    1607                 : 
    1608              10 :     GDALProgressFunc pfnProgress = GDALTermProgress;
    1609                 :     
    1610              10 :     int nXSize = 0;
    1611              10 :     int nYSize = 0;
    1612                 :     
    1613                 :     /* Check strict compilation and runtime library version as we use C++ API */
    1614              10 :     if (! GDAL_CHECK_VERSION(argv[0]))
    1615               0 :         exit(1);
    1616                 : 
    1617              10 :     argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
    1618              10 :     if( argc < 2 )
    1619                 :     {
    1620               0 :         fprintf(stderr, "Not enough arguments\n");
    1621               0 :         Usage();
    1622               0 :         exit( 1 );
    1623                 :     }
    1624                 : 
    1625              10 :     if( EQUAL(argv[1], "--utility_version") || EQUAL(argv[1], "--utility-version") )
    1626                 :     {
    1627                 :         printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
    1628               1 :                 argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
    1629               1 :         return 0;
    1630                 :     }
    1631              11 :     else if ( EQUAL(argv[1], "shade") || EQUAL(argv[1], "hillshade") )
    1632                 :     {
    1633               2 :         eUtilityMode = HILL_SHADE;
    1634                 :     }
    1635               7 :     else if ( EQUAL(argv[1], "slope") )
    1636                 :     {
    1637               1 :         eUtilityMode = SLOPE;
    1638                 :     }
    1639               6 :     else if ( EQUAL(argv[1], "aspect") )
    1640                 :     {
    1641               1 :         eUtilityMode = ASPECT;
    1642                 :     }
    1643               5 :     else if ( EQUAL(argv[1], "color-relief") )
    1644                 :     {
    1645               5 :         eUtilityMode = COLOR_RELIEF;
    1646                 :     }
    1647               0 :     else if ( EQUAL(argv[1], "TRI") )
    1648                 :     {
    1649               0 :         eUtilityMode = TRI;
    1650                 :     }
    1651               0 :     else if ( EQUAL(argv[1], "TPI") )
    1652                 :     {
    1653               0 :         eUtilityMode = TPI;
    1654                 :     }
    1655               0 :     else if ( EQUAL(argv[1], "roughness") )
    1656                 :     {
    1657               0 :         eUtilityMode = ROUGHNESS;
    1658                 :     }
    1659                 :     else
    1660                 :     {
    1661               0 :         fprintf(stderr, "Missing valid sub-utility mention\n");
    1662               0 :         Usage();
    1663               0 :         exit( 1 );
    1664                 :     }
    1665                 : 
    1666                 : /* -------------------------------------------------------------------- */
    1667                 : /*      Parse arguments.                                                */
    1668                 : /* -------------------------------------------------------------------- */
    1669              41 :     for(int i = 2; i < argc; i++ )
    1670                 :     {
    1671              48 :         if( eUtilityMode == HILL_SHADE && i + 1 < argc &&
    1672              14 :             (EQUAL(argv[i], "--z") || EQUAL(argv[i], "-z")))
    1673                 :         {
    1674               2 :             z = atof(argv[++i]);
    1675                 :         }
    1676              30 :         else if ( eUtilityMode == SLOPE && EQUAL(argv[i], "-p"))
    1677                 :         {
    1678               0 :             slopeFormat = 0;
    1679                 :         }
    1680              30 :         else if ( eUtilityMode == ASPECT && EQUAL(argv[i], "-trigonometric"))
    1681                 :         {
    1682               0 :             bAngleAsAzimuth = FALSE;
    1683                 :         }
    1684              30 :         else if ( eUtilityMode == ASPECT && EQUAL(argv[i], "-zero_for_flat"))
    1685                 :         {
    1686               0 :             bZeroForFlat = TRUE;
    1687                 :         }
    1688              30 :         else if ( eUtilityMode == COLOR_RELIEF && EQUAL(argv[i], "-exact_color_entry"))
    1689                 :         {
    1690               0 :             eColorSelectionMode = COLOR_SELECTION_EXACT_ENTRY;
    1691                 :         }
    1692              31 :         else if ( eUtilityMode == COLOR_RELIEF && EQUAL(argv[i], "-nearest_color_entry"))
    1693                 :         {
    1694               1 :             eColorSelectionMode = COLOR_SELECTION_NEAREST_ENTRY;
    1695                 :         }
    1696             106 :         else if( i + 1 < argc &&
    1697              20 :             (EQUAL(argv[i], "--s") || 
    1698              20 :              EQUAL(argv[i], "-s") ||
    1699              17 :              EQUAL(argv[i], "--scale") ||
    1700              17 :              EQUAL(argv[i], "-scale"))
    1701                 :           )
    1702                 :         {
    1703               3 :             scale = atof(argv[++i]);
    1704                 :         }
    1705              38 :         else if( eUtilityMode == HILL_SHADE && i + 1 < argc &&
    1706               3 :             (EQUAL(argv[i], "--az") || 
    1707               3 :              EQUAL(argv[i], "-az") ||
    1708               3 :              EQUAL(argv[i], "--azimuth") ||
    1709               3 :              EQUAL(argv[i], "-azimuth"))
    1710                 :           )
    1711                 :         {
    1712               0 :             az = atof(argv[++i]);
    1713                 :         }
    1714              38 :         else if( eUtilityMode == HILL_SHADE && i + 1 < argc &&
    1715               3 :             (EQUAL(argv[i], "--alt") || 
    1716               3 :              EQUAL(argv[i], "-alt") ||
    1717               3 :              EQUAL(argv[i], "--alt") ||
    1718               3 :              EQUAL(argv[i], "-alt"))
    1719                 :           )
    1720                 :         {
    1721               0 :             alt = atof(argv[++i]);
    1722                 :         }
    1723              43 :         else if( eUtilityMode == COLOR_RELIEF &&
    1724              17 :                  EQUAL(argv[i], "-alpha"))
    1725                 :         {
    1726               0 :             bAddAlpha = TRUE;
    1727                 :         }
    1728              60 :         else if( i + 1 < argc &&
    1729              17 :             (EQUAL(argv[i], "--b") || 
    1730              17 :              EQUAL(argv[i], "-b"))
    1731                 :           )
    1732                 :         {
    1733               0 :             nBand = atoi(argv[++i]);
    1734                 :         }
    1735              26 :         else if ( EQUAL(argv[i], "-q") || EQUAL(argv[i], "-quiet") )
    1736                 :         {
    1737               0 :             pfnProgress = GDALDummyProgress;
    1738                 :         }
    1739              26 :         else if( EQUAL(argv[i],"-co") && i < argc-1 )
    1740                 :         {
    1741               0 :             papszCreateOptions = CSLAddString( papszCreateOptions, argv[++i] );
    1742                 :         }
    1743              29 :         else if( EQUAL(argv[i],"-of") && i < argc-1 )
    1744                 :         {
    1745               3 :             pszFormat = argv[++i];
    1746                 :         }
    1747              23 :         else if( argv[i][0] == '-' )
    1748                 :         {
    1749                 :             fprintf( stderr, "Option %s incomplete, or not recognised.\n\n", 
    1750               0 :                     argv[i] );
    1751               0 :             Usage();
    1752               0 :             GDALDestroyDriverManager();
    1753               0 :             exit( 2 );
    1754                 :         }
    1755              23 :         else if( pszSrcFilename == NULL )
    1756                 :         {
    1757               9 :             pszSrcFilename = argv[i];
    1758                 :         }
    1759              19 :         else if( eUtilityMode == COLOR_RELIEF && pszColorFilename == NULL )
    1760                 :         {
    1761               5 :             pszColorFilename = argv[i];
    1762                 :         }
    1763               9 :         else if( pszDstFilename == NULL )
    1764                 :         {
    1765               9 :             pszDstFilename = argv[i];
    1766                 :         }
    1767                 :         else
    1768               0 :             Usage();
    1769                 :     }
    1770                 : 
    1771               9 :     if( pszSrcFilename == NULL )
    1772                 :     {
    1773               0 :         fprintf( stderr, "Missing source.\n\n" );
    1774               0 :         Usage();
    1775                 :     }
    1776               9 :     if ( eUtilityMode == COLOR_RELIEF && pszColorFilename == NULL )
    1777                 :     {
    1778               0 :         fprintf( stderr, "Missing color file.\n\n" );
    1779               0 :         Usage();
    1780                 :     }
    1781               9 :     if( pszDstFilename == NULL )
    1782                 :     {
    1783               0 :         fprintf( stderr, "Missing destination.\n\n" );
    1784               0 :         Usage();
    1785                 :     }
    1786                 : 
    1787               9 :     GDALAllRegister();
    1788                 : 
    1789                 :     // Open Dataset and get raster band
    1790               9 :     hSrcDataset = GDALOpen( pszSrcFilename, GA_ReadOnly );
    1791                 :     
    1792               9 :     if( hSrcDataset == NULL )
    1793                 :     {
    1794                 :         fprintf( stderr,
    1795                 :                  "GDALOpen failed - %d\n%s\n",
    1796               0 :                  CPLGetLastErrorNo(), CPLGetLastErrorMsg() );
    1797               0 :         GDALDestroyDriverManager();
    1798               0 :         exit( 1 );
    1799                 :     }
    1800                 : 
    1801               9 :     nXSize = GDALGetRasterXSize(hSrcDataset);
    1802               9 :     nYSize = GDALGetRasterYSize(hSrcDataset);
    1803                 : 
    1804               9 :     if( nBand <= 0 || nBand > GDALGetRasterCount(hSrcDataset) )
    1805                 :     {
    1806                 :         fprintf( stderr,
    1807               0 :                  "Unable to fetch band #%d\n", nBand );
    1808               0 :         GDALDestroyDriverManager();
    1809               0 :         exit( 1 );
    1810                 :     }
    1811               9 :     hSrcBand = GDALGetRasterBand( hSrcDataset, nBand );
    1812                 : 
    1813               9 :     GDALGetGeoTransform(hSrcDataset, adfGeoTransform);
    1814                 : 
    1815               9 :     hDriver = GDALGetDriverByName(pszFormat);
    1816               9 :     if( hDriver == NULL 
    1817                 :         || (GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL &&
    1818                 :             GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, NULL ) == NULL))
    1819                 :     {
    1820                 :         int iDr;
    1821                 : 
    1822                 :         fprintf( stderr, "Output driver `%s' not recognised or does not support\n", 
    1823               0 :                  pszFormat );
    1824                 :         fprintf( stderr, "direct output file creation.  The following format drivers are configured\n"
    1825               0 :                 "and support direct output:\n" );
    1826                 : 
    1827               0 :         for( iDr = 0; iDr < GDALGetDriverCount(); iDr++ )
    1828                 :         {
    1829               0 :             GDALDriverH hDriver = GDALGetDriver(iDr);
    1830                 : 
    1831               0 :             if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL &&
    1832                 :                 GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, NULL ) == NULL )
    1833                 :             {
    1834                 :                 printf( "  %s: %s\n",
    1835                 :                         GDALGetDriverShortName( hDriver  ),
    1836               0 :                         GDALGetDriverLongName( hDriver ) );
    1837                 :             }
    1838                 :         }
    1839               0 :         GDALDestroyDriverManager();
    1840               0 :         exit( 1 );
    1841                 :     }
    1842                 : 
    1843               9 :     double dfDstNoDataValue = 0;
    1844               9 :     int bDstHasNoData = FALSE;
    1845               9 :     void* pData = NULL;
    1846               9 :     GDALGeneric3x3ProcessingAlg pfnAlg = NULL;
    1847                 : 
    1848               9 :     if (eUtilityMode == HILL_SHADE)
    1849                 :     {
    1850               2 :         dfDstNoDataValue = 0;
    1851               2 :         bDstHasNoData = TRUE;
    1852                 :         pData = GDALCreateHillshadeData   (adfGeoTransform,
    1853                 :                                            z,
    1854                 :                                            scale,
    1855                 :                                            alt,
    1856               2 :                                            az);
    1857               2 :         pfnAlg = GDALHillshadeAlg;
    1858                 :     }
    1859               7 :     else if (eUtilityMode == SLOPE)
    1860                 :     {
    1861               1 :         dfDstNoDataValue = -9999;
    1862               1 :         bDstHasNoData = TRUE;
    1863                 : 
    1864               1 :         pData = GDALCreateSlopeData(adfGeoTransform, scale, slopeFormat);
    1865               1 :         pfnAlg = GDALSlopeAlg;
    1866                 :     }
    1867                 : 
    1868               6 :     else if (eUtilityMode == ASPECT)
    1869                 :     {
    1870               1 :         if (!bZeroForFlat)
    1871                 :         {
    1872               1 :             dfDstNoDataValue = -9999;
    1873               1 :             bDstHasNoData = TRUE;
    1874                 :         }
    1875                 : 
    1876               1 :         pData = GDALCreateAspectData(bAngleAsAzimuth);
    1877               1 :         pfnAlg = GDALAspectAlg;
    1878                 :     }
    1879               5 :     else if (eUtilityMode == TRI)
    1880                 :     {
    1881               0 :         dfDstNoDataValue = -9999;
    1882               0 :         bDstHasNoData = TRUE;
    1883               0 :         pfnAlg = GDALTRIAlg;
    1884                 :     }
    1885               5 :     else if (eUtilityMode == TPI)
    1886                 :     {
    1887               0 :         dfDstNoDataValue = -9999;
    1888               0 :         bDstHasNoData = TRUE;
    1889               0 :         pfnAlg = GDALTPIAlg;
    1890                 :     }
    1891               5 :     else if (eUtilityMode == ROUGHNESS)
    1892                 :     {
    1893               0 :         dfDstNoDataValue = -9999;
    1894               0 :         bDstHasNoData = TRUE;
    1895               0 :         pfnAlg = GDALRoughnessAlg;
    1896                 :     }
    1897                 :     
    1898                 :     GDALDataType eDstDataType = (eUtilityMode == HILL_SHADE ||
    1899                 :                                  eUtilityMode == COLOR_RELIEF) ? GDT_Byte :
    1900               9 :                                                                GDT_Float32;
    1901                 :     
    1902               9 :     if( GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATE, NULL ) == NULL &&
    1903                 :         GDALGetMetadataItem( hDriver, GDAL_DCAP_CREATECOPY, NULL ) != NULL)
    1904                 :     {
    1905                 :         GDALDatasetH hIntermediateDataset;
    1906                 :         
    1907               3 :         if (eUtilityMode == COLOR_RELIEF)
    1908                 :             hIntermediateDataset = (GDALDatasetH)
    1909                 :                 new GDALColorReliefDataset (hSrcDataset,
    1910                 :                                             hSrcBand,
    1911                 :                                             pszColorFilename,
    1912                 :                                             eColorSelectionMode,
    1913               2 :                                             bAddAlpha);
    1914                 :         else
    1915                 :             hIntermediateDataset = (GDALDatasetH)
    1916                 :                 new GDALGeneric3x3Dataset(hSrcDataset, hSrcBand,
    1917                 :                                           eDstDataType,
    1918                 :                                           bDstHasNoData,
    1919                 :                                           dfDstNoDataValue,
    1920                 :                                           pfnAlg,
    1921               1 :                                           pData);
    1922                 : 
    1923                 :         GDALDatasetH hOutDS = GDALCreateCopy(
    1924                 :                                  hDriver, pszDstFilename, hIntermediateDataset, 
    1925                 :                                  TRUE, papszCreateOptions, 
    1926               3 :                                  pfnProgress, NULL );
    1927                 : 
    1928               3 :         if( hOutDS != NULL )
    1929               3 :             GDALClose( hOutDS );
    1930               3 :         GDALClose(hIntermediateDataset);
    1931               3 :         GDALClose(hSrcDataset);
    1932                 :         
    1933               3 :         CPLFree(pData);
    1934                 : 
    1935               3 :         GDALDestroyDriverManager();
    1936               3 :         CSLDestroy( argv );
    1937               3 :         CSLDestroy( papszCreateOptions );
    1938                 :         
    1939               3 :         return 0;
    1940                 :     }
    1941                 : 
    1942                 :     int nDstBands;
    1943               6 :     if (eUtilityMode == COLOR_RELIEF)
    1944               3 :         nDstBands = (bAddAlpha) ? 4 : 3;
    1945                 :     else
    1946               3 :         nDstBands = 1;
    1947                 : 
    1948                 :     hDstDataset = GDALCreate(   hDriver,
    1949                 :                                 pszDstFilename,
    1950                 :                                 nXSize,
    1951                 :                                 nYSize,
    1952                 :                                 nDstBands,
    1953                 :                                 eDstDataType,
    1954               6 :                                 papszCreateOptions);
    1955                 : 
    1956               6 :     if( hDstDataset == NULL )
    1957                 :     {
    1958                 :         fprintf( stderr,
    1959                 :                  "Unable to create dataset %s %d\n%s\n", pszDstFilename,
    1960               0 :                  CPLGetLastErrorNo(), CPLGetLastErrorMsg() );
    1961               0 :         GDALDestroyDriverManager();
    1962               0 :         exit( 1 );
    1963                 :     }
    1964                 :     
    1965               6 :     hDstBand = GDALGetRasterBand( hDstDataset, 1 );
    1966                 : 
    1967               6 :     GDALSetGeoTransform(hDstDataset, adfGeoTransform);
    1968               6 :     GDALSetProjection(hDstDataset, GDALGetProjectionRef(hSrcDataset));
    1969                 :     
    1970               6 :     if (eUtilityMode == COLOR_RELIEF)
    1971                 :     {
    1972                 :         GDALColorRelief (hSrcBand, 
    1973                 :                          GDALGetRasterBand(hDstDataset, 1),
    1974                 :                          GDALGetRasterBand(hDstDataset, 2),
    1975                 :                          GDALGetRasterBand(hDstDataset, 3),
    1976                 :                          (bAddAlpha) ? GDALGetRasterBand(hDstDataset, 4) : NULL,
    1977                 :                          pszColorFilename,
    1978                 :                          eColorSelectionMode,
    1979               3 :                          pfnProgress, NULL);
    1980                 :     }
    1981                 :     else
    1982                 :     {
    1983               3 :         if (bDstHasNoData)
    1984               3 :             GDALSetRasterNoDataValue(hDstBand, dfDstNoDataValue);
    1985                 :         
    1986                 :         GDALGeneric3x3Processing(hSrcBand, hDstBand,
    1987                 :                                  pfnAlg, pData,
    1988               3 :                                  pfnProgress, NULL);
    1989                 :                                     
    1990                 :     }
    1991                 : 
    1992               6 :     GDALClose(hSrcDataset);
    1993               6 :     GDALClose(hDstDataset);
    1994               6 :     CPLFree(pData);
    1995                 : 
    1996               6 :     GDALDestroyDriverManager();
    1997               6 :     CSLDestroy( argv );
    1998               6 :     CSLDestroy( papszCreateOptions );
    1999                 : 
    2000               6 :     return 0;
    2001                 : }
    2002                 : 

Generated by: LCOV version 1.7