LCOV - code coverage report
Current view: directory - alg - gdalsimplewarp.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 134 0 0.0 %
Date: 2010-01-09 Functions: 2 0 0.0 %

       1                 : /******************************************************************************
       2                 :  * $Id: gdalsimplewarp.cpp 15436 2008-09-24 19:26:31Z rouault $
       3                 :  *
       4                 :  * Project:  Mapinfo Image Warper
       5                 :  * Purpose:  Simple (source in memory) warp algorithm.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2002, i3 - information integration and imaging, Fort Collin,CO
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "gdal_priv.h"
      31                 : #include "gdal_alg.h"
      32                 : #include "cpl_string.h"
      33                 : 
      34                 : CPL_CVSID("$Id: gdalsimplewarp.cpp 15436 2008-09-24 19:26:31Z rouault $");
      35                 : 
      36                 : static void 
      37                 : GDALSimpleWarpRemapping( int nBandCount, GByte **papabySrcData, 
      38                 :                          int nSrcXSize, int nSrcYSize,
      39                 :                          char **papszWarpOptions );
      40                 : 
      41                 : /************************************************************************/
      42                 : /*                        GDALSimpleImageWarp()                         */
      43                 : /************************************************************************/
      44                 : 
      45                 : /**
      46                 :  * Perform simple image warp.
      47                 :  *
      48                 :  * Copies an image from a source dataset to a destination dataset applying
      49                 :  * an application defined transformation.   This algorithm is called simple
      50                 :  * because it lacks many options such as resampling kernels (other than 
      51                 :  * nearest neighbour), support for data types other than 8bit, and the
      52                 :  * ability to warp images without holding the entire source and destination
      53                 :  * image in memory.
      54                 :  *
      55                 :  * The following option(s) may be passed in papszWarpOptions. 
      56                 :  * <ul>
      57                 :  * <li> "INIT=v[,v...]": This option indicates that the output dataset should
      58                 :  * be initialized to the indicated value in any area valid data is not written.
      59                 :  * Distinct values may be listed for each band separated by columns. 
      60                 :  * </ul>
      61                 :  *
      62                 :  * @param hSrcDS the source image dataset. 
      63                 :  * @param hDstDS the destination image dataset. 
      64                 :  * @param nBandCount the number of bands to be warped.  If zero, all bands
      65                 :  * will be processed.
      66                 :  * @param panBandList the list of bands to translate. 
      67                 :  * @param pfnTransform the transformation function to call.  See 
      68                 :  * GDALTransformerFunc(). 
      69                 :  * @param pTransformArg the callback handle to pass to pfnTransform.
      70                 :  * @param pfnProgress the function used to report progress.  See 
      71                 :  * GDALProgressFunc(). 
      72                 :  * @param pProgressArg the callback handle to pass to pfnProgress. 
      73                 :  * @param papszWarpOptions additional options controlling the warp. 
      74                 :  * 
      75                 :  * @return TRUE if the operation completes, or FALSE if an error occurs. 
      76                 :  */
      77                 : 
      78                 : int CPL_STDCALL
      79               0 : GDALSimpleImageWarp( GDALDatasetH hSrcDS, GDALDatasetH hDstDS, 
      80                 :                      int nBandCount, int *panBandList, 
      81                 :                      GDALTransformerFunc pfnTransform, void *pTransformArg,
      82                 :                      GDALProgressFunc pfnProgress, void *pProgressArg, 
      83                 :                      char **papszWarpOptions )
      84                 :     
      85                 : {
      86               0 :     VALIDATE_POINTER1( hSrcDS, "GDALSimpleImageWarp", 0 );
      87               0 :     VALIDATE_POINTER1( hDstDS, "GDALSimpleImageWarp", 0 );
      88                 : 
      89               0 :     int   iBand, bCancelled = FALSE;
      90                 : 
      91                 : /* -------------------------------------------------------------------- */
      92                 : /*      If no bands provided assume we should process all bands.        */
      93                 : /* -------------------------------------------------------------------- */
      94               0 :     if( nBandCount == 0 )
      95                 :     {
      96                 :         int nResult;
      97                 : 
      98               0 :         nBandCount = GDALGetRasterCount( hSrcDS ); 
      99               0 :         if (nBandCount == 0)
     100                 :         {
     101                 :             CPLError(CE_Failure, CPLE_AppDefined,
     102               0 :                      "No raster band in source dataset");
     103               0 :             return FALSE;
     104                 :         }
     105                 : 
     106               0 :         panBandList = (int *) CPLCalloc(sizeof(int),nBandCount);
     107                 : 
     108               0 :         for( iBand = 0; iBand < nBandCount; iBand++ )
     109               0 :             panBandList[iBand] = iBand+1;
     110                 : 
     111                 :         nResult = GDALSimpleImageWarp( hSrcDS, hDstDS, nBandCount, panBandList,
     112                 :                                        pfnTransform, pTransformArg, 
     113                 :                                        pfnProgress, pProgressArg, 
     114               0 :                                        papszWarpOptions );
     115               0 :         CPLFree( panBandList );
     116               0 :         return nResult;
     117                 :     }
     118                 : 
     119                 : /* -------------------------------------------------------------------- */
     120                 : /*      Post initial progress.                                          */
     121                 : /* -------------------------------------------------------------------- */
     122               0 :     if( pfnProgress )
     123                 :     {
     124               0 :         if( !pfnProgress( 0.0, "", pProgressArg ) )
     125               0 :             return FALSE;
     126                 :     }
     127                 : 
     128                 : /* -------------------------------------------------------------------- */
     129                 : /*      Load the source image band(s).                                  */
     130                 : /* -------------------------------------------------------------------- */
     131               0 :     int   nSrcXSize = GDALGetRasterXSize(hSrcDS);
     132               0 :     int   nSrcYSize = GDALGetRasterYSize(hSrcDS);
     133                 :     GByte **papabySrcData;
     134                 : 
     135               0 :     papabySrcData = (GByte **) CPLCalloc(nBandCount,sizeof(GByte*));
     136               0 :     for( iBand = 0; iBand < nBandCount; iBand++ )
     137                 :     {
     138               0 :         papabySrcData[iBand] = (GByte *) VSIMalloc(nSrcXSize*nSrcYSize);
     139                 :         
     140                 :         GDALRasterIO( GDALGetRasterBand(hSrcDS,panBandList[iBand]), GF_Read,
     141                 :                       0, 0, nSrcXSize, nSrcYSize, 
     142               0 :                       papabySrcData[iBand], nSrcXSize, nSrcYSize, GDT_Byte, 
     143               0 :                       0, 0 );
     144                 :     }
     145                 : 
     146                 : /* -------------------------------------------------------------------- */
     147                 : /*      Check for remap request(s).                                     */
     148                 : /* -------------------------------------------------------------------- */
     149                 :     GDALSimpleWarpRemapping( nBandCount, papabySrcData, nSrcXSize, nSrcYSize,
     150               0 :                              papszWarpOptions );
     151                 : 
     152                 : /* -------------------------------------------------------------------- */
     153                 : /*      Allocate scanline buffers for output image.                     */
     154                 : /* -------------------------------------------------------------------- */
     155               0 :     int nDstXSize = GDALGetRasterXSize( hDstDS );
     156               0 :     int nDstYSize = GDALGetRasterYSize( hDstDS );
     157                 :     GByte **papabyDstLine;
     158                 : 
     159               0 :     papabyDstLine = (GByte **) CPLCalloc(nBandCount,sizeof(GByte*));
     160                 :     
     161               0 :     for( iBand = 0; iBand < nBandCount; iBand++ )
     162               0 :         papabyDstLine[iBand] = (GByte *) CPLMalloc( nDstXSize );
     163                 : 
     164                 : /* -------------------------------------------------------------------- */
     165                 : /*      Allocate x,y,z coordinate arrays for transformation ... one     */
     166                 : /*      scanlines worth of positions.                                   */
     167                 : /* -------------------------------------------------------------------- */
     168                 :     double *padfX, *padfY, *padfZ;
     169                 :     int    *pabSuccess;
     170                 : 
     171               0 :     padfX = (double *) CPLMalloc(sizeof(double) * nDstXSize);
     172               0 :     padfY = (double *) CPLMalloc(sizeof(double) * nDstXSize);
     173               0 :     padfZ = (double *) CPLMalloc(sizeof(double) * nDstXSize);
     174               0 :     pabSuccess = (int *) CPLMalloc(sizeof(int) * nDstXSize);
     175                 : 
     176                 : /* -------------------------------------------------------------------- */
     177                 : /*      Establish the value we will use to initialize the bands.  We    */
     178                 : /*      default to -1 indicating the initial value should be read       */
     179                 : /*      and preserved from the source file, but allow this to be        */
     180                 : /*      overridden by passed                                            */
     181                 : /*      option(s).                                                      */
     182                 : /* -------------------------------------------------------------------- */
     183                 :     int         *panBandInit;
     184                 : 
     185               0 :     panBandInit = (int *) CPLCalloc(sizeof(int),nBandCount);
     186               0 :     if( CSLFetchNameValue( papszWarpOptions, "INIT" ) )
     187                 :     {
     188                 :         int  iBand, nTokenCount;
     189                 :         char **papszTokens = 
     190                 :             CSLTokenizeStringComplex( CSLFetchNameValue( papszWarpOptions, 
     191                 :                                                          "INIT" ),
     192               0 :                                       " ,", FALSE, FALSE );
     193                 : 
     194               0 :         nTokenCount = CSLCount(papszTokens);
     195                 : 
     196               0 :         for( iBand = 0; iBand < nBandCount; iBand++ )
     197                 :         {
     198               0 :             if( nTokenCount == 0 )
     199               0 :                 panBandInit[iBand] = 0;
     200                 :             else
     201               0 :                 panBandInit[iBand] = 
     202               0 :                     atoi(papszTokens[MIN(iBand,nTokenCount-1)]);
     203                 :         }
     204                 : 
     205               0 :         CSLDestroy(papszTokens);
     206                 :     }
     207                 : 
     208                 : /* -------------------------------------------------------------------- */
     209                 : /*      Loop over all the scanlines in the output image.                */
     210                 : /* -------------------------------------------------------------------- */
     211                 :     int iDstY;
     212                 : 
     213               0 :     for( iDstY = 0; iDstY < nDstYSize; iDstY++ )
     214                 :     {
     215                 :         int iDstX;
     216                 : 
     217                 :         // Clear output buffer to "transparent" value.  Shouldn't we
     218                 :         // really be reading from the destination file to support overlay?
     219               0 :         for( iBand = 0; iBand < nBandCount; iBand++ )
     220                 :         {
     221               0 :             if( panBandInit[iBand] == -1 )
     222                 :                 GDALRasterIO( GDALGetRasterBand(hDstDS,iBand+1), GF_Read,
     223                 :                               0, iDstY, nDstXSize, 1, 
     224               0 :                               papabyDstLine[iBand], nDstXSize, 1, GDT_Byte, 
     225               0 :                               0, 0 );
     226                 :             else
     227               0 :                 memset( papabyDstLine[iBand], panBandInit[iBand], nDstXSize );
     228                 :         }
     229                 : 
     230                 :         // Set point to transform.
     231               0 :         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
     232                 :         {
     233               0 :             padfX[iDstX] = iDstX + 0.5;
     234               0 :             padfY[iDstX] = iDstY + 0.5;
     235               0 :             padfZ[iDstX] = 0.0;
     236                 :         }
     237                 : 
     238                 :         // Transform the points from destination pixel/line coordinates
     239                 :         // to source pixel/line coordinates.
     240                 :         pfnTransform( pTransformArg, TRUE, nDstXSize, 
     241               0 :                       padfX, padfY, padfZ, pabSuccess );
     242                 : 
     243                 :         // Loop over the output scanline.
     244               0 :         for( iDstX = 0; iDstX < nDstXSize; iDstX++ )
     245                 :         {
     246               0 :             if( !pabSuccess[iDstX] )
     247               0 :                 continue;
     248                 : 
     249                 :             // We test against the value before casting to avoid the
     250                 :             // problem of asymmetric truncation effects around zero.  That is
     251                 :             // -0.5 will be 0 when cast to an int. 
     252               0 :             if( padfX[iDstX] < 0.0 || padfY[iDstX] < 0.0 )
     253               0 :                 continue;
     254                 : 
     255                 :             int iSrcX, iSrcY, iSrcOffset;
     256                 : 
     257               0 :             iSrcX = (int) padfX[iDstX];
     258               0 :             iSrcY = (int) padfY[iDstX];
     259                 : 
     260               0 :             if( iSrcX >= nSrcXSize || iSrcY >= nSrcYSize )
     261               0 :                 continue;
     262                 : 
     263               0 :             iSrcOffset = iSrcX + iSrcY * nSrcXSize;
     264                 :             
     265               0 :             for( iBand = 0; iBand < nBandCount; iBand++ )
     266               0 :                 papabyDstLine[iBand][iDstX] = papabySrcData[iBand][iSrcOffset];
     267                 :         }
     268                 : 
     269                 :         // Write scanline to disk. 
     270               0 :         for( iBand = 0; iBand < nBandCount; iBand++ )
     271                 :         {
     272                 :             GDALRasterIO( GDALGetRasterBand(hDstDS,iBand+1), GF_Write,
     273                 :                           0, iDstY, nDstXSize, 1, 
     274               0 :                           papabyDstLine[iBand], nDstXSize, 1, GDT_Byte, 0, 0 );
     275                 :         }
     276                 : 
     277               0 :         if( pfnProgress != NULL )
     278                 :         {
     279               0 :             if( !pfnProgress( (iDstY+1) / (double) nDstYSize, 
     280                 :                               "", pProgressArg ) )
     281                 :             {
     282               0 :                 CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
     283               0 :                 bCancelled = TRUE;
     284               0 :                 break;
     285                 :             }
     286                 :         }
     287                 :     }
     288                 : 
     289                 : /* -------------------------------------------------------------------- */
     290                 : /*      Cleanup working buffers.                                        */
     291                 : /* -------------------------------------------------------------------- */
     292               0 :     for( iBand = 0; iBand < nBandCount; iBand++ )
     293                 :     {
     294               0 :         CPLFree( papabyDstLine[iBand] );
     295               0 :         CPLFree( papabySrcData[iBand] );
     296                 :     }
     297                 : 
     298               0 :     CPLFree( panBandInit );
     299               0 :     CPLFree( papabyDstLine );
     300               0 :     CPLFree( papabySrcData );
     301               0 :     CPLFree( padfX );
     302               0 :     CPLFree( padfY );
     303               0 :     CPLFree( padfZ );
     304               0 :     CPLFree( pabSuccess );
     305                 :     
     306               0 :     return !bCancelled;
     307                 : }
     308                 : 
     309                 : /************************************************************************/
     310                 : /*                      GDALSimpleWarpRemapping()                       */
     311                 : /*                                                                      */
     312                 : /*      This function implements any raster remapping requested in      */
     313                 : /*      the options list.  The remappings are applied to the source     */
     314                 : /*      data before warping.  Two kinds are support ... REMAP           */
     315                 : /*      commands which remap selected pixel values for any band and     */
     316                 : /*      REMAP_MULTI which only remap pixels matching the input in       */
     317                 : /*      all bands at once (ie. to remap an RGB value to another).       */
     318                 : /************************************************************************/
     319                 : 
     320                 : static void 
     321               0 : GDALSimpleWarpRemapping( int nBandCount, GByte **papabySrcData, 
     322                 :                          int nSrcXSize, int nSrcYSize,
     323                 :                          char **papszWarpOptions )
     324                 : 
     325                 : {
     326                 : 
     327                 : /* ==================================================================== */
     328                 : /*      Process any and all single value REMAP commands.                */
     329                 : /* ==================================================================== */
     330                 :     int  iRemap;
     331                 :     char **papszRemaps = CSLFetchNameValueMultiple( papszWarpOptions, 
     332               0 :                                                     "REMAP" );
     333                 : 
     334               0 :     for( iRemap = 0; iRemap < CSLCount(papszRemaps); iRemap++ )
     335                 :     {
     336                 : 
     337                 : /* -------------------------------------------------------------------- */
     338                 : /*      What are the pixel values to map from and to?                   */
     339                 : /* -------------------------------------------------------------------- */
     340               0 :         char **papszTokens = CSLTokenizeString( papszRemaps[iRemap] );
     341                 :         int  nFromValue, nToValue;
     342                 :         
     343               0 :         if( CSLCount(papszTokens) != 2 )
     344                 :         {
     345                 :             CPLError( CE_Warning, CPLE_AppDefined,
     346                 :                       "Ill formed REMAP `%s' ignored in GDALSimpleWarpRemapping()", 
     347               0 :                       papszRemaps[iRemap] );
     348               0 :             continue;
     349                 :         }
     350                 : 
     351               0 :         nFromValue = atoi(papszTokens[0]);
     352               0 :         nToValue = atoi(papszTokens[1]);
     353                 :         
     354               0 :         CSLDestroy( papszTokens );
     355                 : 
     356                 : /* -------------------------------------------------------------------- */
     357                 : /*      Pass over each band searching for matches.                      */
     358                 : /* -------------------------------------------------------------------- */
     359               0 :         for( int iBand = 0; iBand < nBandCount; iBand++ )
     360                 :         {
     361               0 :             GByte *pabyData = papabySrcData[iBand];
     362               0 :             int   nPixelCount = nSrcXSize * nSrcYSize;
     363                 :             
     364               0 :             while( nPixelCount != 0 )
     365                 :             {
     366               0 :                 if( *pabyData == nFromValue )
     367               0 :                     *pabyData = (GByte) nToValue;
     368                 : 
     369               0 :                 pabyData++;
     370               0 :                 nPixelCount--;
     371                 :             }
     372                 :         }
     373                 :     }
     374                 : 
     375               0 :     CSLDestroy( papszRemaps );
     376                 : 
     377                 : /* ==================================================================== */
     378                 : /*      Process any and all REMAP_MULTI commands.                       */
     379                 : /* ==================================================================== */
     380                 :     papszRemaps = CSLFetchNameValueMultiple( papszWarpOptions, 
     381               0 :                                              "REMAP_MULTI" );
     382                 : 
     383               0 :     for( iRemap = 0; iRemap < CSLCount(papszRemaps); iRemap++ )
     384                 :     {
     385                 : /* -------------------------------------------------------------------- */
     386                 : /*      What are the pixel values to map from and to?                   */
     387                 : /* -------------------------------------------------------------------- */
     388               0 :         char **papszTokens = CSLTokenizeString( papszRemaps[iRemap] );
     389                 :         int *panFromValue, *panToValue;
     390                 :         int  nMapBandCount, iBand;
     391                 : 
     392               0 :         if( CSLCount(papszTokens) % 2 == 1 
     393                 :             || CSLCount(papszTokens) == 0 
     394                 :             || CSLCount(papszTokens) > nBandCount * 2 )
     395                 :         {
     396                 :             CPLError( CE_Warning, CPLE_AppDefined,
     397                 :                       "Ill formed REMAP_MULTI `%s' ignored in GDALSimpleWarpRemapping()", 
     398               0 :                       papszRemaps[iRemap] );
     399               0 :             continue;
     400                 :         }
     401                 : 
     402               0 :         nMapBandCount = CSLCount(papszTokens) / 2;
     403                 :         
     404               0 :         panFromValue = (int *) CPLMalloc(sizeof(int) * nMapBandCount );
     405               0 :         panToValue = (int *) CPLMalloc(sizeof(int) * nMapBandCount );
     406                 : 
     407               0 :         for( iBand = 0; iBand < nMapBandCount; iBand++ )
     408                 :         {
     409               0 :             panFromValue[iBand] = atoi(papszTokens[iBand]);
     410               0 :             panToValue[iBand] = atoi(papszTokens[iBand+nMapBandCount]);
     411                 :         }
     412                 : 
     413               0 :         CSLDestroy( papszTokens );
     414                 : 
     415                 : /* -------------------------------------------------------------------- */
     416                 : /*      Search for matching values to replace.                          */
     417                 : /* -------------------------------------------------------------------- */
     418               0 :         int   nPixelCount = nSrcXSize * nSrcYSize;
     419                 :         int   iPixel;
     420                 : 
     421               0 :         for( iPixel = 0; iPixel < nPixelCount; iPixel++ )
     422                 :         {
     423               0 :             if( papabySrcData[0][iPixel] != panFromValue[0] )
     424               0 :                 continue;
     425                 : 
     426               0 :             int bMatch = TRUE;
     427                 : 
     428               0 :             for( iBand = 1; iBand < nMapBandCount; iBand++ )
     429                 :             {
     430               0 :                 if( papabySrcData[iBand][iPixel] != panFromValue[iBand] )
     431               0 :                     bMatch = FALSE;
     432                 :             }
     433                 : 
     434               0 :             if( !bMatch )
     435               0 :                 continue;
     436                 : 
     437               0 :             for( iBand = 0; iBand < nMapBandCount; iBand++ )
     438               0 :                 papabySrcData[iBand][iPixel] = (GByte) panToValue[iBand];
     439                 :         }
     440                 : 
     441               0 :         CPLFree( panFromValue );
     442               0 :         CPLFree( panToValue );
     443                 :     }
     444                 : 
     445               0 :     CSLDestroy( papszRemaps );
     446               0 : }

Generated by: LCOV version 1.7