LCOV - code coverage report
Current view: directory - apps - gdaldem.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 1136 821 72.3 %
Date: 2012-12-26 Functions: 53 33 62.3 %

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

Generated by: LCOV version 1.7