LCOV - code coverage report
Current view: directory - alg - gdalrasterize.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 323 185 57.3 %
Date: 2010-01-09 Functions: 7 6 85.7 %

       1                 : /******************************************************************************
       2                 :  * $Id: gdalrasterize.cpp 18340 2009-12-19 04:41:45Z chaitanya $
       3                 :  *
       4                 :  * Project:  GDAL
       5                 :  * Purpose:  Vector rasterization.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
      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 <vector>
      31                 : 
      32                 : #include "gdal_alg.h"
      33                 : #include "gdal_alg_priv.h"
      34                 : #include "gdal_priv.h"
      35                 : #include "ogr_api.h"
      36                 : #include "ogr_geometry.h"
      37                 : #include "ogr_spatialref.h"
      38                 : 
      39                 : #ifdef OGR_ENABLED
      40                 : #include "ogrsf_frmts.h"
      41                 : #endif
      42                 : 
      43                 : /************************************************************************/
      44                 : /*                           gvBurnScanline()                           */
      45                 : /************************************************************************/
      46                 : 
      47             361 : void gvBurnScanline( void *pCBData, int nY, int nXStart, int nXEnd,
      48                 :                         double dfVariant )
      49                 : 
      50                 : {
      51             361 :     GDALRasterizeInfo *psInfo = (GDALRasterizeInfo *) pCBData;
      52                 :     int iBand;
      53                 : 
      54             361 :     if( nXStart > nXEnd )
      55               2 :         return;
      56                 : 
      57                 :     CPLAssert( nY >= 0 && nY < psInfo->nYSize );
      58                 :     CPLAssert( nXStart <= nXEnd );
      59                 :     CPLAssert( nXStart < psInfo->nXSize );
      60                 :     CPLAssert( nXEnd >= 0 );
      61                 : 
      62             359 :     if( nXStart < 0 )
      63               0 :         nXStart = 0;
      64             359 :     if( nXEnd >= psInfo->nXSize )
      65               0 :         nXEnd = psInfo->nXSize - 1;
      66                 : 
      67             359 :     if( psInfo->eType == GDT_Byte )
      68                 :     {
      69             900 :         for( iBand = 0; iBand < psInfo->nBands; iBand++ )
      70                 :         {
      71                 :             unsigned char *pabyInsert;
      72                 :             unsigned char nBurnValue = (unsigned char) 
      73             541 :                 ( psInfo->padfBurnValue[iBand] +
      74                 :                   ( (psInfo->eBurnValueSource == GBV_UserBurnValue)?
      75             541 :                              0 : dfVariant ) );
      76                 :             
      77                 :             pabyInsert = psInfo->pabyChunkBuf 
      78                 :                 + iBand * psInfo->nXSize * psInfo->nYSize
      79             541 :                 + nY * psInfo->nXSize + nXStart;
      80                 :                 
      81             541 :             memset( pabyInsert, nBurnValue, nXEnd - nXStart + 1 );
      82                 :         }
      83                 :     }
      84                 :     else
      85                 :     {
      86               0 :         for( iBand = 0; iBand < psInfo->nBands; iBand++ )
      87                 :         {
      88               0 :             int nPixels = nXEnd - nXStart + 1;
      89                 :             float   *pafInsert;
      90                 :             float   fBurnValue = (float)
      91               0 :                 ( psInfo->padfBurnValue[iBand] +
      92                 :                   ( (psInfo->eBurnValueSource == GBV_UserBurnValue)?
      93               0 :                              0 : dfVariant ) );
      94                 :             
      95                 :             pafInsert = ((float *) psInfo->pabyChunkBuf) 
      96                 :                 + iBand * psInfo->nXSize * psInfo->nYSize
      97               0 :                 + nY * psInfo->nXSize + nXStart;
      98                 : 
      99               0 :             while( nPixels-- > 0 )
     100               0 :                 *(pafInsert++) = fBurnValue;
     101                 :         }
     102                 :     }
     103                 : }
     104                 : 
     105                 : /************************************************************************/
     106                 : /*                            gvBurnPoint()                             */
     107                 : /************************************************************************/
     108                 : 
     109             652 : void gvBurnPoint( void *pCBData, int nY, int nX, double dfVariant )
     110                 : 
     111                 : {
     112             652 :     GDALRasterizeInfo *psInfo = (GDALRasterizeInfo *) pCBData;
     113                 :     int iBand;
     114                 : 
     115                 :     CPLAssert( nY >= 0 && nY < psInfo->nYSize );
     116                 :     CPLAssert( nX >= 0 && nX < psInfo->nXSize );
     117                 : 
     118             652 :     if( psInfo->eType == GDT_Byte )
     119                 :     {
     120            2264 :         for( iBand = 0; iBand < psInfo->nBands; iBand++ )
     121                 :         {
     122                 :             unsigned char *pbyInsert = psInfo->pabyChunkBuf 
     123                 :                                       + iBand * psInfo->nXSize * psInfo->nYSize
     124            1612 :                                       + nY * psInfo->nXSize + nX;
     125                 : 
     126            1612 :             *pbyInsert = (unsigned char)( psInfo->padfBurnValue[iBand] +
     127                 :                           ( (psInfo->eBurnValueSource == GBV_UserBurnValue)?
     128            1612 :                              0 : dfVariant ) );
     129                 :         }
     130                 :     }
     131                 :     else
     132                 :     {
     133               0 :         for( iBand = 0; iBand < psInfo->nBands; iBand++ )
     134                 :         {
     135                 :             float   *pfInsert = ((float *) psInfo->pabyChunkBuf) 
     136                 :                                 + iBand * psInfo->nXSize * psInfo->nYSize
     137               0 :                                 + nY * psInfo->nXSize + nX;
     138                 : 
     139               0 :             *pfInsert = (float)( psInfo->padfBurnValue[iBand] +
     140                 :                          ( (psInfo->eBurnValueSource == GBV_UserBurnValue)?
     141               0 :                             0 : dfVariant ) );
     142                 :         }
     143                 :     }
     144             652 : }
     145                 : 
     146                 : /************************************************************************/
     147                 : /*                    GDALCollectRingsFromGeometry()                    */
     148                 : /************************************************************************/
     149                 : 
     150              46 : static void GDALCollectRingsFromGeometry(
     151                 :     OGRGeometry *poShape, 
     152                 :     std::vector<double> &aPointX, std::vector<double> &aPointY, 
     153                 :     std::vector<double> &aPointVariant, 
     154                 :     std::vector<int> &aPartSize, GDALBurnValueSrc eBurnValueSrc)
     155                 : 
     156                 : {
     157              46 :     if( poShape == NULL )
     158               0 :         return;
     159                 : 
     160              46 :     OGRwkbGeometryType eFlatType = wkbFlatten(poShape->getGeometryType());
     161                 :     int i;
     162                 : 
     163              46 :     if ( eFlatType == wkbPoint )
     164                 :     {
     165               0 :         OGRPoint    *poPoint = (OGRPoint *) poShape;
     166               0 :         int nNewCount = aPointX.size() + 1;
     167                 : 
     168               0 :         aPointX.reserve( nNewCount );
     169               0 :         aPointY.reserve( nNewCount );
     170               0 :         aPointX.push_back( poPoint->getX() );
     171               0 :         aPointY.push_back( poPoint->getY() );
     172               0 :         aPartSize.push_back( 1 );
     173               0 :         if( eBurnValueSrc != GBV_UserBurnValue )
     174                 :         {
     175                 :             /*switch( eBurnValueSrc )
     176                 :             {
     177                 :             case GBV_Z:*/
     178               0 :                 aPointVariant.reserve( nNewCount );
     179               0 :                 aPointVariant.push_back( poPoint->getZ() );
     180                 :                 /*break;
     181                 :             case GBV_M:
     182                 :                 aPointVariant.reserve( nNewCount );
     183                 :                 aPointVariant.push_back( poPoint->getM() );
     184                 :             }*/
     185                 :         }
     186                 :     }
     187              46 :     else if ( eFlatType == wkbLineString )
     188                 :     {
     189              24 :         OGRLineString   *poLine = (OGRLineString *) poShape;
     190              24 :         int nCount = poLine->getNumPoints();
     191              24 :         int nNewCount = aPointX.size() + nCount;
     192                 : 
     193              24 :         aPointX.reserve( nNewCount );
     194              24 :         aPointY.reserve( nNewCount );
     195              24 :         if( eBurnValueSrc != GBV_UserBurnValue )
     196               6 :             aPointVariant.reserve( nNewCount );
     197             128 :         for ( i = nCount - 1; i >= 0; i-- )
     198                 :         {
     199             104 :             aPointX.push_back( poLine->getX(i) );
     200             104 :             aPointY.push_back( poLine->getY(i) );
     201             104 :             if( eBurnValueSrc != GBV_UserBurnValue )
     202                 :             {
     203                 :                 /*switch( eBurnValueSrc )
     204                 :                 {
     205                 :                     case GBV_Z:*/
     206              25 :                         aPointVariant.push_back( poLine->getZ(i) );
     207                 :                         /*break;
     208                 :                     case GBV_M:
     209                 :                         aPointVariant.push_back( poLine->getM(i) );
     210                 :                 }*/
     211                 :             }
     212                 :         }
     213              24 :         aPartSize.push_back( nCount );
     214                 :     }
     215              22 :     else if ( EQUAL(poShape->getGeometryName(),"LINEARRING") )
     216                 :     {
     217               0 :         OGRLinearRing *poRing = (OGRLinearRing *) poShape;
     218               0 :         int nCount = poRing->getNumPoints();
     219               0 :         int nNewCount = aPointX.size() + nCount;
     220                 : 
     221               0 :         aPointX.reserve( nNewCount );
     222               0 :         aPointY.reserve( nNewCount );
     223               0 :         if( eBurnValueSrc != GBV_UserBurnValue )
     224               0 :             aPointVariant.reserve( nNewCount );
     225               0 :         for ( i = nCount - 1; i >= 0; i-- )
     226                 :         {
     227               0 :             aPointX.push_back( poRing->getX(i) );
     228               0 :             aPointY.push_back( poRing->getY(i) );
     229                 :         }
     230               0 :         if( eBurnValueSrc != GBV_UserBurnValue )
     231                 :         {
     232                 :             /*switch( eBurnValueSrc )
     233                 :             {
     234                 :             case GBV_Z:*/
     235               0 :                 aPointVariant.push_back( poRing->getZ(i) );
     236                 :                 /*break;
     237                 :             case GBV_M:
     238                 :                 aPointVariant.push_back( poRing->getM(i) );
     239                 :             }*/
     240                 :         }
     241               0 :         aPartSize.push_back( nCount );
     242                 :     }
     243              22 :     else if( eFlatType == wkbPolygon )
     244                 :     {
     245              18 :         OGRPolygon *poPolygon = (OGRPolygon *) poShape;
     246                 :         
     247                 :         GDALCollectRingsFromGeometry( poPolygon->getExteriorRing(), 
     248                 :                                       aPointX, aPointY, aPointVariant, 
     249              18 :                                       aPartSize, eBurnValueSrc );
     250                 : 
     251              20 :         for( i = 0; i < poPolygon->getNumInteriorRings(); i++ )
     252                 :             GDALCollectRingsFromGeometry( poPolygon->getInteriorRing(i), 
     253                 :                                           aPointX, aPointY, aPointVariant, 
     254               2 :                                           aPartSize, eBurnValueSrc );
     255                 :     }
     256                 :     
     257               8 :     else if( eFlatType == wkbMultiPoint
     258                 :              || eFlatType == wkbMultiLineString
     259                 :              || eFlatType == wkbMultiPolygon
     260                 :              || eFlatType == wkbGeometryCollection )
     261                 :     {
     262               4 :         OGRGeometryCollection *poGC = (OGRGeometryCollection *) poShape;
     263                 : 
     264               9 :         for( i = 0; i < poGC->getNumGeometries(); i++ )
     265                 :             GDALCollectRingsFromGeometry( poGC->getGeometryRef(i),
     266                 :                                           aPointX, aPointY, aPointVariant, 
     267               5 :                                           aPartSize, eBurnValueSrc );
     268                 :     }
     269                 :     else
     270                 :     {
     271               0 :         CPLDebug( "GDAL", "Rasterizer ignoring non-polygonal geometry." );
     272                 :     }
     273                 : }
     274                 : 
     275                 : /************************************************************************/
     276                 : /*                       gv_rasterize_one_shape()                       */
     277                 : /************************************************************************/
     278                 : static void 
     279              21 : gv_rasterize_one_shape( unsigned char *pabyChunkBuf, int nYOff,
     280                 :                         int nXSize, int nYSize,
     281                 :                         int nBands, GDALDataType eType, int bAllTouched,
     282                 :                         OGRGeometry *poShape, double *padfBurnValue, 
     283                 :                         GDALBurnValueSrc eBurnValueSrc,
     284                 :                         GDALTransformerFunc pfnTransformer, 
     285                 :                         void *pTransformArg )
     286                 : 
     287                 : {
     288                 :     GDALRasterizeInfo sInfo;
     289                 : 
     290              21 :     sInfo.nXSize = nXSize;
     291              21 :     sInfo.nYSize = nYSize;
     292              21 :     sInfo.nBands = nBands;
     293              21 :     sInfo.pabyChunkBuf = pabyChunkBuf;
     294              21 :     sInfo.eType = eType;
     295              21 :     sInfo.padfBurnValue = padfBurnValue;
     296              21 :     sInfo.eBurnValueSource = eBurnValueSrc;
     297                 : 
     298                 : /* -------------------------------------------------------------------- */
     299                 : /*      Transform polygon geometries into a set of rings and a part     */
     300                 : /*      size list.                                                      */
     301                 : /* -------------------------------------------------------------------- */
     302              21 :     std::vector<double> aPointX;
     303              21 :     std::vector<double> aPointY;
     304              21 :     std::vector<double> aPointVariant;
     305              21 :     std::vector<int> aPartSize;
     306                 : 
     307                 :     GDALCollectRingsFromGeometry( poShape, aPointX, aPointY, aPointVariant,
     308              21 :                                     aPartSize, eBurnValueSrc );
     309                 : 
     310                 : /* -------------------------------------------------------------------- */
     311                 : /*      Transform points if needed.                                     */
     312                 : /* -------------------------------------------------------------------- */
     313              21 :     if( pfnTransformer != NULL )
     314                 :     {
     315              21 :         int *panSuccess = (int *) CPLCalloc(sizeof(int),aPointX.size());
     316                 : 
     317                 :         // TODO: we need to add all appropriate error checking at some point.
     318                 :         pfnTransformer( pTransformArg, FALSE, aPointX.size(), 
     319              21 :                         &(aPointX[0]), &(aPointY[0]), NULL, panSuccess );
     320              21 :         CPLFree( panSuccess );
     321                 :     }
     322                 : 
     323                 : /* -------------------------------------------------------------------- */
     324                 : /*      Shift to account for the buffer offset of this buffer.          */
     325                 : /* -------------------------------------------------------------------- */
     326                 :     unsigned int i;
     327                 : 
     328             125 :     for( i = 0; i < aPointY.size(); i++ )
     329             104 :         aPointY[i] -= nYOff;
     330                 : 
     331                 : /* -------------------------------------------------------------------- */
     332                 : /*      Perform the rasterization.                                      */
     333                 : /*      According to the C++ Standard/23.2.4, elements of a vector are  */
     334                 : /*      stored in continuous memory block.                              */
     335                 : /* -------------------------------------------------------------------- */
     336                 :     unsigned int j,n;
     337                 : 
     338                 :     // TODO - mloskot: Check if vectors are empty, otherwise it may
     339                 :     // lead to undefined behavior by returning non-referencable pointer.
     340                 :     // if (!aPointX.empty())
     341                 :     //    /* fill polygon */
     342                 :     // else
     343                 :     //    /* How to report this problem? */    
     344              21 :     switch ( wkbFlatten(poShape->getGeometryType()) )
     345                 :     {
     346                 :         case wkbPoint:
     347                 :         case wkbMultiPoint:
     348                 :             GDALdllImagePoint( sInfo.nXSize, nYSize, 
     349                 :                                aPartSize.size(), &(aPartSize[0]), 
     350                 :                                &(aPointX[0]), &(aPointY[0]), 
     351                 :                                (eBurnValueSrc == GBV_UserBurnValue)?
     352                 :                                    NULL : &(aPointVariant[0]),
     353               0 :                                gvBurnPoint, &sInfo );
     354               0 :             break;
     355                 :         case wkbLineString:
     356                 :         case wkbMultiLineString:
     357                 :         {
     358               4 :             if( bAllTouched )
     359                 :                 GDALdllImageLineAllTouched( sInfo.nXSize, nYSize, 
     360                 :                                             aPartSize.size(), &(aPartSize[0]), 
     361                 :                                             &(aPointX[0]), &(aPointY[0]), 
     362                 :                                             (eBurnValueSrc == GBV_UserBurnValue)?
     363                 :                                                 NULL : &(aPointVariant[0]),
     364               0 :                                             gvBurnPoint, &sInfo );
     365                 :             else
     366                 :                 GDALdllImageLine( sInfo.nXSize, nYSize, 
     367                 :                                   aPartSize.size(), &(aPartSize[0]), 
     368                 :                                   &(aPointX[0]), &(aPointY[0]), 
     369                 :                                   (eBurnValueSrc == GBV_UserBurnValue)?
     370                 :                                       NULL : &(aPointVariant[0]),
     371               4 :                                   gvBurnPoint, &sInfo );
     372                 :         }
     373               4 :         break;
     374                 : 
     375                 :         default:
     376                 :         {
     377                 :             GDALdllImageFilledPolygon( sInfo.nXSize, nYSize, 
     378                 :                                        aPartSize.size(), &(aPartSize[0]), 
     379                 :                                        &(aPointX[0]), &(aPointY[0]), 
     380                 :                                        (eBurnValueSrc == GBV_UserBurnValue)?
     381                 :                                            NULL : &(aPointVariant[0]),
     382              17 :                                        gvBurnScanline, &sInfo );
     383              17 :             if( bAllTouched )
     384                 :             {
     385                 :                 /* Reverting the variants to the first value because the
     386                 :                    polygon is filled using the variant from the first point of
     387                 :                    the first segment. Should be removed when the code to full
     388                 :                    polygons more appropriately is added. */
     389               7 :                 if(eBurnValueSrc == GBV_UserBurnValue)
     390                 :                 {
     391                 :                 GDALdllImageLineAllTouched( sInfo.nXSize, nYSize, 
     392                 :                                             aPartSize.size(), &(aPartSize[0]), 
     393                 :                                             &(aPointX[0]), &(aPointY[0]), 
     394                 :                                             NULL,
     395               7 :                                             gvBurnPoint, &sInfo );
     396                 :                 }
     397                 :                 else
     398                 :                 {
     399               0 :                 for( i = 0, n = 0; i < aPartSize.size(); i++ )
     400               0 :                     for( j = 0; j < aPartSize[i]; j++ )
     401               0 :                         aPointVariant[n++] = aPointVariant[0];
     402                 :                    
     403                 :                 GDALdllImageLineAllTouched( sInfo.nXSize, nYSize, 
     404                 :                                             aPartSize.size(), &(aPartSize[0]), 
     405                 :                                             &(aPointX[0]), &(aPointY[0]), 
     406                 :                                             &(aPointVariant[0]),
     407               0 :                                             gvBurnPoint, &sInfo );
     408                 :                 }
     409                 :             }
     410                 :         }
     411                 :         break;
     412              21 :     }
     413              21 : }
     414                 : 
     415                 : /************************************************************************/
     416                 : /*                      GDALRasterizeGeometries()                       */
     417                 : /************************************************************************/
     418                 : 
     419                 : /**
     420                 :  * Burn geometries into raster.
     421                 :  *
     422                 :  * Rasterize a list of geometric objects into a raster dataset.  The
     423                 :  * geometries are passed as an array of OGRGeometryH handlers.  
     424                 :  *
     425                 :  * If the geometries are in the georferenced coordinates of the raster
     426                 :  * dataset, then the pfnTransform may be passed in NULL and one will be
     427                 :  * derived internally from the geotransform of the dataset.  The transform
     428                 :  * needs to transform the geometry locations into pixel/line coordinates
     429                 :  * on the raster dataset.
     430                 :  *
     431                 :  * The output raster may be of any GDAL supported datatype, though currently
     432                 :  * internally the burning is done either as GDT_Byte or GDT_Float32.  This
     433                 :  * may be improved in the future.  An explicit list of burn values for
     434                 :  * each geometry for each band must be passed in. 
     435                 :  *
     436                 :  * The papszOption list of options currently only supports one option. The
     437                 :  * "ALL_TOUCHED" option may be enabled by setting it to "TRUE".
     438                 :  *
     439                 :  * @param hDS output data, must be opened in update mode.
     440                 :  * @param nBandCount the number of bands to be updated.
     441                 :  * @param panBandList the list of bands to be updated. 
     442                 :  * @param nGeomCount the number of geometries being passed in pahGeometries.
     443                 :  * @param pahGeometries the array of geometries to burn in. 
     444                 :  * @param pfnTransformer transformation to apply to geometries to put into 
     445                 :  * pixel/line coordinates on raster.  If NULL a geotransform based one will
     446                 :  * be created internally.
     447                 :  * @param pTransformerArg callback data for transformer.
     448                 :  * @param padfGeomBurnValue the array of values to burn into the raster.  
     449                 :  * There should be nBandCount values for each geometry. 
     450                 :  * @param papszOptions special options controlling rasterization
     451                 :  * <dl>
     452                 :  * <dt>"ALL_TOUCHED":</dt> <dd>May be set to TRUE to set all pixels touched 
     453                 :  * by the line or polygons, not just those whose center is within the polygon
     454                 :  * or that are selected by brezenhams line algorithm.  Defaults to FALSE.</dd>
     455                 :  * <dt>"BURN_VALUE_FROM":</dt> <dd>May be set to "Z" to use the Z values of the
     456                 :  * geometries. dfBurnValue is added to this before burning.
     457                 :  * Defaults to GDALBurnValueSrc.GBV_UserBurnValue in which case just the
     458                 :  * dfBurnValue is burned. This is implemented only for points and lines for
     459                 :  * now. The M value may be supported in the future.</dd>
     460                 :  * </dl>
     461                 :  * @param pfnProgress the progress function to report completion.
     462                 :  * @param pProgressArg callback data for progress function.
     463                 :  *
     464                 :  * @return CE_None on success or CE_Failure on error.
     465                 :  */
     466                 : 
     467               8 : CPLErr GDALRasterizeGeometries( GDALDatasetH hDS, 
     468                 :                                 int nBandCount, int *panBandList,
     469                 :                                 int nGeomCount, OGRGeometryH *pahGeometries,
     470                 :                                 GDALTransformerFunc pfnTransformer, 
     471                 :                                 void *pTransformArg, 
     472                 :                                 double *padfGeomBurnValue,
     473                 :                                 char **papszOptions,
     474                 :                                 GDALProgressFunc pfnProgress, 
     475                 :                                 void *pProgressArg )
     476                 : 
     477                 : {
     478                 :     GDALDataType   eType;
     479                 :     int            nYChunkSize, nScanlineBytes;
     480                 :     unsigned char *pabyChunkBuf;
     481                 :     int            iY;
     482               8 :     GDALDataset *poDS = (GDALDataset *) hDS;
     483                 : 
     484               8 :     if( pfnProgress == NULL )
     485               6 :         pfnProgress = GDALDummyProgress;
     486                 : 
     487                 : /* -------------------------------------------------------------------- */
     488                 : /*      Do some rudimentary arg checking.                               */
     489                 : /* -------------------------------------------------------------------- */
     490               8 :     if( nBandCount == 0 || nGeomCount == 0 )
     491               0 :         return CE_None;
     492                 : 
     493                 :     // prototype band.
     494               8 :     GDALRasterBand *poBand = poDS->GetRasterBand( panBandList[0] );
     495               8 :     if (poBand == NULL)
     496               0 :         return CE_Failure;
     497                 : 
     498               8 :     int bAllTouched = CSLFetchBoolean( papszOptions, "ALL_TOUCHED", FALSE );
     499               8 :     const char *pszOpt = CSLFetchNameValue( papszOptions, "BURN_VALUE_FROM" );
     500               8 :     GDALBurnValueSrc eBurnValueSource = GBV_UserBurnValue;
     501               8 :     if( pszOpt )
     502                 :     {
     503               0 :         if( EQUAL(pszOpt,"Z"))
     504               0 :             eBurnValueSource = GBV_Z;
     505                 :         /*else if( EQUAL(pszOpt,"M"))
     506                 :             eBurnValueSource = GBV_M;*/
     507                 :     }
     508                 : 
     509                 : /* -------------------------------------------------------------------- */
     510                 : /*      If we have no transformer, assume the geometries are in file    */
     511                 : /*      georeferenced coordinates, and create a transformer to          */
     512                 : /*      convert that to pixel/line coordinates.                         */
     513                 : /*                                                                      */
     514                 : /*      We really just need to apply an affine transform, but for       */
     515                 : /*      simplicity we use the more general GenImgProjTransformer.       */
     516                 : /* -------------------------------------------------------------------- */
     517               8 :     int bNeedToFreeTransformer = FALSE;
     518                 : 
     519               8 :     if( pfnTransformer == NULL )
     520                 :     {
     521               2 :         bNeedToFreeTransformer = TRUE;
     522                 : 
     523                 :         pTransformArg = 
     524                 :             GDALCreateGenImgProjTransformer( NULL, NULL, hDS, NULL, 
     525               2 :                                              FALSE, 0.0, 0);
     526               2 :         pfnTransformer = GDALGenImgProjTransform;
     527                 :     }
     528                 : 
     529                 : /* -------------------------------------------------------------------- */
     530                 : /*      Establish a chunksize to operate on.  The larger the chunk      */
     531                 : /*      size the less times we need to make a pass through all the      */
     532                 : /*      shapes.                                                         */
     533                 : /* -------------------------------------------------------------------- */
     534               8 :     if( poBand->GetRasterDataType() == GDT_Byte )
     535               8 :         eType = GDT_Byte;
     536                 :     else
     537               0 :         eType = GDT_Float32;
     538                 : 
     539                 :     nScanlineBytes = nBandCount * poDS->GetRasterXSize()
     540               8 :         * (GDALGetDataTypeSize(eType)/8);
     541               8 :     nYChunkSize = 10000000 / nScanlineBytes;
     542               8 :     if( nYChunkSize > poDS->GetRasterYSize() )
     543               8 :         nYChunkSize = poDS->GetRasterYSize();
     544                 : 
     545               8 :     pabyChunkBuf = (unsigned char *) VSIMalloc(nYChunkSize * nScanlineBytes);
     546               8 :     if( pabyChunkBuf == NULL )
     547                 :     {
     548                 :         CPLError( CE_Failure, CPLE_OutOfMemory, 
     549               0 :                   "Unable to allocate rasterization buffer." );
     550               0 :         return CE_Failure;
     551                 :     }
     552                 : 
     553                 : /* ==================================================================== */
     554                 : /*      Loop over image in designated chunks.                           */
     555                 : /* ==================================================================== */
     556               8 :     CPLErr  eErr = CE_None;
     557                 : 
     558               8 :     pfnProgress( 0.0, NULL, pProgressArg );
     559                 : 
     560              16 :     for( iY = 0; 
     561                 :          iY < poDS->GetRasterYSize() && eErr == CE_None; 
     562                 :          iY += nYChunkSize )
     563                 :     {
     564                 :         int nThisYChunkSize;
     565                 :         int     iShape;
     566                 : 
     567               8 :         nThisYChunkSize = nYChunkSize;
     568               8 :         if( nThisYChunkSize + iY > poDS->GetRasterYSize() )
     569               0 :             nThisYChunkSize = poDS->GetRasterYSize() - iY;
     570                 : 
     571                 :         eErr = 
     572                 :             poDS->RasterIO(GF_Read, 
     573                 :                            0, iY, poDS->GetRasterXSize(), nThisYChunkSize, 
     574                 :                            pabyChunkBuf,poDS->GetRasterXSize(),nThisYChunkSize,
     575                 :                            eType, nBandCount, panBandList,
     576               8 :                            0, 0, 0 );
     577               8 :         if( eErr != CE_None )
     578               0 :             break;
     579                 : 
     580              19 :         for( iShape = 0; iShape < nGeomCount; iShape++ )
     581                 :         {
     582                 :             gv_rasterize_one_shape( pabyChunkBuf, iY,
     583                 :                                     poDS->GetRasterXSize(), nThisYChunkSize,
     584                 :                                     nBandCount, eType, bAllTouched,
     585              11 :                                     (OGRGeometry *) pahGeometries[iShape],
     586                 :                                     padfGeomBurnValue + iShape*nBandCount,
     587                 :                                     eBurnValueSource,
     588              22 :                                     pfnTransformer, pTransformArg );
     589                 :         }
     590                 : 
     591                 :         eErr = 
     592                 :             poDS->RasterIO( GF_Write, 0, iY,
     593                 :                             poDS->GetRasterXSize(), nThisYChunkSize, 
     594                 :                             pabyChunkBuf,
     595                 :                             poDS->GetRasterXSize(), nThisYChunkSize, 
     596               8 :                             eType, nBandCount, panBandList, 0, 0, 0 );
     597                 : 
     598               8 :         if( !pfnProgress((iY+nThisYChunkSize)/((double)poDS->GetRasterYSize()),
     599                 :                          "", pProgressArg ) )
     600                 :         {
     601               0 :             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
     602               0 :             eErr = CE_Failure;
     603                 :         }
     604                 :     }
     605                 :     
     606                 : /* -------------------------------------------------------------------- */
     607                 : /*      cleanup                                                         */
     608                 : /* -------------------------------------------------------------------- */
     609               8 :     VSIFree( pabyChunkBuf );
     610                 :     
     611               8 :     if( bNeedToFreeTransformer )
     612               2 :         GDALDestroyTransformer( pTransformArg );
     613                 : 
     614               8 :     return eErr;
     615                 : }
     616                 : 
     617                 : /************************************************************************/
     618                 : /*                        GDALRasterizeLayers()                         */
     619                 : /************************************************************************/
     620                 : 
     621                 : /**
     622                 :  * Burn geometries from the specified list of layers into raster.
     623                 :  *
     624                 :  * Rasterize all the geometric objects from a list of layers into a raster
     625                 :  * dataset.  The layers are passed as an array of OGRLayerH handlers.
     626                 :  *
     627                 :  * If the geometries are in the georferenced coordinates of the raster
     628                 :  * dataset, then the pfnTransform may be passed in NULL and one will be
     629                 :  * derived internally from the geotransform of the dataset.  The transform
     630                 :  * needs to transform the geometry locations into pixel/line coordinates
     631                 :  * on the raster dataset.
     632                 :  *
     633                 :  * The output raster may be of any GDAL supported datatype, though currently
     634                 :  * internally the burning is done either as GDT_Byte or GDT_Float32.  This
     635                 :  * may be improved in the future.  An explicit list of burn values for
     636                 :  * each layer for each band must be passed in. 
     637                 :  *
     638                 :  * @param hDS output data, must be opened in update mode.
     639                 :  * @param nBandCount the number of bands to be updated.
     640                 :  * @param panBandList the list of bands to be updated. 
     641                 :  * @param nLayerCount the number of layers being passed in pahLayers array.
     642                 :  * @param pahLayers the array of layers to burn in. 
     643                 :  * @param pfnTransformer transformation to apply to geometries to put into 
     644                 :  * pixel/line coordinates on raster.  If NULL a geotransform based one will
     645                 :  * be created internally.
     646                 :  * @param pTransformerArg callback data for transformer.
     647                 :  * @param padfLayerBurnValues the array of values to burn into the raster.  
     648                 :  * There should be nBandCount values for each layer. 
     649                 :  * @param papszOption special options controlling rasterization:
     650                 :  * <dl>
     651                 :  * <dt>"ATTRIBUTE":</dt> <dd>Identifies an attribute field on the features to be
     652                 :  * used for a burn in value. The value will be burned into all output
     653                 :  * bands. If specified, padfLayerBurnValues will not be used and can be a NULL
     654                 :  * pointer.</dd>
     655                 :  * <dt>"CHUNKYSIZE":</dt> <dd>The height in lines of the chunk to operate on.
     656                 :  * The larger the chunk size the less times we need to make a pass through all
     657                 :  * the shapes. If it is not set or set to zero the default chunk size will be
     658                 :  * used. Default size will be estimated based on the GDAL cache buffer size
     659                 :  * using formula: cache_size_bytes/scanline_size_bytes, so the chunk will
     660                 :  * not exceed the cache.</dd>
     661                 :  * <dt>"ALL_TOUCHED":</dt> <dd>May be set to TRUE to set all pixels touched 
     662                 :  * by the line or polygons, not just those whose center is within the polygon
     663                 :  * or that are selected by brezenhams line algorithm.  Defaults to FALSE.</dd>
     664                 :  * <dt>"BURN_VALUE_FROM":</dt> <dd>May be set to "Z" to use the Z values of the
     665                 :  * geometries. The value from padfLayerBurnValues or the attribute field value
     666                 :  * is added to this before burning. In default case dfBurnValue is burned as it
     667                 :  * is. This is implemented properly only for points and lines for now. Polygons
     668                 :  * will be burned using the Z value from the first point. The M value may be
     669                 :  * supported in the future.</dd>
     670                 :  * @param pfnProgress the progress function to report completion.
     671                 :  * @param pProgressArg callback data for progress function.
     672                 :  *
     673                 :  * @return CE_None on success or CE_Failure on error.
     674                 :  */
     675                 : 
     676                 : #ifdef OGR_ENABLED
     677                 : 
     678               3 : CPLErr GDALRasterizeLayers( GDALDatasetH hDS, 
     679                 :                             int nBandCount, int *panBandList,
     680                 :                             int nLayerCount, OGRLayerH *pahLayers,
     681                 :                             GDALTransformerFunc pfnTransformer, 
     682                 :                             void *pTransformArg, 
     683                 :                             double *padfLayerBurnValues,
     684                 :                             char **papszOptions,
     685                 :                             GDALProgressFunc pfnProgress, 
     686                 :                             void *pProgressArg )
     687                 : 
     688                 : {
     689                 :     GDALDataType   eType;
     690                 :     unsigned char *pabyChunkBuf;
     691               3 :     GDALDataset *poDS = (GDALDataset *) hDS;
     692                 : 
     693               3 :     if( pfnProgress == NULL )
     694               3 :         pfnProgress = GDALDummyProgress;
     695                 : 
     696                 : /* -------------------------------------------------------------------- */
     697                 : /*      Do some rudimentary arg checking.                               */
     698                 : /* -------------------------------------------------------------------- */
     699               3 :     if( nBandCount == 0 || nLayerCount == 0 )
     700               0 :         return CE_None;
     701                 : 
     702                 :     // prototype band.
     703               3 :     GDALRasterBand *poBand = poDS->GetRasterBand( panBandList[0] );
     704               3 :     if (poBand == NULL)
     705               0 :         return CE_Failure;
     706                 : 
     707               3 :     int bAllTouched = CSLFetchBoolean( papszOptions, "ALL_TOUCHED", FALSE );
     708               3 :     const char *pszOpt = CSLFetchNameValue( papszOptions, "BURN_VALUE_FROM" );
     709               3 :     GDALBurnValueSrc eBurnValueSource = GBV_UserBurnValue;
     710               3 :     if( pszOpt )
     711                 :     {
     712               1 :         if( EQUAL(pszOpt,"Z"))
     713               1 :             eBurnValueSource = GBV_Z;
     714                 :         /*else if( EQUAL(pszOpt,"M"))
     715                 :             eBurnValueSource = GBV_M;*/
     716                 :     }
     717                 : 
     718                 : /* -------------------------------------------------------------------- */
     719                 : /*      Establish a chunksize to operate on.  The larger the chunk      */
     720                 : /*      size the less times we need to make a pass through all the      */
     721                 : /*      shapes.                                                         */
     722                 : /* -------------------------------------------------------------------- */
     723                 :     int         nYChunkSize, nScanlineBytes;
     724                 :     const char  *pszYChunkSize =
     725               3 :         CSLFetchNameValue( papszOptions, "CHUNKYSIZE" );
     726                 : 
     727               3 :     if( poBand->GetRasterDataType() == GDT_Byte )
     728               3 :         eType = GDT_Byte;
     729                 :     else
     730               0 :         eType = GDT_Float32;
     731                 : 
     732                 :     nScanlineBytes = nBandCount * poDS->GetRasterXSize()
     733               3 :         * (GDALGetDataTypeSize(eType)/8);
     734                 : 
     735               3 :     if ( pszYChunkSize && (nYChunkSize = atoi(pszYChunkSize)) )
     736                 :         ;
     737                 :     else
     738               3 :         nYChunkSize = GDALGetCacheMax() / nScanlineBytes;
     739                 : 
     740               3 :     if( nYChunkSize > poDS->GetRasterYSize() )
     741               3 :         nYChunkSize = poDS->GetRasterYSize();
     742                 : 
     743               3 :     pabyChunkBuf = (unsigned char *) VSIMalloc(nYChunkSize * nScanlineBytes);
     744               3 :     if( pabyChunkBuf == NULL )
     745                 :     {
     746                 :         CPLError( CE_Failure, CPLE_OutOfMemory, 
     747               0 :                   "Unable to allocate rasterization buffer." );
     748               0 :         return CE_Failure;
     749                 :     }
     750                 : 
     751                 : /* -------------------------------------------------------------------- */
     752                 : /*      Read the image once for all layers if user requested to render  */
     753                 : /*      the whole raster in single chunk.                               */
     754                 : /* -------------------------------------------------------------------- */
     755               3 :     if ( nYChunkSize == poDS->GetRasterYSize() )
     756                 :     {
     757               3 :         if ( poDS->RasterIO( GF_Read, 0, 0, poDS->GetRasterXSize(),
     758                 :                              nYChunkSize, pabyChunkBuf,
     759                 :                              poDS->GetRasterXSize(), nYChunkSize,
     760                 :                              eType, nBandCount, panBandList, 0, 0, 0 )
     761                 :              != CE_None )
     762                 :         {
     763                 :             CPLError( CE_Failure, CPLE_OutOfMemory, 
     764               0 :                       "Unable to read buffer." );
     765               0 :             CPLFree( pabyChunkBuf );
     766               0 :             return CE_Failure;
     767                 :         }
     768                 :     }
     769                 : 
     770                 : /* ==================================================================== */
     771                 : /*      Read the specified layers transfoming and rasterizing           */
     772                 : /*      geometries.                                                     */
     773                 : /* ==================================================================== */
     774               3 :     CPLErr      eErr = CE_None;
     775                 :     int         iLayer;
     776                 :     const char  *pszBurnAttribute =
     777               3 :         CSLFetchNameValue( papszOptions, "ATTRIBUTE" );
     778                 : 
     779               3 :     pfnProgress( 0.0, NULL, pProgressArg );
     780                 : 
     781               6 :     for( iLayer = 0; iLayer < nLayerCount; iLayer++ )
     782                 :     {
     783               3 :         int         iBurnField = -1;
     784               3 :         double      *padfBurnValues = NULL;
     785               3 :         OGRLayer    *poLayer = (OGRLayer *) pahLayers[iLayer];
     786                 : 
     787               3 :         if ( !poLayer )
     788                 :         {
     789                 :             CPLError( CE_Warning, CPLE_AppDefined, 
     790               0 :                       "Layer element number %d is NULL, skipping.\n", iLayer );
     791               0 :             continue;
     792                 :         }
     793                 : 
     794                 : /* -------------------------------------------------------------------- */
     795                 : /*      If the layer does not contain any features just skip it.        */
     796                 : /*      Do not force the feature count, so if driver doesn't know       */
     797                 : /*      exact number of features, go down the normal way.               */
     798                 : /* -------------------------------------------------------------------- */
     799               3 :         if ( poLayer->GetFeatureCount(FALSE) == 0 )
     800               0 :             continue;
     801                 : 
     802               3 :         if ( pszBurnAttribute )
     803                 :         {
     804                 :             iBurnField =
     805               0 :                 poLayer->GetLayerDefn()->GetFieldIndex( pszBurnAttribute );
     806               0 :             if ( iBurnField == -1 )
     807                 :             {
     808                 :                 CPLError( CE_Warning, CPLE_AppDefined, 
     809                 :                           "Failed to find field %s on layer %s, skipping.\n",
     810                 :                           pszBurnAttribute, 
     811               0 :                           poLayer->GetLayerDefn()->GetName() );
     812               0 :                 continue;
     813                 :             }
     814                 :         }
     815                 :         else
     816               3 :             padfBurnValues = padfLayerBurnValues + iLayer * nBandCount;
     817                 : 
     818                 : /* -------------------------------------------------------------------- */
     819                 : /*      If we have no transformer, create the one from input file       */
     820                 : /*      projection. Note that each layer can be georefernced            */
     821                 : /*      separately.                                                     */
     822                 : /* -------------------------------------------------------------------- */
     823               3 :         int bNeedToFreeTransformer = FALSE;
     824                 : 
     825               3 :         if( pfnTransformer == NULL )
     826                 :         {
     827               3 :             char    *pszProjection = NULL;
     828               3 :             bNeedToFreeTransformer = TRUE;
     829                 : 
     830               3 :             OGRSpatialReference *poSRS = poLayer->GetSpatialRef();
     831               3 :             if ( !poSRS )
     832                 :             {
     833                 :                 CPLError( CE_Warning, CPLE_AppDefined, 
     834                 :                           "Failed to fetch spatial reference on layer %s "
     835                 :                           "to build transformer, assuming matching coordinate systems.\n",
     836               1 :                           poLayer->GetLayerDefn()->GetName() );
     837                 :             }
     838                 :             else
     839               2 :                 poSRS->exportToWkt( &pszProjection );
     840                 : 
     841                 :             pTransformArg = 
     842                 :                 GDALCreateGenImgProjTransformer( NULL, pszProjection,
     843               3 :                                                  hDS, NULL, FALSE, 0.0, 0 );
     844               3 :             pfnTransformer = GDALGenImgProjTransform;
     845                 : 
     846               3 :             CPLFree( pszProjection );
     847                 :         }
     848                 : 
     849                 :         OGRFeature *poFeat;
     850                 : 
     851               3 :         poLayer->ResetReading();
     852                 : 
     853                 : /* -------------------------------------------------------------------- */
     854                 : /*      Loop over image in designated chunks.                           */
     855                 : /* -------------------------------------------------------------------- */
     856                 :         int     iY;
     857               6 :         for( iY = 0; 
     858                 :              iY < poDS->GetRasterYSize() && eErr == CE_None; 
     859                 :              iY += nYChunkSize )
     860                 :         {
     861                 :             int nThisYChunkSize;
     862                 : 
     863               3 :             nThisYChunkSize = nYChunkSize;
     864               3 :             if( nThisYChunkSize + iY > poDS->GetRasterYSize() )
     865               0 :                 nThisYChunkSize = poDS->GetRasterYSize() - iY;
     866                 : 
     867                 :             // Only re-read image if not a single chunk is being rendered
     868               3 :             if ( nYChunkSize < poDS->GetRasterYSize() )
     869                 :             {
     870                 :                 eErr = 
     871                 :                     poDS->RasterIO( GF_Read, 0, iY,
     872                 :                                     poDS->GetRasterXSize(), nThisYChunkSize, 
     873                 :                                     pabyChunkBuf,
     874                 :                                     poDS->GetRasterXSize(), nThisYChunkSize,
     875               0 :                                     eType, nBandCount, panBandList, 0, 0, 0 );
     876               0 :                 if( eErr != CE_None )
     877               0 :                     break;
     878                 :             }
     879                 : 
     880              16 :             while( (poFeat = poLayer->GetNextFeature()) != NULL )
     881                 :             {
     882              10 :                 OGRGeometry *poGeom = poFeat->GetGeometryRef();
     883                 :                 double      dfBurnValue;
     884                 : 
     885              10 :                 if ( pszBurnAttribute )
     886                 :                 {
     887               0 :                     dfBurnValue = poFeat->GetFieldAsDouble( iBurnField );
     888               0 :                     padfBurnValues = &dfBurnValue;
     889                 :                 }
     890                 :                 
     891                 :                 gv_rasterize_one_shape( pabyChunkBuf, iY,
     892                 :                                         poDS->GetRasterXSize(),
     893                 :                                         nThisYChunkSize,
     894                 :                                         nBandCount, eType, bAllTouched, poGeom,
     895                 :                                         padfBurnValues, eBurnValueSource,
     896              10 :                                         pfnTransformer, pTransformArg );
     897                 : 
     898              10 :                 delete poFeat;
     899                 :             }
     900                 : 
     901                 :             // Only write image if not a single chunk is being rendered
     902               3 :             if ( nYChunkSize < poDS->GetRasterYSize() )
     903                 :             {
     904                 :                 eErr = 
     905                 :                     poDS->RasterIO( GF_Write, 0, iY,
     906                 :                                     poDS->GetRasterXSize(), nThisYChunkSize, 
     907                 :                                     pabyChunkBuf,
     908                 :                                     poDS->GetRasterXSize(), nThisYChunkSize, 
     909               0 :                                     eType, nBandCount, panBandList, 0, 0, 0 );
     910                 :             }
     911                 : 
     912               3 :             poLayer->ResetReading();
     913                 : 
     914               3 :             if( !pfnProgress((iY+nThisYChunkSize)/((double)poDS->GetRasterYSize()),
     915                 :                              "", pProgressArg) )
     916                 :             {
     917               0 :                 CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
     918               0 :                 eErr = CE_Failure;
     919                 :             }
     920                 :         }
     921                 : 
     922               3 :         if ( bNeedToFreeTransformer )
     923                 :         {
     924               3 :             GDALDestroyTransformer( pTransformArg );
     925               3 :             pTransformArg = NULL;
     926               3 :             pfnTransformer = NULL;
     927                 :         }
     928                 :     }
     929                 :     
     930                 : /* -------------------------------------------------------------------- */
     931                 : /*      Write out the image once for all layers if user requested       */
     932                 : /*      to render the whole raster in single chunk.                     */
     933                 : /* -------------------------------------------------------------------- */
     934               3 :     if ( nYChunkSize == poDS->GetRasterYSize() )
     935                 :     {
     936                 :         poDS->RasterIO( GF_Write, 0, 0,
     937                 :                                 poDS->GetRasterXSize(), nYChunkSize, 
     938                 :                                 pabyChunkBuf,
     939                 :                                 poDS->GetRasterXSize(), nYChunkSize, 
     940               3 :                                 eType, nBandCount, panBandList, 0, 0, 0 );
     941                 :     }
     942                 : 
     943                 : /* -------------------------------------------------------------------- */
     944                 : /*      cleanup                                                         */
     945                 : /* -------------------------------------------------------------------- */
     946               3 :     VSIFree( pabyChunkBuf );
     947                 :     
     948               3 :     return eErr;
     949                 : }
     950                 : 
     951                 : #endif /* def OGR_ENABLED */
     952                 : 
     953                 : /************************************************************************/
     954                 : /*                        GDALRasterizeLayersBuf()                      */
     955                 : /************************************************************************/
     956                 : 
     957                 : /**
     958                 :  * Burn geometries from the specified list of layer into raster.
     959                 :  *
     960                 :  * Rasterize all the geometric objects from a list of layers into supplied
     961                 :  * raster buffer.  The layers are passed as an array of OGRLayerH handlers.
     962                 :  *
     963                 :  * If the geometries are in the georferenced coordinates of the raster
     964                 :  * dataset, then the pfnTransform may be passed in NULL and one will be
     965                 :  * derived internally from the geotransform of the dataset.  The transform
     966                 :  * needs to transform the geometry locations into pixel/line coordinates
     967                 :  * of the target raster.
     968                 :  *
     969                 :  * The output raster may be of any GDAL supported datatype, though currently
     970                 :  * internally the burning is done either as GDT_Byte or GDT_Float32.  This
     971                 :  * may be improved in the future. 
     972                 :  *
     973                 :  * @param pData pointer to the output data array.
     974                 :  *
     975                 :  * @param nBufXSize width of the output data array in pixels.
     976                 :  *
     977                 :  * @param nBufYSize height of the output data array in pixels. 
     978                 :  *
     979                 :  * @param eBufType data type of the output data array.
     980                 :  *
     981                 :  * @param nPixelSpace The byte offset from the start of one pixel value in
     982                 :  * pData to the start of the next pixel value within a scanline.  If defaulted
     983                 :  * (0) the size of the datatype eBufType is used.
     984                 :  *
     985                 :  * @param nLineSpace The byte offset from the start of one scanline in
     986                 :  * pData to the start of the next.  If defaulted the size of the datatype
     987                 :  * eBufType * nBufXSize is used.
     988                 :  *
     989                 :  * @param nLayerCount the number of layers being passed in pahLayers array.
     990                 :  *
     991                 :  * @param pahLayers the array of layers to burn in. 
     992                 :  *
     993                 :  * @param pszDstProjection WKT defining the coordinate system of the target
     994                 :  * raster.
     995                 :  *
     996                 :  * @param padfDstGeoTransform geotransformation matrix of the target raster.
     997                 :  *
     998                 :  * @param pfnTransformer transformation to apply to geometries to put into 
     999                 :  * pixel/line coordinates on raster.  If NULL a geotransform based one will
    1000                 :  * be created internally.
    1001                 :  *
    1002                 :  * @param pTransformerArg callback data for transformer.
    1003                 :  *
    1004                 :  * @param dfBurnValue the value to burn into the raster.  
    1005                 :  *
    1006                 :  * @param papszOption special options controlling rasterization:
    1007                 :  * <dl>
    1008                 :  * <dt>"ATTRIBUTE":</dt> <dd>Identifies an attribute field on the features to be
    1009                 :  * used for a burn in value. The value will be burned into all output
    1010                 :  * bands. If specified, padfLayerBurnValues will not be used and can be a NULL
    1011                 :  * pointer.</dd>
    1012                 :  * <dt>"ALL_TOUCHED":</dt> <dd>May be set to TRUE to set all pixels touched 
    1013                 :  * by the line or polygons, not just those whose center is within the polygon
    1014                 :  * or that are selected by brezenhams line algorithm.  Defaults to FALSE.</dd>
    1015                 :  * </dl>
    1016                 :  * <dt>"BURN_VALUE_FROM":</dt> <dd>May be set to "Z" to use
    1017                 :  * the Z values of the geometries. dfBurnValue or the attribute field value is
    1018                 :  * added to this before burning. In default case dfBurnValue is burned as it
    1019                 :  * is. This is implemented properly only for points and lines for now. Polygons
    1020                 :  * will be burned using the Z value from the first point. The M value may
    1021                 :  * be supported in the future.</dd>
    1022                 :  * </dl>
    1023                 :  *
    1024                 :  * @param pfnProgress the progress function to report completion.
    1025                 :  *
    1026                 :  * @param pProgressArg callback data for progress function.
    1027                 :  *
    1028                 :  *
    1029                 :  * @return CE_None on success or CE_Failure on error.
    1030                 :  */
    1031                 : 
    1032                 : #ifdef OGR_ENABLED
    1033                 : 
    1034               0 : CPLErr GDALRasterizeLayersBuf( void *pData, int nBufXSize, int nBufYSize,
    1035                 :                                GDALDataType eBufType,
    1036                 :                                int nPixelSpace, int nLineSpace,
    1037                 :                                int nLayerCount, OGRLayerH *pahLayers,
    1038                 :                                const char *pszDstProjection,
    1039                 :                                double *padfDstGeoTransform,
    1040                 :                                GDALTransformerFunc pfnTransformer, 
    1041                 :                                void *pTransformArg, double dfBurnValue,
    1042                 :                                char **papszOptions,
    1043                 :                                GDALProgressFunc pfnProgress,
    1044                 :                                void *pProgressArg )
    1045                 : 
    1046                 : {
    1047                 : /* -------------------------------------------------------------------- */
    1048                 : /*      If pixel and line spaceing are defaulted assign reasonable      */
    1049                 : /*      value assuming a packed buffer.                                 */
    1050                 : /* -------------------------------------------------------------------- */
    1051               0 :     if( nPixelSpace == 0 )
    1052               0 :         nPixelSpace = GDALGetDataTypeSize( eBufType ) / 8;
    1053                 :     
    1054               0 :     if( nLineSpace == 0 )
    1055               0 :         nLineSpace = nPixelSpace * nBufXSize;
    1056                 : 
    1057               0 :     if( pfnProgress == NULL )
    1058               0 :         pfnProgress = GDALDummyProgress;
    1059                 : 
    1060                 : /* -------------------------------------------------------------------- */
    1061                 : /*      Do some rudimentary arg checking.                               */
    1062                 : /* -------------------------------------------------------------------- */
    1063               0 :     if( nLayerCount == 0 )
    1064               0 :         return CE_None;
    1065                 : 
    1066               0 :     int bAllTouched = CSLFetchBoolean( papszOptions, "ALL_TOUCHED", FALSE );
    1067               0 :     const char *pszOpt = CSLFetchNameValue( papszOptions, "BURN_VALUE_FROM" );
    1068               0 :     GDALBurnValueSrc eBurnValueSource = GBV_UserBurnValue;
    1069               0 :     if( pszOpt )
    1070                 :     {
    1071               0 :         if( EQUAL(pszOpt,"Z"))
    1072               0 :             eBurnValueSource = GBV_Z;
    1073                 :         /*else if( EQUAL(pszOpt,"M"))
    1074                 :             eBurnValueSource = GBV_M;*/
    1075                 :     }
    1076                 : 
    1077                 : /* ==================================================================== */
    1078                 : /*      Read thes pecified layers transfoming and rasterizing           */
    1079                 : /*      geometries.                                                     */
    1080                 : /* ==================================================================== */
    1081               0 :     CPLErr      eErr = CE_None;
    1082                 :     int         iLayer;
    1083                 :     const char  *pszBurnAttribute =
    1084               0 :         CSLFetchNameValue( papszOptions, "ATTRIBUTE" );
    1085                 : 
    1086               0 :     pfnProgress( 0.0, NULL, pProgressArg );
    1087                 : 
    1088               0 :     for( iLayer = 0; iLayer < nLayerCount; iLayer++ )
    1089                 :     {
    1090               0 :         int         iBurnField = -1;
    1091               0 :         OGRLayer    *poLayer = (OGRLayer *) pahLayers[iLayer];
    1092                 : 
    1093               0 :         if ( !poLayer )
    1094                 :         {
    1095                 :             CPLError( CE_Warning, CPLE_AppDefined, 
    1096               0 :                       "Layer element number %d is NULL, skipping.\n", iLayer );
    1097               0 :             continue;
    1098                 :         }
    1099                 : 
    1100                 : /* -------------------------------------------------------------------- */
    1101                 : /*      If the layer does not contain any features just skip it.        */
    1102                 : /*      Do not force the feature count, so if driver doesn't know       */
    1103                 : /*      exact number of features, go down the normal way.               */
    1104                 : /* -------------------------------------------------------------------- */
    1105               0 :         if ( poLayer->GetFeatureCount(FALSE) == 0 )
    1106               0 :             continue;
    1107                 : 
    1108               0 :         if ( pszBurnAttribute )
    1109                 :         {
    1110                 :             iBurnField =
    1111               0 :                 poLayer->GetLayerDefn()->GetFieldIndex( pszBurnAttribute );
    1112               0 :             if ( iBurnField == -1 )
    1113                 :             {
    1114                 :                 CPLError( CE_Warning, CPLE_AppDefined, 
    1115                 :                           "Failed to find field %s on layer %s, skipping.\n",
    1116                 :                           pszBurnAttribute, 
    1117               0 :                           poLayer->GetLayerDefn()->GetName() );
    1118               0 :                 continue;
    1119                 :             }
    1120                 :         }
    1121                 : 
    1122                 : /* -------------------------------------------------------------------- */
    1123                 : /*      If we have no transformer, create the one from input file       */
    1124                 : /*      projection. Note that each layer can be georefernced            */
    1125                 : /*      separately.                                                     */
    1126                 : /* -------------------------------------------------------------------- */
    1127               0 :         int bNeedToFreeTransformer = FALSE;
    1128                 : 
    1129               0 :         if( pfnTransformer == NULL )
    1130                 :         {
    1131               0 :             char    *pszProjection = NULL;
    1132               0 :             bNeedToFreeTransformer = TRUE;
    1133                 : 
    1134               0 :             OGRSpatialReference *poSRS = poLayer->GetSpatialRef();
    1135               0 :             if ( !poSRS )
    1136                 :             {
    1137                 :                 CPLError( CE_Warning, CPLE_AppDefined, 
    1138                 :                           "Failed to fetch spatial reference on layer %s "
    1139                 :                           "to build transformer, assuming matching coordinate systems.\n",
    1140               0 :                           poLayer->GetLayerDefn()->GetName() );
    1141                 :             }
    1142                 :             else
    1143               0 :                 poSRS->exportToWkt( &pszProjection );
    1144                 : 
    1145                 :             pTransformArg =
    1146                 :                 GDALCreateGenImgProjTransformer3( pszProjection, NULL,
    1147                 :                                                   pszDstProjection,
    1148               0 :                                                   padfDstGeoTransform );
    1149               0 :             pfnTransformer = GDALGenImgProjTransform;
    1150                 : 
    1151               0 :             CPLFree( pszProjection );
    1152                 :         }
    1153                 : 
    1154                 :         OGRFeature *poFeat;
    1155                 : 
    1156               0 :         poLayer->ResetReading();
    1157                 : 
    1158               0 :         while( (poFeat = poLayer->GetNextFeature()) != NULL )
    1159                 :         {
    1160               0 :             OGRGeometry *poGeom = poFeat->GetGeometryRef();
    1161                 : 
    1162               0 :             if ( pszBurnAttribute )
    1163               0 :                 dfBurnValue = poFeat->GetFieldAsDouble( iBurnField );
    1164                 :             
    1165                 :             gv_rasterize_one_shape( (unsigned char *) pData, 0,
    1166                 :                                     nBufXSize, nBufYSize,
    1167                 :                                     1, eBufType, bAllTouched, poGeom,
    1168                 :                                     &dfBurnValue, eBurnValueSource,
    1169               0 :                                     pfnTransformer, pTransformArg );
    1170                 : 
    1171               0 :             delete poFeat;
    1172                 :         }
    1173                 : 
    1174               0 :         poLayer->ResetReading();
    1175                 : 
    1176               0 :         if( !pfnProgress(1, "", pProgressArg) )
    1177                 :         {
    1178               0 :             CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
    1179               0 :             eErr = CE_Failure;
    1180                 :         }
    1181                 : 
    1182               0 :         if ( bNeedToFreeTransformer )
    1183                 :         {
    1184               0 :             GDALDestroyTransformer( pTransformArg );
    1185               0 :             pTransformArg = NULL;
    1186               0 :             pfnTransformer = NULL;
    1187                 :         }
    1188                 :     }
    1189                 :     
    1190               0 :     return eErr;
    1191                 : }
    1192                 : 
    1193                 : #endif /* def OGR_ENABLED */

Generated by: LCOV version 1.7