LCOV - code coverage report
Current view: directory - frmts/vrt - vrtderivedrasterband.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 104 0 0.0 %
Date: 2010-01-09 Functions: 12 0 0.0 %

       1                 : /******************************************************************************
       2                 :  *
       3                 :  * Project:  Virtual GDAL Datasets
       4                 :  * Purpose:  Implementation of a sourced raster band that derives its raster
       5                 :  *           by applying an algorithm (GDALDerivedPixelFunc) to the sources.
       6                 :  * Author:   Pete Nagy
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2005 Vexcel Corp.
      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 "vrtdataset.h"
      31                 : #include "cpl_minixml.h"
      32                 : #include "cpl_string.h"
      33                 : 
      34                 : /************************************************************************/
      35                 : /* ==================================================================== */
      36                 : /*                          VRTDerivedRasterBand                        */
      37                 : /* ==================================================================== */
      38                 : /************************************************************************/
      39                 : 
      40                 : static int nFunctions = 0;
      41                 : static GDALDerivedPixelFunc *papfnPixelFunctions = NULL;
      42                 : static char **papszNames = NULL;
      43                 : 
      44                 : /************************************************************************/
      45                 : /*                        VRTDerivedRasterBand()                        */
      46                 : /************************************************************************/
      47                 : 
      48               0 : VRTDerivedRasterBand::VRTDerivedRasterBand(GDALDataset *poDS, int nBand)
      49               0 :     : VRTSourcedRasterBand( poDS, nBand )
      50                 : 
      51                 : {
      52               0 :     this->pszFuncName = NULL;
      53               0 :     this->eSourceTransferType = GDT_Unknown;
      54               0 : }
      55                 : 
      56                 : /************************************************************************/
      57                 : /*                        VRTDerivedRasterBand()                        */
      58                 : /************************************************************************/
      59                 : 
      60               0 : VRTDerivedRasterBand::VRTDerivedRasterBand(GDALDataset *poDS, int nBand,
      61                 :              GDALDataType eType, 
      62                 :              int nXSize, int nYSize)
      63               0 :     : VRTSourcedRasterBand(poDS, nBand, eType, nXSize, nYSize)
      64                 : 
      65                 : {
      66               0 :     this->pszFuncName = NULL;
      67               0 :     this->eSourceTransferType = GDT_Unknown;
      68               0 : }
      69                 : 
      70                 : /************************************************************************/
      71                 : /*                       ~VRTDerivedRasterBand()                        */
      72                 : /************************************************************************/
      73                 : 
      74               0 : VRTDerivedRasterBand::~VRTDerivedRasterBand()
      75                 : 
      76                 : {
      77               0 :     if (this->pszFuncName != NULL) {
      78               0 :         CPLFree(this->pszFuncName);
      79               0 :         this->pszFuncName = NULL;
      80                 :     }
      81               0 : }
      82                 : 
      83                 : /************************************************************************/
      84                 : /*                           AddPixelFunction()                         */
      85                 : /************************************************************************/
      86                 : 
      87                 : /**
      88                 :  * This adds a pixel function to the global list of available pixel
      89                 :  * functions for derived bands.  Pixel functions must be registered
      90                 :  * in this way before a derived band tries to access data.
      91                 :  *
      92                 :  * Derived bands are stored with only the name of the pixel function 
      93                 :  * that it will apply, and if a pixel function matching the name is not
      94                 :  * found the IRasterIO() call will do nothing.
      95                 :  *
      96                 :  * @param pszFuncName Name used to access pixel function
      97                 :  * @param pfnNewFunction Pixel function associated with name.  An
      98                 :  *  existing pixel function registered with the same name will be
      99                 :  *  replaced with the new one.
     100                 :  *
     101                 :  * @return CE_None, invalid (NULL) parameters are currently ignored.
     102                 :  */
     103               0 : CPLErr CPL_STDCALL GDALAddDerivedBandPixelFunc
     104                 : (const char *pszFuncName, GDALDerivedPixelFunc pfnNewFunction)
     105                 : {
     106                 :     int ii;
     107                 : 
     108                 :     /* ---- Init ---- */
     109               0 :     if ((pszFuncName == NULL) || (pfnNewFunction == NULL)) {
     110               0 :   return CE_None;
     111                 :     }
     112                 : 
     113                 :     /* ---- Check for match with fn already on list, and replace ---- */
     114               0 :     for (ii = 0; ii < nFunctions; ii++) {
     115               0 :   if (strcmp(pszFuncName, papszNames[ii]) == 0) {
     116               0 :       papfnPixelFunctions[ii] = pfnNewFunction;
     117               0 :       return CE_None;
     118                 :   }
     119                 :     }
     120                 : 
     121                 :     /* ---- Increment pixel function counter and add name/fn to lists ---- */
     122               0 :     nFunctions++;
     123                 : 
     124                 :     papfnPixelFunctions = (GDALDerivedPixelFunc *) 
     125               0 :         CPLRealloc(papfnPixelFunctions, sizeof(void*) * nFunctions);
     126               0 :     papfnPixelFunctions[nFunctions - 1] = pfnNewFunction;
     127                 : 
     128                 :     papszNames = (char **)
     129               0 :   CPLRealloc(papszNames, sizeof(void*) * nFunctions);
     130               0 :     papszNames[nFunctions - 1] = (char *)pszFuncName;
     131                 : 
     132               0 :     return CE_None;
     133                 : }
     134                 : /**
     135                 :  * This adds a pixel function to the global list of available pixel
     136                 :  * functions for derived bands.
     137                 :  *
     138                 :  * This is the same as the c function GDALAddDerivedBandPixelFunc()
     139                 :  *
     140                 :  * @param pszFuncName Name used to access pixel function
     141                 :  * @param pfnNewFunction Pixel function associated with name.  An
     142                 :  *  existing pixel function registered with the same name will be
     143                 :  *  replaced with the new one.
     144                 :  *
     145                 :  * @return CE_None, invalid (NULL) parameters are currently ignored.
     146                 :  */
     147               0 : CPLErr VRTDerivedRasterBand::AddPixelFunction
     148                 : (const char *pszFuncName, GDALDerivedPixelFunc pfnNewFunction)
     149                 : {
     150               0 :     return GDALAddDerivedBandPixelFunc(pszFuncName, pfnNewFunction);
     151                 : }
     152                 : 
     153                 : /************************************************************************/
     154                 : /*                           GetPixelFunction()                         */
     155                 : /************************************************************************/
     156                 : 
     157                 : /**
     158                 :  * Get a pixel function previously registered using the global
     159                 :  * AddPixelFunction.
     160                 :  *
     161                 :  * @param pszFuncName The name associated with the pixel function.
     162                 :  *
     163                 :  * @return A derived band pixel function, or NULL if none have been
     164                 :  * registered for pszFuncName.
     165                 :  */
     166               0 : GDALDerivedPixelFunc VRTDerivedRasterBand::GetPixelFunction
     167                 : (const char *pszFuncName)
     168                 : {
     169                 :     int ii;
     170                 : 
     171                 :     /* ---- Init ---- */
     172               0 :     if ((pszFuncName == NULL) || (pszFuncName[0] == '\0')) return NULL;
     173                 : 
     174                 :     /* ---- Check for match with fn added with AddPixelFunction ---- */
     175               0 :     for (ii = 0; ii < nFunctions; ii++) {
     176               0 :   if (strcmp(pszFuncName, papszNames[ii]) == 0) {
     177               0 :       return papfnPixelFunctions[ii];
     178                 :   }
     179                 :     }
     180                 : 
     181               0 :     return NULL;
     182                 : }
     183                 : 
     184                 : /************************************************************************/
     185                 : /*                         SetPixelFunctionName()                       */
     186                 : /************************************************************************/
     187                 : 
     188                 : /**
     189                 :  * Set the pixel function name to be applied to this derived band.  The
     190                 :  * name should match a pixel function registered using AddPixelFunction.
     191                 :  *
     192                 :  * @param pszFuncName Name of pixel function to be applied to this derived
     193                 :  * band.
     194                 :  */
     195               0 : void VRTDerivedRasterBand::SetPixelFunctionName(const char *pszFuncName)
     196                 : {
     197               0 :     this->pszFuncName = CPLStrdup( pszFuncName );
     198               0 : }
     199                 : 
     200                 : /************************************************************************/
     201                 : /*                         SetSourceTransferType()                      */
     202                 : /************************************************************************/
     203                 : 
     204                 : /**
     205                 :  * Set the transfer type to be used to obtain pixel information from
     206                 :  * all of the sources.  If unset, the transfer type used will be the
     207                 :  * same as the derived band data type.  This makes it possible, for
     208                 :  * example, to pass CFloat32 source pixels to the pixel function, even
     209                 :  * if the pixel function generates a raster for a derived band that
     210                 :  * is of type Byte.
     211                 :  *
     212                 :  * @param eDataType Data type to use to obtain pixel information from
     213                 :  * the sources to be passed to the derived band pixel function.
     214                 :  */
     215               0 : void VRTDerivedRasterBand::SetSourceTransferType(GDALDataType eDataType)
     216                 : {
     217               0 :     this->eSourceTransferType = eDataType;
     218               0 : }
     219                 : 
     220                 : /************************************************************************/
     221                 : /*                             IRasterIO()                              */
     222                 : /************************************************************************/
     223                 : 
     224                 : /**
     225                 :  * Read/write a region of image data for this band.
     226                 :  *
     227                 :  * Each of the sources for this derived band will be read and passed to
     228                 :  * the derived band pixel function.  The pixel function is responsible
     229                 :  * for applying whatever algorithm is necessary to generate this band's
     230                 :  * pixels from the sources.
     231                 :  *
     232                 :  * The sources will be read using the transfer type specified for sources
     233                 :  * using SetSourceTransferType().  If no transfer type has been set for
     234                 :  * this derived band, the band's data type will be used as the transfer type.
     235                 :  *
     236                 :  * @see gdalrasterband
     237                 :  *
     238                 :  * @param eRWFlag Either GF_Read to read a region of data, or GT_Write to
     239                 :  * write a region of data.
     240                 :  *
     241                 :  * @param nXOff The pixel offset to the top left corner of the region
     242                 :  * of the band to be accessed.  This would be zero to start from the left side.
     243                 :  *
     244                 :  * @param nYOff The line offset to the top left corner of the region
     245                 :  * of the band to be accessed.  This would be zero to start from the top.
     246                 :  *
     247                 :  * @param nXSize The width of the region of the band to be accessed in pixels.
     248                 :  *
     249                 :  * @param nYSize The height of the region of the band to be accessed in lines.
     250                 :  *
     251                 :  * @param pData The buffer into which the data should be read, or from which
     252                 :  * it should be written.  This buffer must contain at least nBufXSize *
     253                 :  * nBufYSize words of type eBufType.  It is organized in left to right,
     254                 :  * top to bottom pixel order.  Spacing is controlled by the nPixelSpace,
     255                 :  * and nLineSpace parameters.
     256                 :  *
     257                 :  * @param nBufXSize The width of the buffer image into which the desired
     258                 :  * region is to be read, or from which it is to be written.
     259                 :  *
     260                 :  * @param nBufYSize The height of the buffer image into which the desired
     261                 :  * region is to be read, or from which it is to be written.
     262                 :  *
     263                 :  * @param eBufType The type of the pixel values in the pData data buffer.  The
     264                 :  * pixel values will automatically be translated to/from the GDALRasterBand
     265                 :  * data type as needed.
     266                 :  *
     267                 :  * @param nPixelSpace The byte offset from the start of one pixel value in
     268                 :  * pData to the start of the next pixel value within a scanline.  If defaulted
     269                 :  * (0) the size of the datatype eBufType is used.
     270                 :  *
     271                 :  * @param nLineSpace The byte offset from the start of one scanline in
     272                 :  * pData to the start of the next.  If defaulted the size of the datatype
     273                 :  * eBufType * nBufXSize is used.
     274                 :  *
     275                 :  * @return CE_Failure if the access fails, otherwise CE_None.
     276                 :  */
     277               0 : CPLErr VRTDerivedRasterBand::IRasterIO(GDALRWFlag eRWFlag,
     278                 :                int nXOff, int nYOff, int nXSize, 
     279                 :                int nYSize, void * pData, int nBufXSize,
     280                 :                int nBufYSize, GDALDataType eBufType,
     281                 :                int nPixelSpace, int nLineSpace )
     282                 : {
     283                 :     GDALDerivedPixelFunc pfnPixelFunc;
     284                 :     void **pBuffers;
     285               0 :     CPLErr eErr = CE_None;
     286                 :     int iSource, ii, typesize, sourcesize;
     287                 :     GDALDataType eSrcType;
     288                 : 
     289               0 :     if( eRWFlag == GF_Write )
     290                 :     {
     291                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     292               0 :                   "Writing through VRTSourcedRasterBand is not supported." );
     293               0 :         return CE_Failure;
     294                 :     }
     295                 : 
     296               0 :     typesize = GDALGetDataTypeSize(eBufType) / 8;
     297               0 :     if (GDALGetDataTypeSize(eBufType) % 8 > 0) typesize++;
     298               0 :     eSrcType = this->eSourceTransferType;
     299               0 :     if ((eSrcType == GDT_Unknown) || (eSrcType >= GDT_TypeCount)) {
     300               0 :   eSrcType = eBufType;
     301                 :     }
     302               0 :     sourcesize = GDALGetDataTypeSize(eSrcType) / 8;
     303                 : 
     304                 : /* -------------------------------------------------------------------- */
     305                 : /*      Initialize the buffer to some background value. Use the         */
     306                 : /*      nodata value if available.                                      */
     307                 : /* -------------------------------------------------------------------- */
     308               0 :     if ( nPixelSpace == typesize &&
     309                 :          (!bNoDataValueSet || dfNoDataValue == 0) ) {
     310               0 :         memset( pData, 0, nBufXSize * nBufYSize * nPixelSpace );
     311                 :     }
     312               0 :     else if ( !bEqualAreas || bNoDataValueSet )
     313                 :     {
     314               0 :         double dfWriteValue = 0.0;
     315                 :         int    iLine;
     316                 : 
     317               0 :         if( bNoDataValueSet )
     318               0 :             dfWriteValue = dfNoDataValue;
     319                 : 
     320               0 :         for( iLine = 0; iLine < nBufYSize; iLine++ )
     321                 :         {
     322                 :             GDALCopyWords( &dfWriteValue, GDT_Float64, 0, 
     323                 :                            ((GByte *)pData) + nLineSpace * iLine, 
     324               0 :                            eBufType, nPixelSpace, nBufXSize );
     325                 :         }
     326                 :     }
     327                 : 
     328                 : /* -------------------------------------------------------------------- */
     329                 : /*      Do we have overviews that would be appropriate to satisfy       */
     330                 : /*      this request?                                                   */
     331                 : /* -------------------------------------------------------------------- */
     332               0 :     if( (nBufXSize < nXSize || nBufYSize < nYSize)
     333               0 :         && GetOverviewCount() > 0 )
     334                 :     {
     335               0 :         if( OverviewRasterIO( eRWFlag, nXOff, nYOff, nXSize, nYSize, 
     336                 :                               pData, nBufXSize, nBufYSize, 
     337                 :                               eBufType, nPixelSpace, nLineSpace ) == CE_None )
     338               0 :             return CE_None;
     339                 :     }
     340                 : 
     341                 :     /* ---- Get pixel function for band ---- */
     342               0 :     pfnPixelFunc = VRTDerivedRasterBand::GetPixelFunction(this->pszFuncName);
     343               0 :     if (pfnPixelFunc == NULL) {
     344                 :   CPLError( CE_Failure, CPLE_IllegalArg, 
     345                 :       "VRTDerivedRasterBand::IRasterIO:" \
     346                 :       "Derived band pixel function '%s' not registered.\n",
     347               0 :       this->pszFuncName);
     348               0 :   return CE_Failure;
     349                 :     }
     350                 : 
     351                 :     /* TODO: It would be nice to use a MallocBlock function for each
     352                 :        individual buffer that would recycle blocks of memory from a
     353                 :        cache by reassigning blocks that are nearly the same size.
     354                 :        A corresponding FreeBlock might only truly free if the total size
     355                 :        of freed blocks gets to be too great of a percentage of the size
     356                 :        of the allocated blocks. */
     357                 : 
     358                 :     /* ---- Get buffers for each source ---- */
     359               0 :     pBuffers = (void **) CPLMalloc(sizeof(void *) * nSources);
     360               0 :     for (iSource = 0; iSource < nSources; iSource++) {
     361               0 :         pBuffers[iSource] = (void *) 
     362               0 :       malloc(sourcesize * nBufXSize * nBufYSize);
     363               0 :         if (pBuffers[iSource] == NULL) {
     364               0 :             for (ii = 0; ii < iSource; ii++) {
     365               0 :                 free(pBuffers[iSource]);
     366                 :       }
     367                 :       CPLError( CE_Failure, CPLE_OutOfMemory, 
     368                 :           "VRTDerivedRasterBand::IRasterIO:" \
     369                 :           "Out of memory allocating %d bytes.\n",
     370               0 :           nPixelSpace * nBufXSize * nBufYSize);
     371               0 :       return CE_Failure;
     372                 :   }
     373                 :     }
     374                 : 
     375                 :     /* ---- Load values for sources into packed buffers ---- */
     376               0 :     for(iSource = 0; iSource < nSources; iSource++) {
     377               0 :         eErr = ((VRTSource *)papoSources[iSource])->RasterIO
     378                 :       (nXOff, nYOff, nXSize, nYSize, 
     379                 :        pBuffers[iSource], nBufXSize, nBufYSize, 
     380                 :        eSrcType, GDALGetDataTypeSize( eSrcType ) / 8,
     381               0 :              (GDALGetDataTypeSize( eSrcType ) / 8) * nBufXSize);
     382                 :     }
     383                 : 
     384                 :     /* ---- Apply pixel function ---- */
     385               0 :     if (eErr == CE_None) {
     386                 :   eErr = pfnPixelFunc((void **)pBuffers, nSources,
     387                 :           pData, nBufXSize, nBufYSize,
     388               0 :           eSrcType, eBufType, nPixelSpace, nLineSpace);
     389                 :     }
     390                 : 
     391                 :     /* ---- Release buffers ---- */
     392               0 :     for (iSource = 0; iSource < nSources; iSource++) {
     393               0 :         free(pBuffers[iSource]);
     394                 :     }
     395               0 :     CPLFree(pBuffers);
     396                 : 
     397               0 :     return eErr;
     398                 : }
     399                 : 
     400                 : /************************************************************************/
     401                 : /*                              XMLInit()                               */
     402                 : /************************************************************************/
     403                 : 
     404               0 : CPLErr VRTDerivedRasterBand::XMLInit(CPLXMLNode *psTree, 
     405                 :              const char *pszVRTPath)
     406                 : 
     407                 : {
     408                 :     CPLErr eErr;
     409                 :     const char *pszTypeName;
     410                 : 
     411               0 :     eErr = VRTSourcedRasterBand::XMLInit( psTree, pszVRTPath );
     412               0 :     if( eErr != CE_None )
     413               0 :         return eErr;
     414                 : 
     415                 :     /* ---- Read derived pixel function type ---- */
     416                 :     this->SetPixelFunctionName
     417               0 :   (CPLGetXMLValue(psTree, "PixelFunctionType", NULL));
     418                 : 
     419                 :     /* ---- Read optional source transfer data type ---- */
     420               0 :     pszTypeName = CPLGetXMLValue(psTree, "SourceTransferType", NULL);
     421               0 :     if (pszTypeName != NULL) {
     422               0 :   this->eSourceTransferType = GDALGetDataTypeByName(pszTypeName);
     423                 :     }
     424                 : 
     425               0 :     return CE_None;
     426                 : }
     427                 : 
     428                 : /************************************************************************/
     429                 : /*                           SerializeToXML()                           */
     430                 : /************************************************************************/
     431                 : 
     432               0 : CPLXMLNode *VRTDerivedRasterBand::SerializeToXML(const char *pszVRTPath)
     433                 : {
     434                 :     CPLXMLNode *psTree;
     435                 : 
     436               0 :     psTree = VRTSourcedRasterBand::SerializeToXML( pszVRTPath );
     437                 : 
     438                 : /* -------------------------------------------------------------------- */
     439                 : /*      Set subclass.                                                   */
     440                 : /* -------------------------------------------------------------------- */
     441                 :     CPLCreateXMLNode( 
     442                 :         CPLCreateXMLNode( psTree, CXT_Attribute, "subClass" ), 
     443               0 :         CXT_Text, "VRTDerivedRasterBand" );
     444                 : 
     445                 :     /* ---- Encode DerivedBand-specific fields ---- */
     446               0 :     if( pszFuncName != NULL && strlen(pszFuncName) > 0 )
     447               0 :         CPLSetXMLValue(psTree, "PixelFunctionType", this->pszFuncName);
     448               0 :     if( this->eSourceTransferType != GDT_Unknown)
     449                 :         CPLSetXMLValue(psTree, "SourceTransferType", 
     450               0 :            GDALGetDataTypeName(this->eSourceTransferType));
     451                 : 
     452               0 :     return psTree;
     453                 : }
     454                 : 

Generated by: LCOV version 1.7