int GDALArrayBandBlockCache::Init()
{
    if( poBand->nBlocksPerRow < SUBBLOCK_SIZE/2 )
    {
        bSubBlockingActive = FALSE;

        if (poBand->nBlocksPerRow < INT_MAX / poBand->nBlocksPerColumn)
        {
            u.papoBlocks = (GDALRasterBlock **)
                VSICalloc( sizeof(void*), poBand->nBlocksPerRow * poBand->nBlocksPerColumn );
            if( u.papoBlocks == NULL )
            {
                poBand->ReportError( CE_Failure, CPLE_OutOfMemory,
                                    "Out of memory in InitBlockInfo()." );
                return FALSE;
            }
        }
        else
        {
            poBand->ReportError( CE_Failure, CPLE_NotSupported,
                                 "Too many blocks : %d x %d",
                                 poBand->nBlocksPerRow, poBand->nBlocksPerColumn );
            return FALSE;
        }
    }
    else
    {
        bSubBlockingActive = TRUE;

        nSubBlocksPerRow = DIV_ROUND_UP(poBand->nBlocksPerRow, SUBBLOCK_SIZE);
        nSubBlocksPerColumn = DIV_ROUND_UP(poBand->nBlocksPerColumn, SUBBLOCK_SIZE);

        if (nSubBlocksPerRow < INT_MAX / nSubBlocksPerColumn)
        {
            u.papapoBlocks = (GDALRasterBlock ***)
                VSICalloc( sizeof(void*), nSubBlocksPerRow * nSubBlocksPerColumn );
            if( u.papapoBlocks == NULL )
            {
                poBand->ReportError( CE_Failure, CPLE_OutOfMemory,
                                    "Out of memory in InitBlockInfo()." );
                return FALSE;
            }

        }
        else
        {
            poBand->ReportError( CE_Failure, CPLE_NotSupported,
                                 "Too many subblocks : %d x %d",
                                 nSubBlocksPerRow, nSubBlocksPerColumn );
            return FALSE;
        }
    }

    
    return TRUE;
}
CPLErr MEMDataset::AddBand( GDALDataType eType, char **papszOptions )

{
    int nBandId = GetRasterCount() + 1;
    GByte *pData;
    int   nPixelSize = (GDALGetDataTypeSize(eType) / 8);

/* -------------------------------------------------------------------- */
/*      Do we need to allocate the memory ourselves?  This is the       */
/*      simple case.                                                    */
/* -------------------------------------------------------------------- */
    if( CSLFetchNameValue( papszOptions, "DATAPOINTER" ) == NULL )
    {

        pData = (GByte *) 
            VSICalloc(nPixelSize * GetRasterXSize(), GetRasterYSize() );

        if( pData == NULL )
        {
            CPLError( CE_Failure, CPLE_OutOfMemory,
                      "Unable to create band arrays ... out of memory." );
            return CE_Failure;
        }

        SetBand( nBandId,
                 new MEMRasterBand( this, nBandId, pData, eType, nPixelSize, 
                                    nPixelSize * GetRasterXSize(), TRUE ) );

        return CE_None;
    }

/* -------------------------------------------------------------------- */
/*      Get layout of memory and other flags.                           */
/* -------------------------------------------------------------------- */
    const char *pszOption;
    int nPixelOffset, nLineOffset;
    const char *pszDataPointer;

    pszDataPointer = CSLFetchNameValue(papszOptions,"DATAPOINTER");
    pData = (GByte *) CPLScanPointer(pszDataPointer,
                                     strlen(pszDataPointer));
    
    pszOption = CSLFetchNameValue(papszOptions,"PIXELOFFSET");
    if( pszOption == NULL )
        nPixelOffset = nPixelSize;
    else
        nPixelOffset = atoi(pszOption);

    pszOption = CSLFetchNameValue(papszOptions,"LINEOFFSET");
    if( pszOption == NULL )
        nLineOffset = GetRasterXSize() * nPixelOffset;
    else
        nLineOffset = atoi(pszOption);

    SetBand( nBandId,
             new MEMRasterBand( this, nBandId, pData, eType, 
                                nPixelOffset, nLineOffset, FALSE ) );

    return CE_None;
}
Esempio n. 3
0
void* _TIFFcalloc(tmsize_t nmemb, tmsize_t siz)
{
    if( nmemb == 0 || siz == 0 )
        return ((void *) NULL);

    return VSICalloc((size_t) nmemb, (size_t)siz);
}
Esempio n. 4
0
GSAGRasterBand::GSAGRasterBand( GSAGDataset *poDS, int nBand,
				vsi_l_offset nDataStart ) :
    padfRowMinZ(NULL),
    padfRowMaxZ(NULL),
    nMinZRow(-1),
    nMaxZRow(-1)

{
    this->poDS = poDS;
    this->nBand = nBand;
    
    eDataType = GDT_Float64;

    nBlockXSize = poDS->GetRasterXSize();
    nBlockYSize = 1;

    panLineOffset =
	(vsi_l_offset *)VSICalloc( poDS->nRasterYSize+1, sizeof(vsi_l_offset) );
    if( panLineOffset == NULL )
    {
        CPLError(CE_Failure, CPLE_OutOfMemory,
                 "GSAGRasterBand::GSAGRasterBand : Out of memory allocating %d * %d bytes",
                 (int) poDS->nRasterYSize+1, (int) sizeof(vsi_l_offset) );
	return;
    }

	panLineOffset[poDS->nRasterYSize-1] = nDataStart;
	nLastReadLine = poDS->nRasterYSize;
}
CPLErr GDALArrayBandBlockCache::AdoptBlock( GDALRasterBlock * poBlock )

{
    int         nBlockIndex;
    int         nXBlockOff = poBlock->GetXOff();
    int         nYBlockOff = poBlock->GetYOff();

    FreeDanglingBlocks();

/* -------------------------------------------------------------------- */
/*      Simple case without subblocking.                                */
/* -------------------------------------------------------------------- */
    if( !bSubBlockingActive )
    {
        nBlockIndex = nXBlockOff + nYBlockOff * poBand->nBlocksPerRow;

        CPLAssert( u.papoBlocks[nBlockIndex] == NULL );
        u.papoBlocks[nBlockIndex] = poBlock;
    }
    else
    {
/* -------------------------------------------------------------------- */
/*      Identify the subblock in which our target occurs, and create    */
/*      it if necessary.                                                */
/* -------------------------------------------------------------------- */
        int nSubBlock = TO_SUBBLOCK(nXBlockOff) 
            + TO_SUBBLOCK(nYBlockOff) * nSubBlocksPerRow;

        if( u.papapoBlocks[nSubBlock] == NULL )
        {
            const int nSubGridSize = 
                sizeof(GDALRasterBlock*) * SUBBLOCK_SIZE * SUBBLOCK_SIZE;

            u.papapoBlocks[nSubBlock] = (GDALRasterBlock **) VSICalloc(1, nSubGridSize);
            if( u.papapoBlocks[nSubBlock] == NULL )
            {
                poBand->ReportError( CE_Failure, CPLE_OutOfMemory,
                        "Out of memory in AdoptBlock()." );
                return CE_Failure;
            }
        }

/* -------------------------------------------------------------------- */
/*      Check within subblock.                                          */
/* -------------------------------------------------------------------- */
        GDALRasterBlock **papoSubBlockGrid = u.papapoBlocks[nSubBlock];

        int nBlockInSubBlock = WITHIN_SUBBLOCK(nXBlockOff)
            + WITHIN_SUBBLOCK(nYBlockOff) * SUBBLOCK_SIZE;

        CPLAssert( papoSubBlockGrid[nBlockInSubBlock] == NULL );
        papoSubBlockGrid[nBlockInSubBlock] = poBlock;
    }

    return CE_None;
}
Esempio n. 6
0
//! @cond Doxygen_Suppress
int
PamParseHistogram( CPLXMLNode *psHistItem,
                   double *pdfMin, double *pdfMax,
                   int *pnBuckets, GUIntBig **ppanHistogram,
                   int * /* pbIncludeOutOfRange */,
                   int * /* pbApproxOK */ )
{
    if( psHistItem == nullptr )
        return FALSE;

    *pdfMin = CPLAtofM(CPLGetXMLValue( psHistItem, "HistMin", "0"));
    *pdfMax = CPLAtofM(CPLGetXMLValue( psHistItem, "HistMax", "1"));
    *pnBuckets = atoi(CPLGetXMLValue( psHistItem, "BucketCount","2"));

    if( *pnBuckets <= 0 || *pnBuckets > INT_MAX / 2 )
        return FALSE;

    if( ppanHistogram == nullptr )
        return TRUE;

    // Fetch the histogram and use it.
    const char *pszHistCounts = CPLGetXMLValue( psHistItem,
                                                "HistCounts", "" );

    // Sanity check to test consistency of BucketCount and HistCounts.
    if( strlen(pszHistCounts) < 2 * static_cast<size_t>(*pnBuckets) - 1 )
    {
        CPLError(
            CE_Failure, CPLE_AppDefined,
            "HistCounts content isn't consistent with BucketCount value" );
        return FALSE;
    }

    *ppanHistogram = static_cast<GUIntBig *>(
        VSICalloc(sizeof(GUIntBig),*pnBuckets) );
    if( *ppanHistogram == nullptr )
    {
        CPLError( CE_Failure, CPLE_OutOfMemory,
                  "Cannot allocate memory for %d buckets", *pnBuckets );
        return FALSE;
    }

    for( int iBucket = 0; iBucket < *pnBuckets; iBucket++ )
    {
        (*ppanHistogram)[iBucket] = CPLAtoGIntBig(pszHistCounts);

        // Skip to next number.
        while( *pszHistCounts != '\0' && *pszHistCounts != '|' )
            pszHistCounts++;
        if( *pszHistCounts == '|' )
            pszHistCounts++;
    }

    return TRUE;
}
Esempio n. 7
0
int 
PamParseHistogram( CPLXMLNode *psHistItem, 
                   double *pdfMin, double *pdfMax, 
                   int *pnBuckets, int **ppanHistogram, 
                   int *pbIncludeOutOfRange, int *pbApproxOK )

{
    if( psHistItem == NULL )
        return FALSE;

    *pdfMin = atof(CPLGetXMLValue( psHistItem, "HistMin", "0"));
    *pdfMax = atof(CPLGetXMLValue( psHistItem, "HistMax", "1"));
    *pnBuckets = atoi(CPLGetXMLValue( psHistItem, "BucketCount","2"));
    if (*pnBuckets <= 0 || *pnBuckets > INT_MAX / 2)
        return FALSE;

    if( ppanHistogram == NULL )
        return TRUE;

    // Fetch the histogram and use it. 
    int iBucket;
    const char *pszHistCounts = CPLGetXMLValue( psHistItem, 
                                                "HistCounts", "" );

    /* Sanity check to test consistency of BucketCount and HistCounts */
    if( strlen(pszHistCounts) < 2 * (size_t)(*pnBuckets) -1 )
    {
        CPLError(CE_Failure, CPLE_AppDefined,
                 "HistCounts content isn't consistant with BucketCount value");
        return FALSE;
    }

    *ppanHistogram = (int *) VSICalloc(sizeof(int),*pnBuckets);
    if (*ppanHistogram == NULL)
    {
        CPLError(CE_Failure, CPLE_OutOfMemory,
                 "Cannot allocate memory for %d buckets", *pnBuckets);
        return FALSE;
    }

    for( iBucket = 0; iBucket < *pnBuckets; iBucket++ )
    {
        (*ppanHistogram)[iBucket] = atoi(pszHistCounts);
        
        // skip to next number.
        while( *pszHistCounts != '\0' && *pszHistCounts != '|' )
            pszHistCounts++;
        if( *pszHistCounts == '|' )
            pszHistCounts++;
    }
    
    return TRUE;
}
void VizGeorefSpline2D::grow_points()

{
    int new_max = _max_nof_points*2 + 2 + 3;
    int i;
    
    if( _max_nof_points == 0 )
    {
        x = (double *) VSIMalloc( sizeof(double) * new_max );
        y = (double *) VSIMalloc( sizeof(double) * new_max );
        u = (double *) VSIMalloc( sizeof(double) * new_max );
        unused = (int *) VSIMalloc( sizeof(int) * new_max );
        index = (int *) VSIMalloc( sizeof(int) * new_max );
        for( i = 0; i < VIZGEOREF_MAX_VARS; i++ )
        {
            rhs[i] = (double *) VSICalloc( sizeof(double), new_max );
            coef[i] = (double *) VSICalloc( sizeof(double), new_max );
        }
    }
    else
    {
        x = (double *) VSIRealloc( x, sizeof(double) * new_max );
        y = (double *) VSIRealloc( y, sizeof(double) * new_max );
        u = (double *) VSIRealloc( u, sizeof(double) * new_max );
        unused = (int *) VSIRealloc( unused, sizeof(int) * new_max );
        index = (int *) VSIRealloc( index, sizeof(int) * new_max );
        for( i = 0; i < VIZGEOREF_MAX_VARS; i++ )
        {
            rhs[i] = (double *) 
                VSIRealloc( rhs[i], sizeof(double) * new_max );
            coef[i] = (double *) 
                VSIRealloc( coef[i], sizeof(double) * new_max );
        }
    }

    _max_nof_points = new_max - 3;
}
Esempio n. 9
0
int 
PamParseHistogram( CPLXMLNode *psHistItem, 
                   double *pdfMin, double *pdfMax, 
                   int *pnBuckets, int **ppanHistogram, 
                   int *pbIncludeOutOfRange, int *pbApproxOK )

{
    if( psHistItem == NULL )
        return FALSE;

    *pdfMin = atof(CPLGetXMLValue( psHistItem, "HistMin", "0"));
    *pdfMax = atof(CPLGetXMLValue( psHistItem, "HistMax", "1"));
    *pnBuckets = atoi(CPLGetXMLValue( psHistItem, "BucketCount","2"));
    if (*pnBuckets <= 0)
        return FALSE;

    if( ppanHistogram == NULL )
        return TRUE;

    // Fetch the histogram and use it. 
    int iBucket;
    const char *pszHistCounts = CPLGetXMLValue( psHistItem, 
                                                "HistCounts", "" );

    *ppanHistogram = (int *) VSICalloc(sizeof(int),*pnBuckets);
    if (*ppanHistogram == NULL)
    {
        CPLError(CE_Failure, CPLE_OutOfMemory,
                 "Cannot allocate memory for %d buckets", *pnBuckets);
        return FALSE;
    }

    for( iBucket = 0; iBucket < *pnBuckets; iBucket++ )
    {
        (*ppanHistogram)[iBucket] = atoi(pszHistCounts);
        
        // skip to next number.
        while( *pszHistCounts != '\0' && *pszHistCounts != '|' )
            pszHistCounts++;
        if( *pszHistCounts == '|' )
            pszHistCounts++;
    }
    
    return TRUE;
}
Esempio n. 10
0
void *CPLCalloc( int nCount, int nSize )

{
    void	*pReturn;

    if( nSize == 0 )
        return NULL;
    
    pReturn = VSICalloc( nCount, nSize );
    if( pReturn == NULL )
    {
        CPLError( CE_Fatal, CPLE_OutOfMemory,
                  "CPLCalloc(): Out of memory allocating %d bytes.\n",
                  nSize * nCount );
    }

    return pReturn;
}
Esempio n. 11
0
static CPLErrorContext *CPLGetErrorContext()

{
    CPLErrorContext *psCtx = 
        (CPLErrorContext *) CPLGetTLS( CTLS_ERRORCONTEXT );

    if( psCtx == NULL )
    {
        psCtx = (CPLErrorContext *) VSICalloc(sizeof(CPLErrorContext),1);
        if (psCtx == NULL) {
            CPLEmergencyError("Out of memory attempting to report error");
        }
        psCtx->eLastErrType = CE_None;
        psCtx->nLastErrMsgMax = sizeof(psCtx->szLastErrMsg);
        CPLSetTLS( CTLS_ERRORCONTEXT, psCtx, TRUE );
    }

    return psCtx;
}
Esempio n. 12
0
static void GXFScanForZMinMax( GXFHandle hGXF )

{
    GXFInfo_t	*psGXF = (GXFInfo_t *) hGXF;
    int		iLine, iPixel;
    double	*padfScanline;
    

    padfScanline = (double *) VSICalloc(sizeof(double),psGXF->nRawXSize);
    if( padfScanline == NULL )
        return;

    psGXF->dfZMinimum = 1e50;
    psGXF->dfZMaximum = -1e50;

    for( iLine = 0; iLine < psGXF->nRawYSize; iLine++ )
    {
        if( GXFGetRawScanline( hGXF, iLine, padfScanline ) != CE_None )
            break;

        for( iPixel = 0; iPixel < psGXF->nRawXSize; iPixel++ )
        {
            if( padfScanline[iPixel] != psGXF->dfSetDummyTo )
            {
                psGXF->dfZMinimum =
                    MIN(psGXF->dfZMinimum,padfScanline[iPixel]);
                psGXF->dfZMaximum =
                    MAX(psGXF->dfZMaximum,padfScanline[iPixel]);
            }
        }
    }

    VSIFree( padfScanline );

/* -------------------------------------------------------------------- */
/*      Did we get any real data points?                                */
/* -------------------------------------------------------------------- */
    if( psGXF->dfZMinimum > psGXF->dfZMaximum )
    {
        psGXF->dfZMinimum = 0.0;
        psGXF->dfZMaximum = 0.0;
    }
}
Esempio n. 13
0
int
GDALComputeMedianCutPCTInternal( GDALRasterBandH hRed,
                                 GDALRasterBandH hGreen,
                                 GDALRasterBandH hBlue,
                                 GByte* pabyRedBand,
                                 GByte* pabyGreenBand,
                                 GByte* pabyBlueBand,
                                 int (*pfnIncludePixel)(int,int,void*),
                                 int nColors,
                                 int nBits,
                                 int* panHistogram, /* NULL, or at least of size (1<<nBits)^3 * sizeof(int) bytes */
                                 GDALColorTableH hColorTable,
                                 GDALProgressFunc pfnProgress,
                                 void * pProgressArg )

{
    VALIDATE_POINTER1( hRed, "GDALComputeMedianCutPCT", CE_Failure );
    VALIDATE_POINTER1( hGreen, "GDALComputeMedianCutPCT", CE_Failure );
    VALIDATE_POINTER1( hBlue, "GDALComputeMedianCutPCT", CE_Failure );

    int		nXSize, nYSize;
    CPLErr err = CE_None;

    /* -------------------------------------------------------------------- */
    /*      Validate parameters.                                            */
    /* -------------------------------------------------------------------- */
    nXSize = GDALGetRasterBandXSize( hRed );
    nYSize = GDALGetRasterBandYSize( hRed );

    if( GDALGetRasterBandXSize( hGreen ) != nXSize
            || GDALGetRasterBandYSize( hGreen ) != nYSize
            || GDALGetRasterBandXSize( hBlue ) != nXSize
            || GDALGetRasterBandYSize( hBlue ) != nYSize )
    {
        CPLError( CE_Failure, CPLE_IllegalArg,
                  "Green or blue band doesn't match size of red band.\n" );

        return CE_Failure;
    }

    if( pfnIncludePixel != NULL )
    {
        CPLError( CE_Failure, CPLE_IllegalArg,
                  "GDALComputeMedianCutPCT() doesn't currently support "
                  " pfnIncludePixel function." );

        return CE_Failure;
    }

    if ( nColors <= 0 )
    {
        CPLError( CE_Failure, CPLE_IllegalArg,
                  "GDALComputeMedianCutPCT() : nColors must be strictly greater than 1." );

        return CE_Failure;
    }

    if ( nColors > 256 )
    {
        CPLError( CE_Failure, CPLE_IllegalArg,
                  "GDALComputeMedianCutPCT() : nColors must be lesser than or equal to 256." );

        return CE_Failure;
    }

    if( pfnProgress == NULL )
        pfnProgress = GDALDummyProgress;

    /* ==================================================================== */
    /*      STEP 1: create empty boxes.                                     */
    /* ==================================================================== */
    int	     i;
    Colorbox *box_list, *ptr;
    int* histogram;
    Colorbox *freeboxes;
    Colorbox *usedboxes;
    int nCLevels = 1 << nBits;
    int nColorShift = 8 - nBits;
    int nColorCounter = 0;
    GByte anRed[256], anGreen[256], anBlue[256];
    int nPixels = 0;
    HashHistogram* psHashHistogram = NULL;

    if( nBits == 8 && pabyRedBand != NULL && pabyGreenBand != NULL &&
            pabyBlueBand != NULL && nXSize < INT_MAX / nYSize )
    {
        nPixels = nXSize * nYSize;
    }

    if( panHistogram )
    {
        if( nBits == 8 && (GIntBig)nXSize * nYSize <= 65536 )
        {
            /* If the image is small enough, then the number of colors */
            /* will be limited and using a hashmap, rather than a full table */
            /* will be more efficient */
            histogram = NULL;
            psHashHistogram = (HashHistogram*)panHistogram;
            memset(psHashHistogram, 0xFF, sizeof(HashHistogram) * PRIME_FOR_65536);
        }
        else
        {
            histogram = panHistogram;
            memset(histogram, 0, nCLevels*nCLevels*nCLevels * sizeof(int));
        }
    }
    else
    {
        histogram = (int*) VSICalloc(nCLevels*nCLevels*nCLevels,sizeof(int));
        if( histogram == NULL )
        {
            CPLError( CE_Failure, CPLE_OutOfMemory,
                      "VSICalloc(): Out of memory in GDALComputeMedianCutPCT" );
            return CE_Failure;
        }
    }
    usedboxes = NULL;
    box_list = freeboxes = (Colorbox *)CPLMalloc(nColors*sizeof (Colorbox));
    freeboxes[0].next = &freeboxes[1];
    freeboxes[0].prev = NULL;
    for (i = 1; i < nColors-1; ++i) {
        freeboxes[i].next = &freeboxes[i+1];
        freeboxes[i].prev = &freeboxes[i-1];
    }
    freeboxes[nColors-1].next = NULL;
    freeboxes[nColors-1].prev = &freeboxes[nColors-2];

    /* ==================================================================== */
    /*      Build histogram.                                                */
    /* ==================================================================== */
    GByte	*pabyRedLine, *pabyGreenLine, *pabyBlueLine;
    int		iLine, iPixel;

    /* -------------------------------------------------------------------- */
    /*      Initialize the box datastructures.                              */
    /* -------------------------------------------------------------------- */
    ptr = freeboxes;
    freeboxes = ptr->next;
    if (freeboxes)
        freeboxes->prev = NULL;
    ptr->next = usedboxes;
    usedboxes = ptr;
    if (ptr->next)
        ptr->next->prev = ptr;

    ptr->rmin = ptr->gmin = ptr->bmin = 999;
    ptr->rmax = ptr->gmax = ptr->bmax = -1;
    ptr->total = nXSize * nYSize;

    /* -------------------------------------------------------------------- */
    /*      Collect histogram.                                              */
    /* -------------------------------------------------------------------- */
    pabyRedLine = (GByte *) VSIMalloc(nXSize);
    pabyGreenLine = (GByte *) VSIMalloc(nXSize);
    pabyBlueLine = (GByte *) VSIMalloc(nXSize);

    if (pabyRedLine == NULL ||
            pabyGreenLine == NULL ||
            pabyBlueLine == NULL)
    {
        CPLError( CE_Failure, CPLE_OutOfMemory,
                  "VSIMalloc(): Out of memory in GDALComputeMedianCutPCT" );
        err = CE_Failure;
        goto end_and_cleanup;
    }

    for( iLine = 0; iLine < nYSize; iLine++ )
    {
        if( !pfnProgress( iLine / (double) nYSize,
                          "Generating Histogram", pProgressArg ) )
        {
            CPLError( CE_Failure, CPLE_UserInterrupt, "User Terminated" );
            err = CE_Failure;
            goto end_and_cleanup;
        }

        GDALRasterIO( hRed, GF_Read, 0, iLine, nXSize, 1,
                      pabyRedLine, nXSize, 1, GDT_Byte, 0, 0 );
        GDALRasterIO( hGreen, GF_Read, 0, iLine, nXSize, 1,
                      pabyGreenLine, nXSize, 1, GDT_Byte, 0, 0 );
        GDALRasterIO( hBlue, GF_Read, 0, iLine, nXSize, 1,
                      pabyBlueLine, nXSize, 1, GDT_Byte, 0, 0 );

        for( iPixel = 0; iPixel < nXSize; iPixel++ )
        {
            int	nRed, nGreen, nBlue;

            nRed = pabyRedLine[iPixel] >> nColorShift;
            nGreen = pabyGreenLine[iPixel] >> nColorShift;
            nBlue = pabyBlueLine[iPixel] >> nColorShift;

            ptr->rmin = MIN(ptr->rmin, nRed);
            ptr->gmin = MIN(ptr->gmin, nGreen);
            ptr->bmin = MIN(ptr->bmin, nBlue);
            ptr->rmax = MAX(ptr->rmax, nRed);
            ptr->gmax = MAX(ptr->gmax, nGreen);
            ptr->bmax = MAX(ptr->bmax, nBlue);

            int* pnColor;
            if( psHashHistogram )
            {
                pnColor = FindAndInsertColorCount(psHashHistogram,
                                                  MAKE_COLOR_CODE(nRed, nGreen, nBlue));
            }
            else
            {
                pnColor = &HISTOGRAM(histogram, nCLevels, nRed, nGreen, nBlue);
            }
            if( *pnColor == 0 )
            {
                if( nColorShift == 0 && nColorCounter < nColors )
                {
                    anRed[nColorCounter] = nRed;
                    anGreen[nColorCounter] = nGreen;
                    anBlue[nColorCounter] = nBlue;
                }
                nColorCounter++;
            }
            (*pnColor) ++;
        }
    }

    if( !pfnProgress( 1.0, "Generating Histogram", pProgressArg ) )
    {
        CPLError( CE_Failure, CPLE_UserInterrupt, "User Terminated" );
        err = CE_Failure;
        goto end_and_cleanup;
    }

    if( nColorShift == 0 && nColorCounter <= nColors )
    {
        //CPLDebug("MEDIAN_CUT", "%d colors found <= %d", nColorCounter, nColors);
        for(int iColor = 0; iColor<nColorCounter; iColor++)
        {
            GDALColorEntry  sEntry;
            sEntry.c1 = (GByte) anRed[iColor];
            sEntry.c2 = (GByte) anGreen[iColor];
            sEntry.c3 = (GByte) anBlue[iColor];
            sEntry.c4 = 255;
            GDALSetColorEntry( hColorTable, iColor, &sEntry );
        }
        goto end_and_cleanup;
    }

    /* ==================================================================== */
    /*      STEP 3: continually subdivide boxes until no more free          */
    /*      boxes remain or until all colors assigned.                      */
    /* ==================================================================== */
    while (freeboxes != NULL) {
        ptr = largest_box(usedboxes);
        if (ptr != NULL)
            splitbox(ptr, histogram, psHashHistogram, nCLevels, &freeboxes, &usedboxes,
                     pabyRedBand, pabyGreenBand, pabyBlueBand, nPixels);
        else
            freeboxes = NULL;
    }

    /* ==================================================================== */
    /*      STEP 4: assign colors to all boxes                              */
    /* ==================================================================== */
    for (i = 0, ptr = usedboxes; ptr != NULL; ++i, ptr = ptr->next)
    {
        GDALColorEntry	sEntry;

        sEntry.c1 = (GByte) (((ptr->rmin + ptr->rmax) << nColorShift) / 2);
        sEntry.c2 = (GByte) (((ptr->gmin + ptr->gmax) << nColorShift) / 2);
        sEntry.c3 = (GByte) (((ptr->bmin + ptr->bmax) << nColorShift) / 2);
        sEntry.c4 = 255;
        GDALSetColorEntry( hColorTable, i, &sEntry );
    }

end_and_cleanup:
    CPLFree( pabyRedLine );
    CPLFree( pabyGreenLine );
    CPLFree( pabyBlueLine );

    /* We're done with the boxes now */
    CPLFree(box_list);
    freeboxes = usedboxes = NULL;

    if( panHistogram == NULL )
        CPLFree( histogram );

    return err;
}
Esempio n. 14
0
int GDALDitherRGB2PCTInternal( GDALRasterBandH hRed, 
                         GDALRasterBandH hGreen, 
                         GDALRasterBandH hBlue, 
                         GDALRasterBandH hTarget, 
                         GDALColorTableH hColorTable,
                         int nBits,
                         GInt16* pasDynamicColorMap, /* NULL or at least 256 * 256 * 256 * sizeof(GInt16) bytes */
                         int bDither,
                         GDALProgressFunc pfnProgress, 
                         void * pProgressArg )
{
    VALIDATE_POINTER1( hRed, "GDALDitherRGB2PCT", CE_Failure );
    VALIDATE_POINTER1( hGreen, "GDALDitherRGB2PCT", CE_Failure );
    VALIDATE_POINTER1( hBlue, "GDALDitherRGB2PCT", CE_Failure );
    VALIDATE_POINTER1( hTarget, "GDALDitherRGB2PCT", CE_Failure );
    VALIDATE_POINTER1( hColorTable, "GDALDitherRGB2PCT", CE_Failure );

    int		nXSize, nYSize;
    CPLErr err = CE_None;
    
/* -------------------------------------------------------------------- */
/*      Validate parameters.                                            */
/* -------------------------------------------------------------------- */
    nXSize = GDALGetRasterBandXSize( hRed );
    nYSize = GDALGetRasterBandYSize( hRed );

    if( GDALGetRasterBandXSize( hGreen ) != nXSize 
        || GDALGetRasterBandYSize( hGreen ) != nYSize 
        || GDALGetRasterBandXSize( hBlue ) != nXSize 
        || GDALGetRasterBandYSize( hBlue ) != nYSize )
    {
        CPLError( CE_Failure, CPLE_IllegalArg,
                  "Green or blue band doesn't match size of red band.\n" );

        return CE_Failure;
    }

    if( GDALGetRasterBandXSize( hTarget ) != nXSize 
        || GDALGetRasterBandYSize( hTarget ) != nYSize )
    {
        CPLError( CE_Failure, CPLE_IllegalArg,
                  "GDALDitherRGB2PCT(): "
                  "Target band doesn't match size of source bands.\n" );

        return CE_Failure;
    }

    if( pfnProgress == NULL )
        pfnProgress = GDALDummyProgress;

/* -------------------------------------------------------------------- */
/*      Setup more direct colormap.                                     */
/* -------------------------------------------------------------------- */
    int		nColors, iColor;
#ifdef USE_SSE2
    int anPCTUnaligned[256+4]; /* 4 for alignment on 16-byte boundary */
    int* anPCT = ALIGN_INT_ARRAY_ON_16_BYTE(anPCTUnaligned);
#else
    int anPCT[256*4];
#endif
    nColors = GDALGetColorEntryCount( hColorTable );
    
    if (nColors == 0 )
    {
        CPLError( CE_Failure, CPLE_IllegalArg,
                  "GDALDitherRGB2PCT(): "
                  "Color table must not be empty.\n" );

        return CE_Failure;
    }
    else if (nColors > 256)
    {
        CPLError( CE_Failure, CPLE_IllegalArg,
                  "GDALDitherRGB2PCT(): "
                  "Color table cannot have more than 256 entries.\n" );

        return CE_Failure;
    }
    
    for( iColor = 0; iColor < nColors; iColor++ )
    {
        GDALColorEntry	sEntry;

        GDALGetColorEntryAsRGB( hColorTable, iColor, &sEntry );
        CAST_PCT(anPCT)[4*iColor+0] = sEntry.c1;
        CAST_PCT(anPCT)[4*iColor+1] = sEntry.c2;
        CAST_PCT(anPCT)[4*iColor+2] = sEntry.c3;
        CAST_PCT(anPCT)[4*iColor+3] = 0;
    }
#ifdef USE_SSE2
    /* Pad to multiple of 8 colors */
    int nColorsMod8 = nColors % 8;
    if( nColorsMod8 )
    {
        for( iColor = 0; iColor < 8 - nColorsMod8; iColor ++)
        {
            anPCT[nColors+iColor] = anPCT[nColors-1];
        }
    }
#endif

/* -------------------------------------------------------------------- */
/*      Setup various variables.                                        */
/* -------------------------------------------------------------------- */
    GByte   *pabyRed, *pabyGreen, *pabyBlue, *pabyIndex;
    GByte   *pabyColorMap = NULL;
    int     *panError;
    int nCLevels = 1 << nBits;
    ColorIndex* psColorIndexMap = NULL;

    pabyRed = (GByte *) VSIMalloc(nXSize);
    pabyGreen = (GByte *) VSIMalloc(nXSize);
    pabyBlue = (GByte *) VSIMalloc(nXSize);

    pabyIndex = (GByte *) VSIMalloc(nXSize);

    panError = (int *) VSICalloc(sizeof(int),(nXSize+2) * 3);
    
    if (pabyRed == NULL ||
        pabyGreen == NULL ||
        pabyBlue == NULL ||
        pabyIndex == NULL ||
        panError == NULL)
    {
        CPLError( CE_Failure, CPLE_OutOfMemory,
                  "VSIMalloc(): Out of memory in GDALDitherRGB2PCT" );
        err = CE_Failure;
        goto end_and_cleanup;
    }

    if( pasDynamicColorMap == NULL )
    {
/* -------------------------------------------------------------------- */
/*      Build a 24bit to 8 bit color mapping.                           */
/* -------------------------------------------------------------------- */

        pabyColorMap = (GByte *) VSIMalloc(nCLevels * nCLevels * nCLevels 
                                        * sizeof(GByte));
        if( pabyColorMap == NULL )
        {
            CPLError( CE_Failure, CPLE_OutOfMemory,
                  "VSIMalloc(): Out of memory in GDALDitherRGB2PCT" );
            err = CE_Failure;
            goto end_and_cleanup;
        }

        FindNearestColor( nColors, anPCT, pabyColorMap, nCLevels);
    }
    else
    {
        pabyColorMap = NULL;
        if( nBits == 8 && (GIntBig)nXSize * nYSize <= 65536 )
        {
            /* If the image is small enough, then the number of colors */
            /* will be limited and using a hashmap, rather than a full table */
            /* will be more efficient */
            psColorIndexMap = (ColorIndex*)pasDynamicColorMap;
            memset(psColorIndexMap, 0xFF, sizeof(ColorIndex) * PRIME_FOR_65536);
        }
        else
        {
            memset(pasDynamicColorMap, 0xFF, 256 * 256 * 256 * sizeof(GInt16));
        }
    }

/* ==================================================================== */
/*      Loop over all scanlines of data to process.                     */
/* ==================================================================== */
    int		iScanline;

    for( iScanline = 0; iScanline < nYSize; iScanline++ )
    {
        int	nLastRedError, nLastGreenError, nLastBlueError, i;

/* -------------------------------------------------------------------- */
/*      Report progress                                                 */
/* -------------------------------------------------------------------- */
        if( !pfnProgress( iScanline / (double) nYSize, NULL, pProgressArg ) )
        {
            CPLError( CE_Failure, CPLE_UserInterrupt, "User Terminated" );
            err = CE_Failure;
            goto end_and_cleanup;
        }

/* -------------------------------------------------------------------- */
/*      Read source data.                                               */
/* -------------------------------------------------------------------- */
        GDALRasterIO( hRed, GF_Read, 0, iScanline, nXSize, 1, 
                      pabyRed, nXSize, 1, GDT_Byte, 0, 0 );
        GDALRasterIO( hGreen, GF_Read, 0, iScanline, nXSize, 1, 
                      pabyGreen, nXSize, 1, GDT_Byte, 0, 0 );
        GDALRasterIO( hBlue, GF_Read, 0, iScanline, nXSize, 1, 
                      pabyBlue, nXSize, 1, GDT_Byte, 0, 0 );

/* -------------------------------------------------------------------- */
/*	Apply the error from the previous line to this one.		*/
/* -------------------------------------------------------------------- */
        if( bDither )
        {
          for( i = 0; i < nXSize; i++ )
          {
            pabyRed[i] = (GByte)
                MAX(0,MIN(255,(pabyRed[i]   + panError[i*3+0+3])));
            pabyGreen[i] = (GByte)
                MAX(0,MIN(255,(pabyGreen[i] + panError[i*3+1+3])));
            pabyBlue[i] =  (GByte)
                MAX(0,MIN(255,(pabyBlue[i]  + panError[i*3+2+3])));
          }

          memset( panError, 0, sizeof(int) * (nXSize+2) * 3 );
        }

/* -------------------------------------------------------------------- */
/*	Figure out the nearest color to the RGB value.			*/
/* -------------------------------------------------------------------- */
        nLastRedError = 0;
        nLastGreenError = 0;
        nLastBlueError = 0;

        for( i = 0; i < nXSize; i++ )
        {
            int		iIndex, nError, nSixth;
            int		nRedValue, nGreenValue, nBlueValue;

            nRedValue =   MAX(0,MIN(255, pabyRed[i]   + nLastRedError));
            nGreenValue = MAX(0,MIN(255, pabyGreen[i] + nLastGreenError));
            nBlueValue =  MAX(0,MIN(255, pabyBlue[i]  + nLastBlueError));

            if( psColorIndexMap )
            {
                GUInt32 nColorCode = MAKE_COLOR_CODE(nRedValue, nGreenValue, nBlueValue);
                GUInt32 nIdx = nColorCode % PRIME_FOR_65536;
                //int nCollisions = 0;
                //static int nMaxCollisions = 0;
                while( TRUE )
                {
                    if( psColorIndexMap[nIdx].nColorCode == nColorCode )
                    {
                        iIndex = psColorIndexMap[nIdx].nIndex;
                        break;
                    }
                    if( (int)psColorIndexMap[nIdx].nColorCode < 0 )
                    {
                        psColorIndexMap[nIdx].nColorCode = nColorCode;
                        iIndex = FindNearestColor( nColors, anPCT,
                                                   nRedValue, nGreenValue, nBlueValue );
                        psColorIndexMap[nIdx].nIndex = (GByte) iIndex;
                        break;
                    }
                    if( psColorIndexMap[nIdx].nColorCode2 == nColorCode )
                    {
                        iIndex = psColorIndexMap[nIdx].nIndex2;
                        break;
                    }
                    if( (int)psColorIndexMap[nIdx].nColorCode2 < 0 )
                    {
                        psColorIndexMap[nIdx].nColorCode2 = nColorCode;
                        iIndex = FindNearestColor( nColors, anPCT,
                                                   nRedValue, nGreenValue, nBlueValue );
                        psColorIndexMap[nIdx].nIndex2 = (GByte) iIndex;
                        break;
                    }
                    if( psColorIndexMap[nIdx].nColorCode3 == nColorCode )
                    {
                        iIndex = psColorIndexMap[nIdx].nIndex3;
                        break;
                    }
                    if( (int)psColorIndexMap[nIdx].nColorCode3 < 0 )
                    {
                        psColorIndexMap[nIdx].nColorCode3 = nColorCode;
                        iIndex = FindNearestColor( nColors, anPCT,
                                                   nRedValue, nGreenValue, nBlueValue );
                        psColorIndexMap[nIdx].nIndex3 = (GByte) iIndex;
                        break;
                    }

                    do
                    {
                        //nCollisions ++;
                        nIdx+=257;
                        if( nIdx >= PRIME_FOR_65536 )
                            nIdx -= PRIME_FOR_65536;
                    }
                    while( (int)psColorIndexMap[nIdx].nColorCode >= 0 &&
                            psColorIndexMap[nIdx].nColorCode != nColorCode &&
                            (int)psColorIndexMap[nIdx].nColorCode2 >= 0 &&
                            psColorIndexMap[nIdx].nColorCode2 != nColorCode&&
                            (int)psColorIndexMap[nIdx].nColorCode3 >= 0 &&
                            psColorIndexMap[nIdx].nColorCode3 != nColorCode );
                    /*if( nCollisions > nMaxCollisions )
                    {
                        nMaxCollisions = nCollisions;
                        printf("nCollisions = %d for R=%d,G=%d,B=%d\n",
                                nCollisions, nRedValue, nGreenValue, nBlueValue);
                    }*/
                }
            }
            else if( pasDynamicColorMap == NULL )
            {
                int iRed   = nRedValue *   nCLevels   / 256;
                int iGreen = nGreenValue * nCLevels / 256;
                int iBlue  = nBlueValue *  nCLevels  / 256;
                
                iIndex = pabyColorMap[iRed + iGreen * nCLevels 
                                    + iBlue * nCLevels * nCLevels];
            }
            else
            {
                GUInt32 nColorCode = MAKE_COLOR_CODE(nRedValue, nGreenValue, nBlueValue);
                GInt16* psIndex = &pasDynamicColorMap[nColorCode];
                if( *psIndex < 0 )
                    iIndex = *psIndex = FindNearestColor( nColors, anPCT,
                                                          nRedValue,
                                                          nGreenValue,
                                                          nBlueValue );
                else
                    iIndex = *psIndex;
            }

            pabyIndex[i] = (GByte) iIndex;
            if( !bDither )
                continue;

/* -------------------------------------------------------------------- */
/*      Compute Red error, and carry it on to the next error line.      */
/* -------------------------------------------------------------------- */
            nError = nRedValue - CAST_PCT(anPCT)[4*iIndex+0];
            nSixth = nError / 6;
            
            panError[i*3    ] += nSixth;
            panError[i*3+6  ] = nSixth;
            panError[i*3+3  ] += nError - 5 * nSixth;
            
            nLastRedError = 2 * nSixth;

/* -------------------------------------------------------------------- */
/*      Compute Green error, and carry it on to the next error line.    */
/* -------------------------------------------------------------------- */
            nError = nGreenValue - CAST_PCT(anPCT)[4*iIndex+1];
            nSixth = nError / 6;

            panError[i*3  +1] += nSixth;
            panError[i*3+6+1] = nSixth;
            panError[i*3+3+1] += nError - 5 * nSixth;
            
            nLastGreenError = 2 * nSixth;

/* -------------------------------------------------------------------- */
/*      Compute Blue error, and carry it on to the next error line.     */
/* -------------------------------------------------------------------- */
            nError = nBlueValue - CAST_PCT(anPCT)[4*iIndex+2];
            nSixth = nError / 6;
            
            panError[i*3  +2] += nSixth;
            panError[i*3+6+2] = nSixth;
            panError[i*3+3+2] += nError - 5 * nSixth;
            
            nLastBlueError = 2 * nSixth;
        }

/* -------------------------------------------------------------------- */
/*      Write results.                                                  */
/* -------------------------------------------------------------------- */
        GDALRasterIO( hTarget, GF_Write, 0, iScanline, nXSize, 1, 
                      pabyIndex, nXSize, 1, GDT_Byte, 0, 0 );
    }

    pfnProgress( 1.0, NULL, pProgressArg );

/* -------------------------------------------------------------------- */
/*      Cleanup                                                         */
/* -------------------------------------------------------------------- */
end_and_cleanup:
    CPLFree( pabyRed );
    CPLFree( pabyGreen );
    CPLFree( pabyBlue );
    CPLFree( pabyIndex );
    CPLFree( panError );
    CPLFree( pabyColorMap );

    return err;
}
Esempio n. 15
0
CPLErr
VRTFilteredSource::RasterIO( int nXOff, int nYOff, int nXSize, int nYSize, 
                             void *pData, int nBufXSize, int nBufYSize, 
                             GDALDataType eBufType, 
                             GSpacing nPixelSpace,
                             GSpacing nLineSpace,
                             GDALRasterIOExtraArg* psExtraArg )

{
/* -------------------------------------------------------------------- */
/*      For now we don't support filtered access to non-full            */
/*      resolution requests. Just collect the data directly without     */
/*      any operator.                                                   */
/* -------------------------------------------------------------------- */
    if( nBufXSize != nXSize || nBufYSize != nYSize )
    {
        return VRTComplexSource::RasterIO( nXOff, nYOff, nXSize, nYSize, 
                                           pData, nBufXSize, nBufYSize, 
                                           eBufType, nPixelSpace, nLineSpace, psExtraArg );
    }

    // The window we will actually request from the source raster band.
    double dfReqXOff, dfReqYOff, dfReqXSize, dfReqYSize;
    int nReqXOff, nReqYOff, nReqXSize, nReqYSize;

    // The window we will actual set _within_ the pData buffer.
    int nOutXOff, nOutYOff, nOutXSize, nOutYSize;

    if( !GetSrcDstWindow( nXOff, nYOff, nXSize, nYSize, nBufXSize, nBufYSize,
                        &dfReqXOff, &dfReqYOff, &dfReqXSize, &dfReqYSize,
                        &nReqXOff, &nReqYOff, &nReqXSize, &nReqYSize,
                        &nOutXOff, &nOutYOff, &nOutXSize, &nOutYSize ) )
        return CE_None;

    pData = ((GByte *)pData)
                            + nPixelSpace * nOutXOff
                            + nLineSpace * nOutYOff;

/* -------------------------------------------------------------------- */
/*      Determine the data type we want to request.  We try to match    */
/*      the source or destination request, and if both those fail we    */
/*      fallback to the first supported type at least as expressive     */
/*      as the request.                                                 */
/* -------------------------------------------------------------------- */
    GDALDataType eOperDataType = GDT_Unknown;
    int i;
    
    if( IsTypeSupported( eBufType ) )
        eOperDataType = eBufType;

    if( eOperDataType == GDT_Unknown 
        && IsTypeSupported( poRasterBand->GetRasterDataType() ) )
        eOperDataType = poRasterBand->GetRasterDataType();

    if( eOperDataType == GDT_Unknown )
    {
        for( i = 0; i < nSupportedTypesCount; i++ )
        {
            if( GDALDataTypeUnion( aeSupportedTypes[i], eBufType ) 
                == aeSupportedTypes[i] )
            {
                eOperDataType = aeSupportedTypes[i];
            }
        }
    }

    if( eOperDataType == GDT_Unknown )
    {
        eOperDataType = aeSupportedTypes[0];

        for( i = 1; i < nSupportedTypesCount; i++ )
        {
            if( GDALGetDataTypeSize( aeSupportedTypes[i] ) 
                > GDALGetDataTypeSize( eOperDataType ) )
            {
                eOperDataType = aeSupportedTypes[i];
            }
        }
    }

/* -------------------------------------------------------------------- */
/*      Allocate the buffer of data into which our imagery will be      */
/*      read, with the extra edge pixels as well. This will be the      */
/*      source data fed into the filter.                                */
/* -------------------------------------------------------------------- */
    int nPixelOffset, nLineOffset;
    int nExtraXSize = nOutXSize + 2 * nExtraEdgePixels;
    int nExtraYSize = nOutYSize + 2 * nExtraEdgePixels;
    GByte *pabyWorkData;

    // FIXME? : risk of multiplication overflow
    pabyWorkData = (GByte *) 
        VSICalloc( nExtraXSize * nExtraYSize,
                   (GDALGetDataTypeSize(eOperDataType) / 8) );
    
    if( pabyWorkData == NULL )
    {
        CPLError( CE_Failure, CPLE_OutOfMemory, 
                  "Work buffer allocation failed." );
        return CE_Failure;
    }

    nPixelOffset = GDALGetDataTypeSize( eOperDataType ) / 8;
    nLineOffset = nPixelOffset * nExtraXSize;

/* -------------------------------------------------------------------- */
/*      Allocate the output buffer if the passed in output buffer is    */
/*      not of the same type as our working format, or if the passed    */
/*      in buffer has an unusual organization.                          */
/* -------------------------------------------------------------------- */
    GByte *pabyOutData;

    if( nPixelSpace != nPixelOffset || nLineSpace != nLineOffset
        || eOperDataType != eBufType )
    {
        pabyOutData = (GByte *) 
            VSIMalloc3(nOutXSize, nOutYSize, nPixelOffset );

        if( pabyOutData == NULL )
        {
            CPLError( CE_Failure, CPLE_OutOfMemory, 
                      "Work buffer allocation failed." );
            return CE_Failure;
        }
    }
    else
        pabyOutData = (GByte *) pData;

/* -------------------------------------------------------------------- */
/*      Figure out the extended window that we want to load.  Note      */
/*      that we keep track of the file window as well as the amount     */
/*      we will need to edge fill past the edge of the source dataset.  */
/* -------------------------------------------------------------------- */
    int nTopFill=0, nLeftFill=0, nRightFill=0, nBottomFill=0;
    int nFileXOff, nFileYOff, nFileXSize, nFileYSize;

    nFileXOff = nReqXOff - nExtraEdgePixels;
    nFileYOff = nReqYOff - nExtraEdgePixels;
    nFileXSize = nExtraXSize;
    nFileYSize = nExtraYSize;

    if( nFileXOff < 0 )
    {
        nLeftFill = -nFileXOff;
        nFileXOff = 0;
        nFileXSize -= nLeftFill;
    }

    if( nFileYOff < 0 )
    {
        nTopFill = -nFileYOff;
        nFileYOff = 0;
        nFileYSize -= nTopFill;
    }

    if( nFileXOff + nFileXSize > poRasterBand->GetXSize() )
    {
        nRightFill = nFileXOff + nFileXSize - poRasterBand->GetXSize();
        nFileXSize -= nRightFill;
    }

    if( nFileYOff + nFileYSize > poRasterBand->GetYSize() )
    {
        nBottomFill = nFileYOff + nFileYSize - poRasterBand->GetYSize();
        nFileYSize -= nBottomFill;
    }

/* -------------------------------------------------------------------- */
/*      Load the data.                                                  */
/* -------------------------------------------------------------------- */
    CPLErr eErr;

    eErr =
        VRTComplexSource::RasterIOInternal( nFileXOff, nFileYOff, nFileXSize, nFileYSize,
                                            pabyWorkData
                                              + nLineOffset * nTopFill
                                              + nPixelOffset * nLeftFill,
                                            nFileXSize, nFileYSize, eOperDataType,
                                            nPixelOffset, nLineOffset, psExtraArg );

    if( eErr != CE_None )
    {
        if( pabyWorkData != pData )
            VSIFree( pabyWorkData );

        return eErr;
    }

/* -------------------------------------------------------------------- */
/*      Fill in missing areas.  Note that we replicate the edge         */
/*      valid values out.  We don't using "mirroring" which might be    */
/*      more suitable for some times of filters.  We also don't mark    */
/*      these pixels as "nodata" though perhaps we should.              */
/* -------------------------------------------------------------------- */
    if( nLeftFill != 0 || nRightFill != 0 )
    {
        for( i = nTopFill; i < nExtraYSize - nBottomFill; i++ )
        {
            if( nLeftFill != 0 )
                GDALCopyWords( pabyWorkData + nPixelOffset * nLeftFill
                               + i * nLineOffset, eOperDataType, 0, 
                               pabyWorkData + i * nLineOffset, eOperDataType, 
                               nPixelOffset, nLeftFill );

            if( nRightFill != 0 )
                GDALCopyWords( pabyWorkData + i * nLineOffset
                               + nPixelOffset * (nExtraXSize - nRightFill - 1),
                               eOperDataType, 0, 
                               pabyWorkData + i * nLineOffset
                               + nPixelOffset * (nExtraXSize - nRightFill),
                               eOperDataType, nPixelOffset, nRightFill );
        }
    }

    for( i = 0; i < nTopFill; i++ )
    {
        memcpy( pabyWorkData + i * nLineOffset, 
                pabyWorkData + nTopFill * nLineOffset, 
                nLineOffset );
    }

    for( i = nExtraYSize - nBottomFill; i < nExtraYSize; i++ )
    {
        memcpy( pabyWorkData + i * nLineOffset, 
                pabyWorkData + (nExtraYSize - nBottomFill - 1) * nLineOffset, 
                nLineOffset );
    }
    
/* -------------------------------------------------------------------- */
/*      Filter the data.                                                */
/* -------------------------------------------------------------------- */
    eErr = FilterData( nOutXSize, nOutYSize, eOperDataType,
                       pabyWorkData, pabyOutData );

    VSIFree( pabyWorkData );
    if( eErr != CE_None )
    {
        if( pabyOutData != pData )
            VSIFree( pabyOutData );

        return eErr;
    }
    
/* -------------------------------------------------------------------- */
/*      Copy from work buffer to target buffer.                         */
/* -------------------------------------------------------------------- */
    if( pabyOutData != pData )
    {
        for( i = 0; i < nOutYSize; i++ )
        {
            GDALCopyWords( pabyOutData + i * (nPixelOffset * nOutXSize),
                           eOperDataType, nPixelOffset,
                           ((GByte *) pData) + i * nLineSpace, 
                           eBufType, nPixelSpace, nOutXSize );
        }

        VSIFree( pabyOutData );
    }

    return CE_None;
}
Esempio n. 16
0
OGRErr OGRPGeoLayer::createFromShapeBin( GByte *pabyShape, 
                                         OGRGeometry **ppoGeom,
                                         int nBytes )

{
    *ppoGeom = NULL;

    if( nBytes < 1 )
        return OGRERR_FAILURE;

    int nSHPType = pabyShape[0];


//    CPLDebug( "PGeo", 
//              "Shape type read from PGeo data is nSHPType = %d", 
//              nSHPType );

/* -------------------------------------------------------------------- */
/*      type 50 appears to just be an alias for normal line             */
/*      strings. (#1484)                                                */
/*      Type 51 appears to just be an alias for normal polygon. (#3100) */
/*      TODO: These types include additional attributes including       */
/*      non-linear segments and such. They should be handled.           */
/* -------------------------------------------------------------------- */
    switch( nSHPType )
    {
      case 50:
        nSHPType = SHPT_ARC;
        break;
      case 51:
        nSHPType = SHPT_POLYGON;
        break;
      case 52:
        nSHPType = SHPT_POINT;
        break;
      case 53:
        nSHPType = SHPT_MULTIPOINT;
        break;
      case 54:
        nSHPType = SHPT_MULTIPATCH;
    }

/* ==================================================================== */
/*  Extract vertices for a Polygon or Arc.				*/
/* ==================================================================== */
    if(    nSHPType == SHPT_ARC
        || nSHPType == SHPT_ARCZ
        || nSHPType == SHPT_ARCM
        || nSHPType == SHPT_ARCZM
        || nSHPType == SHPT_POLYGON 
        || nSHPType == SHPT_POLYGONZ
        || nSHPType == SHPT_POLYGONM
        || nSHPType == SHPT_POLYGONZM
        || nSHPType == SHPT_MULTIPATCH 
        || nSHPType == SHPT_MULTIPATCHM)
    {
        GInt32         nPoints, nParts;
        int            i, nOffset;
        GInt32         *panPartStart;

        if (nBytes < 44)
        {
            CPLError(CE_Failure, CPLE_AppDefined,
                     "Corrupted Shape : nBytes=%d, nSHPType=%d", nBytes, nSHPType);
            return OGRERR_FAILURE;
        }

/* -------------------------------------------------------------------- */
/*      Extract part/point count, and build vertex and part arrays      */
/*      to proper size.                                                 */
/* -------------------------------------------------------------------- */
	memcpy( &nPoints, pabyShape + 40, 4 );
	memcpy( &nParts, pabyShape + 36, 4 );

	CPL_LSBPTR32( &nPoints );
	CPL_LSBPTR32( &nParts );

        if (nPoints < 0 || nParts < 0 ||
            nPoints > 50 * 1000 * 1000 || nParts > 10 * 1000 * 1000)
        {
            CPLError(CE_Failure, CPLE_AppDefined, "Corrupted Shape : nPoints=%d, nParts=%d.",
                     nPoints, nParts);
            return OGRERR_FAILURE;
        }

        int bHasZ = (  nSHPType == SHPT_POLYGONZ
                    || nSHPType == SHPT_POLYGONZM
                    || nSHPType == SHPT_ARCZ
                    || nSHPType == SHPT_ARCZM
                    || nSHPType == SHPT_MULTIPATCH 
                    || nSHPType == SHPT_MULTIPATCHM );

        int bIsMultiPatch = ( nSHPType == SHPT_MULTIPATCH || nSHPType == SHPT_MULTIPATCHM );

        /* With the previous checks on nPoints and nParts, */
        /* we should not overflow here and after */
        /* since 50 M * (16 + 8 + 8) = 1 600 MB */
        int nRequiredSize = 44 + 4 * nParts + 16 * nPoints;
        if ( bHasZ )
        {
            nRequiredSize += 16 + 8 * nPoints;
        }
        if( bIsMultiPatch )
        {
            nRequiredSize += 4 * nParts;
        }
        if (nRequiredSize > nBytes)
        {
            CPLError(CE_Failure, CPLE_AppDefined,
                     "Corrupted Shape : nPoints=%d, nParts=%d, nBytes=%d, nSHPType=%d",
                     nPoints, nParts, nBytes, nSHPType);
            return OGRERR_FAILURE;
        }

        panPartStart = (GInt32 *) VSICalloc(nParts,sizeof(GInt32));
        if (panPartStart == NULL)
        {
            CPLError(CE_Failure, CPLE_OutOfMemory,
                     "Not enough memory for shape (nPoints=%d, nParts=%d)", nPoints, nParts);
            return OGRERR_FAILURE;
        }

/* -------------------------------------------------------------------- */
/*      Copy out the part array from the record.                        */
/* -------------------------------------------------------------------- */
	memcpy( panPartStart, pabyShape + 44, 4 * nParts );
	for( i = 0; i < nParts; i++ )
	{
            CPL_LSBPTR32( panPartStart + i );

            /* We check that the offset is inside the vertex array */
            if (panPartStart[i] < 0 ||
                panPartStart[i] >= nPoints)
            {
                CPLError(CE_Failure, CPLE_AppDefined,
                         "Corrupted Shape : panPartStart[%d] = %d, nPoints = %d",
                         i, panPartStart[i], nPoints); 
                CPLFree(panPartStart);
                return OGRERR_FAILURE;
            }
            if (i > 0 && panPartStart[i] <= panPartStart[i-1])
            {
                CPLError(CE_Failure, CPLE_AppDefined,
                         "Corrupted Shape : panPartStart[%d] = %d, panPartStart[%d] = %d",
                         i, panPartStart[i], i - 1, panPartStart[i - 1]); 
                CPLFree(panPartStart);
                return OGRERR_FAILURE;
            }
	}

	nOffset = 44 + 4*nParts;

/* -------------------------------------------------------------------- */
/*      If this is a multipatch, we will also have parts types.  For    */
/*      now we ignore and skip past them.                               */
/* -------------------------------------------------------------------- */
        if( bIsMultiPatch )
            nOffset += 4*nParts;
        
/* -------------------------------------------------------------------- */
/*      Copy out the vertices from the record.                          */
/* -------------------------------------------------------------------- */
        double *padfX = (double *) VSIMalloc(sizeof(double)*nPoints);
        double *padfY = (double *) VSIMalloc(sizeof(double)*nPoints);
        double *padfZ = (double *) VSICalloc(sizeof(double),nPoints);
        if (padfX == NULL || padfY == NULL || padfZ == NULL)
        {
            CPLFree( panPartStart );
            CPLFree( padfX );
            CPLFree( padfY );
            CPLFree( padfZ );
            CPLError(CE_Failure, CPLE_OutOfMemory,
                     "Not enough memory for shape (nPoints=%d, nParts=%d)", nPoints, nParts);
            return OGRERR_FAILURE;
        }

	for( i = 0; i < nPoints; i++ )
	{
	    memcpy(padfX + i, pabyShape + nOffset + i * 16, 8 );
	    memcpy(padfY + i, pabyShape + nOffset + i * 16 + 8, 8 );
            CPL_LSBPTR64( padfX + i );
            CPL_LSBPTR64( padfY + i );
	}

        nOffset += 16*nPoints;
        
/* -------------------------------------------------------------------- */
/*      If we have a Z coordinate, collect that now.                    */
/* -------------------------------------------------------------------- */
        if( bHasZ )
        {
            for( i = 0; i < nPoints; i++ )
            {
                memcpy( padfZ + i, pabyShape + nOffset + 16 + i*8, 8 );
                CPL_LSBPTR64( padfZ + i );
            }

            nOffset += 16 + 8*nPoints;
        }

/* -------------------------------------------------------------------- */
/*      Build corresponding OGR objects.                                */
/* -------------------------------------------------------------------- */
        if(    nSHPType == SHPT_ARC 
            || nSHPType == SHPT_ARCZ
            || nSHPType == SHPT_ARCM
            || nSHPType == SHPT_ARCZM )
        {
/* -------------------------------------------------------------------- */
/*      Arc - As LineString                                             */
/* -------------------------------------------------------------------- */
            if( nParts == 1 )
            {
                OGRLineString *poLine = new OGRLineString();
                *ppoGeom = poLine;

                poLine->setPoints( nPoints, padfX, padfY, padfZ );
            }

/* -------------------------------------------------------------------- */
/*      Arc - As MultiLineString                                        */
/* -------------------------------------------------------------------- */
            else
            {
                OGRMultiLineString *poMulti = new OGRMultiLineString;
                *ppoGeom = poMulti;

                for( i = 0; i < nParts; i++ )
                {
                    OGRLineString *poLine = new OGRLineString;
                    int nVerticesInThisPart;

                    if( i == nParts-1 )
                        nVerticesInThisPart = nPoints - panPartStart[i];
                    else
                        nVerticesInThisPart = 
                            panPartStart[i+1] - panPartStart[i];

                    poLine->setPoints( nVerticesInThisPart, 
                                       padfX + panPartStart[i], 
                                       padfY + panPartStart[i], 
                                       padfZ + panPartStart[i] );

                    poMulti->addGeometryDirectly( poLine );
                }
            }
        } /* ARC */

/* -------------------------------------------------------------------- */
/*      Polygon                                                         */
/* -------------------------------------------------------------------- */
        else if(    nSHPType == SHPT_POLYGON
                 || nSHPType == SHPT_POLYGONZ
                 || nSHPType == SHPT_POLYGONM
                 || nSHPType == SHPT_POLYGONZM )
        {
            OGRPolygon *poMulti = new OGRPolygon;
            *ppoGeom = poMulti;

            for( i = 0; i < nParts; i++ )
            {
                OGRLinearRing *poRing = new OGRLinearRing;
                int nVerticesInThisPart;

                if( i == nParts-1 )
                    nVerticesInThisPart = nPoints - panPartStart[i];
                else
                    nVerticesInThisPart = 
                        panPartStart[i+1] - panPartStart[i];

                poRing->setPoints( nVerticesInThisPart, 
                                   padfX + panPartStart[i], 
                                   padfY + panPartStart[i], 
                                   padfZ + panPartStart[i] );

                poMulti->addRingDirectly( poRing );
            }
        } /* polygon */

/* -------------------------------------------------------------------- */
/*      Multipatch                                                      */
/* -------------------------------------------------------------------- */
        else if( bIsMultiPatch )
        {
            /* return to this later */
        } 

        CPLFree( panPartStart );
        CPLFree( padfX );
        CPLFree( padfY );
        CPLFree( padfZ );

        if( !bHasZ )
            (*ppoGeom)->setCoordinateDimension( 2 );

        return OGRERR_NONE;
    }

/* ==================================================================== */
/*  Extract vertices for a MultiPoint.					*/
/* ==================================================================== */
    else if(    nSHPType == SHPT_MULTIPOINT
             || nSHPType == SHPT_MULTIPOINTM
             || nSHPType == SHPT_MULTIPOINTZ
             || nSHPType == SHPT_MULTIPOINTZM )
    {
#ifdef notdef
	int32		nPoints;
	int    		i, nOffset;

	memcpy( &nPoints, psSHP->pabyRec + 44, 4 );
	if( bBigEndian ) SwapWord( 4, &nPoints );

	psShape->nVertices = nPoints;
        psShape->padfX = (double *) calloc(nPoints,sizeof(double));
        psShape->padfY = (double *) calloc(nPoints,sizeof(double));
        psShape->padfZ = (double *) calloc(nPoints,sizeof(double));
        psShape->padfM = (double *) calloc(nPoints,sizeof(double));

	for( i = 0; i < nPoints; i++ )
	{
	    memcpy(psShape->padfX+i, psSHP->pabyRec + 48 + 16 * i, 8 );
	    memcpy(psShape->padfY+i, psSHP->pabyRec + 48 + 16 * i + 8, 8 );

	    if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
	    if( bBigEndian ) SwapWord( 8, psShape->padfY + i );
	}

        nOffset = 48 + 16*nPoints;
        
/* -------------------------------------------------------------------- */
/*	Get the X/Y bounds.						*/
/* -------------------------------------------------------------------- */
        memcpy( &(psShape->dfXMin), psSHP->pabyRec + 8 +  4, 8 );
        memcpy( &(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 );
        memcpy( &(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 );
        memcpy( &(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 );

	if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) );
	if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) );
	if( bBigEndian ) SwapWord( 8, &(psShape->dfXMax) );
	if( bBigEndian ) SwapWord( 8, &(psShape->dfYMax) );

/* -------------------------------------------------------------------- */
/*      If we have a Z coordinate, collect that now.                    */
/* -------------------------------------------------------------------- */
        if( psShape->nSHPType == SHPT_MULTIPOINTZ || psShape->nSHPType == SHPT_MULTIPOINTZM )
        {
            memcpy( &(psShape->dfZMin), psSHP->pabyRec + nOffset, 8 );
            memcpy( &(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 );
            
            if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) );
            if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) );
            
            for( i = 0; i < nPoints; i++ )
            {
                memcpy( psShape->padfZ + i,
                        psSHP->pabyRec + nOffset + 16 + i*8, 8 );
                if( bBigEndian ) SwapWord( 8, psShape->padfZ + i );
            }

            nOffset += 16 + 8*nPoints;
        }

/* -------------------------------------------------------------------- */
/*      If we have a M measure value, then read it now.  We assume      */
/*      that the measure can be present for any shape if the size is    */
/*      big enough, but really it will only occur for the Z shapes      */
/*      (options), and the M shapes.                                    */
/* -------------------------------------------------------------------- */
        if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints )
        {
            memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
            memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
            
            if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) );
            if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) );
            
            for( i = 0; i < nPoints; i++ )
            {
                memcpy( psShape->padfM + i,
                        psSHP->pabyRec + nOffset + 16 + i*8, 8 );
                if( bBigEndian ) SwapWord( 8, psShape->padfM + i );
            }
        }
#endif
    }

/* ==================================================================== */
/*      Extract vertices for a point.                                   */
/* ==================================================================== */
    else if(    nSHPType == SHPT_POINT
             || nSHPType == SHPT_POINTM
             || nSHPType == SHPT_POINTZ
             || nSHPType == SHPT_POINTZM )
    {
        int	nOffset;
        double  dfX, dfY, dfZ = 0;

        int bHasZ = (nSHPType == SHPT_POINTZ || nSHPType == SHPT_POINTZM);

        if (nBytes < 4 + 8 + 8 + ((nSHPType == SHPT_POINTZ) ? 8 : 0))
        {
            CPLError(CE_Failure, CPLE_AppDefined,
                     "Corrupted Shape : nBytes=%d, nSHPType=%d", nBytes, nSHPType);
            return OGRERR_FAILURE;
        }
        
	memcpy( &dfX, pabyShape + 4, 8 );
	memcpy( &dfY, pabyShape + 4 + 8, 8 );

        CPL_LSBPTR64( &dfX );
        CPL_LSBPTR64( &dfY );
        nOffset = 20 + 8;
        
        if( bHasZ )
        {
            memcpy( &dfZ, pabyShape + 4 + 16, 8 );
            CPL_LSBPTR64( &dfZ );
        }

        *ppoGeom = new OGRPoint( dfX, dfY, dfZ );

        if( !bHasZ )
            (*ppoGeom)->setCoordinateDimension( 2 );

        return OGRERR_NONE;
    }

    char* pszHex = CPLBinaryToHex( nBytes, pabyShape );
    CPLDebug( "PGEO", "Unsupported geometry type:%d\nnBytes=%d, hex=%s",
              nSHPType, nBytes, pszHex );
    CPLFree(pszHex);

    return OGRERR_FAILURE;
}
Esempio n. 17
0
AIGInfo_t *AIGOpen( const char * pszInputName, const char * pszAccess )

{
    AIGInfo_t	*psInfo;
    char        *pszCoverName;

    (void) pszAccess;

/* -------------------------------------------------------------------- */
/*      If the pass name ends in .adf assume a file within the          */
/*      coverage has been selected, and strip that off the coverage     */
/*      name.                                                           */
/* -------------------------------------------------------------------- */
    pszCoverName = CPLStrdup( pszInputName );
    if( EQUAL(pszCoverName+strlen(pszCoverName)-4, ".adf") )
    {
        int      i;

        for( i = strlen(pszCoverName)-1; i > 0; i-- )
        {
            if( pszCoverName[i] == '\\' || pszCoverName[i] == '/' )
            {
                pszCoverName[i] = '\0';
                break;
            }
        }

        if( i == 0 )
            strcpy(pszCoverName,".");
    }

/* -------------------------------------------------------------------- */
/*      Allocate info structure.                                        */
/* -------------------------------------------------------------------- */
    psInfo = (AIGInfo_t *) CPLCalloc(sizeof(AIGInfo_t),1);
    psInfo->bHasWarned = FALSE;
    psInfo->pszCoverName = pszCoverName;

/* -------------------------------------------------------------------- */
/*      Read the header file.                                           */
/* -------------------------------------------------------------------- */
    if( AIGReadHeader( pszCoverName, psInfo ) != CE_None )
    {
        CPLFree( pszCoverName );
        CPLFree( psInfo );
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Read the extents.                                               */
/* -------------------------------------------------------------------- */
    if( AIGReadBounds( pszCoverName, psInfo ) != CE_None )
    {
        AIGClose( psInfo );
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Compute the number of pixels and lines, and the number of       */
/*      tile files.                                                     */
/* -------------------------------------------------------------------- */
    if (psInfo->dfCellSizeX <= 0 || psInfo->dfCellSizeY <= 0)
    {
        CPLError( CE_Failure, CPLE_AppDefined, 
                  "Illegal cell size : %f x %f",
                  psInfo->dfCellSizeX, psInfo->dfCellSizeY );
        AIGClose( psInfo );
        return NULL;
    }

    psInfo->nPixels = (int)
        ((psInfo->dfURX - psInfo->dfLLX + 0.5 * psInfo->dfCellSizeX) 
		/ psInfo->dfCellSizeX);
    psInfo->nLines = (int)
        ((psInfo->dfURY - psInfo->dfLLY + 0.5 * psInfo->dfCellSizeY) 
		/ psInfo->dfCellSizeY);
    
    if (psInfo->nPixels <= 0 || psInfo->nLines <= 0)
    {
        CPLError( CE_Failure, CPLE_AppDefined, 
                  "Invalid raster dimensions : %d x %d",
                  psInfo->nPixels, psInfo->nLines );
        AIGClose( psInfo );
        return NULL;
    }

    if (psInfo->nBlockXSize <= 0 || psInfo->nBlockYSize <= 0 ||
        psInfo->nBlocksPerRow <= 0 || psInfo->nBlocksPerColumn <= 0 ||
        psInfo->nBlockXSize > INT_MAX / psInfo->nBlocksPerRow ||
        psInfo->nBlockYSize > INT_MAX / psInfo->nBlocksPerColumn)
    {
        CPLError( CE_Failure, CPLE_AppDefined, 
                  "Invalid block characteristics: nBlockXSize=%d, "
                  "nBlockYSize=%d, nBlocksPerRow=%d, nBlocksPerColumn=%d",
                  psInfo->nBlockXSize, psInfo->nBlockYSize,
                  psInfo->nBlocksPerRow, psInfo->nBlocksPerColumn);
        AIGClose( psInfo );
        return NULL;
    }

    psInfo->nTileXSize = psInfo->nBlockXSize * psInfo->nBlocksPerRow;
    psInfo->nTileYSize = psInfo->nBlockYSize * psInfo->nBlocksPerColumn;

    psInfo->nTilesPerRow = (psInfo->nPixels-1) / psInfo->nTileXSize + 1;
    psInfo->nTilesPerColumn = (psInfo->nLines-1) / psInfo->nTileYSize + 1;

    if (psInfo->nTilesPerRow > INT_MAX / psInfo->nTilesPerColumn)
    {
        CPLError(CE_Failure, CPLE_OutOfMemory, "Too many tiles");
        AIGClose( psInfo );
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Setup tile infos, but defer reading of tile data.               */
/* -------------------------------------------------------------------- */
    psInfo->pasTileInfo = (AIGTileInfo *) 
        VSICalloc(sizeof(AIGTileInfo),
                  psInfo->nTilesPerRow * psInfo->nTilesPerColumn);
    if (psInfo->pasTileInfo == NULL)
    {
        CPLError(CE_Failure, CPLE_OutOfMemory, "Cannot allocate tile info array");
        AIGClose( psInfo );
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Read the statistics.                                            */
/* -------------------------------------------------------------------- */
    if( AIGReadStatistics( pszCoverName, psInfo ) != CE_None )
    {
        AIGClose( psInfo );
        return NULL;
    }

    return( psInfo );
}
Esempio n. 18
0
GXFHandle GXFOpen( const char * pszFilename )

{
    FILE	*fp;
    GXFInfo_t	*psGXF;
    char	szTitle[71];
    char	**papszList;
    int     nHeaderCount = 0;

/* -------------------------------------------------------------------- */
/*      We open in binary to ensure that we can efficiently seek()      */
/*      to any location when reading scanlines randomly.  If we         */
/*      opened as text we might still be able to seek(), but I          */
/*      believe that on Windows, the C library has to read through      */
/*      all the data to find the right spot taking into account DOS     */
/*      CRs.                                                            */
/* -------------------------------------------------------------------- */
    fp = VSIFOpen( pszFilename, "rb" );

    if( fp == NULL )
    {
        /* how to effectively communicate this error out? */
        CPLError( CE_Failure, CPLE_OpenFailed,
                  "Unable to open file: %s\n", pszFilename );
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Create the GXF Information object.                              */
/* -------------------------------------------------------------------- */
    psGXF = (GXFInfo_t *) VSICalloc( sizeof(GXFInfo_t), 1 );
    psGXF->fp = fp;
    psGXF->dfTransformScale = 1.0;
    psGXF->nSense = GXFS_LL_RIGHT;
    psGXF->dfXPixelSize = 1.0;
    psGXF->dfYPixelSize = 1.0;
    psGXF->dfSetDummyTo = -1e12;

    psGXF->dfUnitToMeter = 1.0;
    psGXF->pszTitle = VSIStrdup("");
    
/* -------------------------------------------------------------------- */
/*      Read the header, one line at a time.                            */
/* -------------------------------------------------------------------- */
    while( (papszList = GXFReadHeaderValue( fp, szTitle)) != NULL && nHeaderCount < MAX_HEADER_COUNT )
    {
        if( EQUALN(szTitle,"#TITL",5) )
        {
            CPLFree( psGXF->pszTitle );
            psGXF->pszTitle = CPLStrdup( papszList[0] );
        }
        else if( EQUALN(szTitle,"#POIN",5) )
        {
            psGXF->nRawXSize = atoi(papszList[0]);
        }
        else if( EQUALN(szTitle,"#ROWS",5) )
        {
            psGXF->nRawYSize = atoi(papszList[0]);
        }
        else if( EQUALN(szTitle,"#PTSE",5) )
        {
            psGXF->dfXPixelSize = CPLAtof(papszList[0]);
        }
        else if( EQUALN(szTitle,"#RWSE",5) )
        {
            psGXF->dfYPixelSize = CPLAtof(papszList[0]);
        }
        else if( EQUALN(szTitle,"#DUMM",5) )
        {
            memset( psGXF->szDummy, 0, sizeof(psGXF->szDummy));
            strncpy( psGXF->szDummy, papszList[0], sizeof(psGXF->szDummy) - 1);
            psGXF->dfSetDummyTo = CPLAtof(papszList[0]);
        }
        else if( EQUALN(szTitle,"#XORI",5) )
        {
            psGXF->dfXOrigin = CPLAtof(papszList[0]);
        }
        else if( EQUALN(szTitle,"#YORI",5) )
        {
            psGXF->dfYOrigin = CPLAtof(papszList[0]);
        }
        else if( EQUALN(szTitle,"#ZMIN",5) )
        {
            psGXF->dfZMinimum = CPLAtof(papszList[0]);
        }
        else if( EQUALN(szTitle,"#ZMAX",5) )
        {
            psGXF->dfZMaximum = CPLAtof(papszList[0]);
        }
        else if( EQUALN(szTitle,"#SENS",5) )
        {
            psGXF->nSense = atoi(papszList[0]);
        }
        else if( EQUALN(szTitle,"#MAP_PROJECTION",8) )
        {
            psGXF->papszMapProjection = papszList;
            papszList = NULL;
        }
        else if( EQUALN(szTitle,"#MAP_D",5) )
        {
            psGXF->papszMapDatumTransform = papszList;
            papszList = NULL;
        }
        else if( EQUALN(szTitle,"#UNIT",5) )
        {
            char	**papszFields;

            papszFields = CSLTokenizeStringComplex( papszList[0], ", ",
                                                    TRUE, TRUE );

            if( CSLCount(papszFields) > 1 )
            {
                psGXF->pszUnitName = VSIStrdup( papszFields[0] );
                psGXF->dfUnitToMeter = CPLAtof( papszFields[1] );
                if( psGXF->dfUnitToMeter == 0.0 )
                    psGXF->dfUnitToMeter = 1.0;
            }

            CSLDestroy( papszFields );
        }
        else if( EQUALN(szTitle,"#TRAN",5) )
        {
            char	**papszFields;

            papszFields = CSLTokenizeStringComplex( papszList[0], ", ",
                                                    TRUE, TRUE );

            if( CSLCount(papszFields) > 1 )
            {
                psGXF->dfTransformScale = CPLAtof(papszFields[0]);
                psGXF->dfTransformOffset = CPLAtof(papszFields[1]);
            }

            if( CSLCount(papszFields) > 2 )
                psGXF->pszTransformName = CPLStrdup( papszFields[2] );

            CSLDestroy( papszFields );
        }
        else if( EQUALN(szTitle,"#GTYPE",5) )
        {
            psGXF->nGType = atoi(papszList[0]);
        }

        CSLDestroy( papszList );
        nHeaderCount ++;
    }

    CSLDestroy( papszList );

/* -------------------------------------------------------------------- */
/*      Did we find the #GRID?                                          */
/* -------------------------------------------------------------------- */
    if( !EQUALN(szTitle,"#GRID",5) )
    {
        GXFClose( psGXF );
        CPLError( CE_Failure, CPLE_WrongFormat,
                  "Didn't parse through to #GRID successfully in.\n"
                  "file `%s'.\n",
                  pszFilename );

        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Allocate, and initialize the raw scanline offset array.         */
/* -------------------------------------------------------------------- */
    if( psGXF->nRawYSize <= 0 )
    {
        GXFClose( psGXF );
        return NULL;
    }

    psGXF->panRawLineOffset = (long *)
        VSICalloc( sizeof(long), psGXF->nRawYSize+1 );
    if( psGXF->panRawLineOffset == NULL )
    {
        GXFClose( psGXF );
        return NULL;
    }

    psGXF->panRawLineOffset[0] = VSIFTell( psGXF->fp );

/* -------------------------------------------------------------------- */
/*      Update the zmin/zmax values to take into account #TRANSFORM     */
/*      information.                                                    */
/* -------------------------------------------------------------------- */
    if( psGXF->dfZMinimum != 0.0 || psGXF->dfZMaximum != 0.0 )
    {
        psGXF->dfZMinimum = (psGXF->dfZMinimum * psGXF->dfTransformScale)
            			+ psGXF->dfTransformOffset;
        psGXF->dfZMaximum = (psGXF->dfZMaximum * psGXF->dfTransformScale)
            			+ psGXF->dfTransformOffset;
    }

    return( (GXFHandle) psGXF );
}
Esempio n. 19
0
GDALDataset *CTGDataset::Open( GDALOpenInfo * poOpenInfo )

{
    int         i;

    if (!Identify(poOpenInfo))
        return NULL;

    CPLString osFilename(poOpenInfo->pszFilename);

    /*  GZipped grid_cell.gz files are common, so automagically open them */
    /*  if the /vsigzip/ has not been explicitely passed */
    const char* pszFilename = CPLGetFilename(poOpenInfo->pszFilename);
    if ((EQUAL(pszFilename, "grid_cell.gz") ||
         EQUAL(pszFilename, "grid_cell1.gz") ||
         EQUAL(pszFilename, "grid_cell2.gz")) &&
        !EQUALN(poOpenInfo->pszFilename, "/vsigzip/", 9))
    {
        osFilename = "/vsigzip/";
        osFilename += poOpenInfo->pszFilename;
    }

    if (poOpenInfo->eAccess == GA_Update)
    {
        CPLError( CE_Failure, CPLE_NotSupported,
                  "The CTG driver does not support update access to existing"
                  " datasets.\n" );
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Find dataset characteristics                                    */
/* -------------------------------------------------------------------- */
    VSILFILE* fp = VSIFOpenL(osFilename.c_str(), "rb");
    if (fp == NULL)
        return NULL;

    char szHeader[HEADER_LINE_COUNT * 80+1];
    szHeader[HEADER_LINE_COUNT * 80] = 0;
    if (VSIFReadL(szHeader, 1, HEADER_LINE_COUNT * 80, fp) != HEADER_LINE_COUNT * 80)
    {
        VSIFCloseL(fp);
        return NULL;
    }

    for(i=HEADER_LINE_COUNT * 80 - 1;i>=0;i--)
    {
        if (szHeader[i] == ' ')
            szHeader[i] = 0;
        else
            break;
    }

    char szField[11];
    int nRows = atoi(ExtractField(szField, szHeader, 0, 10));
    int nCols = atoi(ExtractField(szField, szHeader, 20, 10));

/* -------------------------------------------------------------------- */
/*      Create a corresponding GDALDataset.                             */
/* -------------------------------------------------------------------- */
    CTGDataset         *poDS;

    poDS = new CTGDataset();
    poDS->fp = fp;
    fp = NULL;
    poDS->nRasterXSize = nCols;
    poDS->nRasterYSize = nRows;

    poDS->SetMetadataItem("TITLE", szHeader + 4 * 80);

    poDS->nCellSize = atoi(ExtractField(szField, szHeader, 35, 5));
    if (poDS->nCellSize <= 0 || poDS->nCellSize >= 10000)
    {
        delete poDS;
        return NULL;
    }
    poDS->nNWEasting = atoi(ExtractField(szField, szHeader + 3*80, 40, 10));
    poDS->nNWNorthing = atoi(ExtractField(szField, szHeader + 3*80, 50, 10));
    poDS->nUTMZone = atoi(ExtractField(szField, szHeader, 50, 5));
    if (poDS->nUTMZone <= 0 || poDS->nUTMZone > 60)
    {
        delete poDS;
        return NULL;
    }

    OGRSpatialReference oSRS;
    oSRS.importFromEPSG(32600 + poDS->nUTMZone);
    oSRS.exportToWkt(&poDS->pszProjection);

    if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize))
    {
        delete poDS;
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Read the imagery                                                */
/* -------------------------------------------------------------------- */
    GByte* pabyImage = (GByte*)VSICalloc(nCols * nRows, 6 * sizeof(int));
    if (pabyImage == NULL)
    {
        delete poDS;
        return NULL;
    }
    poDS->pabyImage = pabyImage;

/* -------------------------------------------------------------------- */
/*      Create band information objects.                                */
/* -------------------------------------------------------------------- */
    poDS->nBands = 6;
    for( i = 0; i < poDS->nBands; i++ )
    {
        poDS->SetBand( i+1, new CTGRasterBand( poDS, i+1 ) );
        poDS->GetRasterBand(i+1)->SetDescription(apszBandDescription[i]);
    }

/* -------------------------------------------------------------------- */
/*      Initialize any PAM information.                                 */
/* -------------------------------------------------------------------- */
    poDS->SetDescription( poOpenInfo->pszFilename );
    poDS->TryLoadXML();

/* -------------------------------------------------------------------- */
/*      Support overviews.                                              */
/* -------------------------------------------------------------------- */
    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );

    return( poDS );
}
Esempio n. 20
0
CPLErr CPL_STDCALL
GDALFillNodata( GDALRasterBandH hTargetBand, 
                GDALRasterBandH hMaskBand,
                double dfMaxSearchDist, 
                CPL_UNUSED int bDeprecatedOption,
                int nSmoothingIterations,
                CPL_UNUSED char **papszOptions,
                GDALProgressFunc pfnProgress, 
                void * pProgressArg )

{
    VALIDATE_POINTER1( hTargetBand, "GDALFillNodata", CE_Failure );

    int nXSize = GDALGetRasterBandXSize( hTargetBand );
    int nYSize = GDALGetRasterBandYSize( hTargetBand );
    CPLErr eErr = CE_None;

    // Special "x" pixel values identifying pixels as special.
    GUInt32 nNoDataVal;
    GDALDataType eType;

    if( dfMaxSearchDist == 0.0 )
        dfMaxSearchDist = MAX(nXSize,nYSize) + 1;

    int nMaxSearchDist = (int) floor(dfMaxSearchDist);

    if( nXSize > 65533 || nYSize > 65533 )
    {
        eType = GDT_UInt32;
        nNoDataVal = 4000002;
    }
    else
    {
        eType = GDT_UInt16;
        nNoDataVal = 65535;
    }

    if( hMaskBand == NULL )
        hMaskBand = GDALGetMaskBand( hTargetBand );

    /* If there are smoothing iterations, reserve 10% of the progress for them */
    double dfProgressRatio = (nSmoothingIterations > 0) ? 0.9 : 1.0;

/* -------------------------------------------------------------------- */
/*      Initialize progress counter.                                    */
/* -------------------------------------------------------------------- */
    if( pfnProgress == NULL )
        pfnProgress = GDALDummyProgress;

    if( !pfnProgress( 0.0, "Filling...", pProgressArg ) )
    {
        CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
        return CE_Failure;
    }

/* -------------------------------------------------------------------- */
/*      Create a work file to hold the Y "last value" indices.          */
/* -------------------------------------------------------------------- */
    GDALDriverH  hDriver = GDALGetDriverByName( "GTiff" );
    if (hDriver == NULL)
    {
        CPLError(CE_Failure, CPLE_AppDefined,
                 "GDALFillNodata needs GTiff driver");
        return CE_Failure;
    }
    
    GDALDatasetH hYDS;
    GDALRasterBandH hYBand;
    static const char *apszOptions[] = { "COMPRESS=LZW", "BIGTIFF=IF_SAFER", 
                                         NULL };
    CPLString osTmpFile = CPLGenerateTempFilename("");
    CPLString osYTmpFile = osTmpFile + "fill_y_work.tif";
    
    hYDS = GDALCreate( hDriver, osYTmpFile, nXSize, nYSize, 1, 
                       eType, (char **) apszOptions );
    
    if( hYDS == NULL )
        return CE_Failure;

    hYBand = GDALGetRasterBand( hYDS, 1 );

/* -------------------------------------------------------------------- */
/*      Create a work file to hold the pixel value associated with      */
/*      the "last xy value" pixel.                                      */
/* -------------------------------------------------------------------- */
    GDALDatasetH hValDS;
    GDALRasterBandH hValBand;
    CPLString osValTmpFile = osTmpFile + "fill_val_work.tif";

    hValDS = GDALCreate( hDriver, osValTmpFile, nXSize, nYSize, 1,
                         GDALGetRasterDataType( hTargetBand ), 
                         (char **) apszOptions );
    
    if( hValDS == NULL )
        return CE_Failure;

    hValBand = GDALGetRasterBand( hValDS, 1 );

/* -------------------------------------------------------------------- */
/*      Create a mask file to make it clear what pixels can be filtered */
/*      on the filtering pass.                                          */
/* -------------------------------------------------------------------- */
    GDALDatasetH hFiltMaskDS;
    GDALRasterBandH hFiltMaskBand;
    CPLString osFiltMaskTmpFile = osTmpFile + "fill_filtmask_work.tif";
    
    hFiltMaskDS = 
        GDALCreate( hDriver, osFiltMaskTmpFile, nXSize, nYSize, 1,
                    GDT_Byte, (char **) apszOptions );
    
    if( hFiltMaskDS == NULL )
        return CE_Failure;

    hFiltMaskBand = GDALGetRasterBand( hFiltMaskDS, 1 );

/* -------------------------------------------------------------------- */
/*      Allocate buffers for last scanline and this scanline.           */
/* -------------------------------------------------------------------- */
    GUInt32 *panLastY, *panThisY, *panTopDownY;
    float   *pafLastValue, *pafThisValue, *pafScanline, *pafTopDownValue;
    GByte   *pabyMask, *pabyFiltMask;
    int     iX;
    int     iY;

    panLastY = (GUInt32 *) VSICalloc(nXSize,sizeof(GUInt32));
    panThisY = (GUInt32 *) VSICalloc(nXSize,sizeof(GUInt32));
    panTopDownY = (GUInt32 *) VSICalloc(nXSize,sizeof(GUInt32));
    pafLastValue = (float *) VSICalloc(nXSize,sizeof(float));
    pafThisValue = (float *) VSICalloc(nXSize,sizeof(float));
    pafTopDownValue = (float *) VSICalloc(nXSize,sizeof(float));
    pafScanline = (float *) VSICalloc(nXSize,sizeof(float));
    pabyMask = (GByte *) VSICalloc(nXSize,1);
    pabyFiltMask = (GByte *) VSICalloc(nXSize,1);
    if (panLastY == NULL || panThisY == NULL || panTopDownY == NULL ||
        pafLastValue == NULL || pafThisValue == NULL || pafTopDownValue == NULL ||
        pafScanline == NULL || pabyMask == NULL || pabyFiltMask == NULL)
    {
        CPLError(CE_Failure, CPLE_OutOfMemory,
                 "Could not allocate enough memory for temporary buffers");

        eErr = CE_Failure;
        goto end;
    }

    for( iX = 0; iX < nXSize; iX++ )
    {
        panLastY[iX] = nNoDataVal;
    }

/* ==================================================================== */
/*      Make first pass from top to bottom collecting the "last         */
/*      known value" for each column and writing it out to the work     */
/*      files.                                                          */
/* ==================================================================== */
    
    for( iY = 0; iY < nYSize && eErr == CE_None; iY++ )
    {
/* -------------------------------------------------------------------- */
/*      Read data and mask for this line.                               */
/* -------------------------------------------------------------------- */
        eErr = 
            GDALRasterIO( hMaskBand, GF_Read, 0, iY, nXSize, 1, 
                          pabyMask, nXSize, 1, GDT_Byte, 0, 0 );

        if( eErr != CE_None )
            break;

        eErr = 
            GDALRasterIO( hTargetBand, GF_Read, 0, iY, nXSize, 1, 
                          pafScanline, nXSize, 1, GDT_Float32, 0, 0 );
        
        if( eErr != CE_None )
            break;
        
/* -------------------------------------------------------------------- */
/*      Figure out the most recent pixel for each column.               */
/* -------------------------------------------------------------------- */
        
        for( iX = 0; iX < nXSize; iX++ )
        {
            if( pabyMask[iX] )
            {
                pafThisValue[iX] = pafScanline[iX];
                panThisY[iX] = iY;
            }
            else if( iY <= dfMaxSearchDist + panLastY[iX] )
            {
                pafThisValue[iX] = pafLastValue[iX];
                panThisY[iX] = panLastY[iX];
            }
            else
            {
                panThisY[iX] = nNoDataVal;
            }
        }
        
/* -------------------------------------------------------------------- */
/*      Write out best index/value to working files.                    */
/* -------------------------------------------------------------------- */
        eErr = GDALRasterIO( hYBand, GF_Write, 0, iY, nXSize, 1, 
                             panThisY, nXSize, 1, GDT_UInt32, 0, 0 );
        if( eErr != CE_None )
            break;

        eErr = GDALRasterIO( hValBand, GF_Write, 0, iY, nXSize, 1, 
                             pafThisValue, nXSize, 1, GDT_Float32, 0, 0 );
        if( eErr != CE_None )
            break;

/* -------------------------------------------------------------------- */
/*      Flip this/last buffers.                                         */
/* -------------------------------------------------------------------- */
        {
            float *pafTmp = pafThisValue;
            pafThisValue = pafLastValue;
            pafLastValue = pafTmp;

            GUInt32 *panTmp = panThisY;
            panThisY = panLastY;
            panLastY = panTmp;
        }

/* -------------------------------------------------------------------- */
/*      report progress.                                                */
/* -------------------------------------------------------------------- */
        if( eErr == CE_None
            && !pfnProgress( dfProgressRatio * (0.5*(iY+1) / (double)nYSize), 
                             "Filling...", pProgressArg ) )
        {
            CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
            eErr = CE_Failure;
        }
    }

/* ==================================================================== */
/*      Now we will do collect similar this/last information from       */
/*      bottom to top and use it in combination with the top to         */
/*      bottom search info to interpolate.                              */
/* ==================================================================== */
    for( iY = nYSize-1; iY >= 0 && eErr == CE_None; iY-- )
    {
        eErr = 
            GDALRasterIO( hMaskBand, GF_Read, 0, iY, nXSize, 1, 
                          pabyMask, nXSize, 1, GDT_Byte, 0, 0 );

        if( eErr != CE_None )
            break;

        eErr = 
            GDALRasterIO( hTargetBand, GF_Read, 0, iY, nXSize, 1, 
                          pafScanline, nXSize, 1, GDT_Float32, 0, 0 );
        
        if( eErr != CE_None )
            break;
        
/* -------------------------------------------------------------------- */
/*      Figure out the most recent pixel for each column.               */
/* -------------------------------------------------------------------- */
        
        for( iX = 0; iX < nXSize; iX++ )
        {
            if( pabyMask[iX] )
            {
                pafThisValue[iX] = pafScanline[iX];
                panThisY[iX] = iY;
            }
            else if( panLastY[iX] - iY <= dfMaxSearchDist )
            {
                pafThisValue[iX] = pafLastValue[iX];
                panThisY[iX] = panLastY[iX];
            }
            else
            {
                panThisY[iX] = nNoDataVal;
            }
        }
        
/* -------------------------------------------------------------------- */
/*      Load the last y and corresponding value from the top down pass. */
/* -------------------------------------------------------------------- */
        eErr = 
            GDALRasterIO( hYBand, GF_Read, 0, iY, nXSize, 1, 
                          panTopDownY, nXSize, 1, GDT_UInt32, 0, 0 );

        if( eErr != CE_None )
            break;

        eErr = 
            GDALRasterIO( hValBand, GF_Read, 0, iY, nXSize, 1, 
                          pafTopDownValue, nXSize, 1, GDT_Float32, 0, 0 );

        if( eErr != CE_None )
            break;

/* -------------------------------------------------------------------- */
/*      Attempt to interpolate any pixels that are nodata.              */
/* -------------------------------------------------------------------- */
        memset( pabyFiltMask, 0, nXSize );
        for( iX = 0; iX < nXSize; iX++ )
        {
            int iStep, iQuad;
            int nThisMaxSearchDist = nMaxSearchDist;

            // If this was a valid target - no change.
            if( pabyMask[iX] )
                continue;

            // Quadrants 0:topleft, 1:bottomleft, 2:topright, 3:bottomright
            double adfQuadDist[4];
            double adfQuadValue[4];

            for( iQuad = 0; iQuad < 4; iQuad++ )
            {
                adfQuadDist[iQuad] = dfMaxSearchDist + 1.0;
                adfQuadValue[iQuad] = 0.0;
            }
            
            // Step left and right by one pixel searching for the closest 
            // target value for each quadrant. 
            for( iStep = 0; iStep < nThisMaxSearchDist; iStep++ )
            {
                int iLeftX = MAX(0,iX - iStep);
                int iRightX = MIN(nXSize-1,iX + iStep);
                
                // top left includes current line 
                QUAD_CHECK(adfQuadDist[0],adfQuadValue[0], 
                           iLeftX, panTopDownY[iLeftX], iX, iY,
                           pafTopDownValue[iLeftX] );

                // bottom left 
                QUAD_CHECK(adfQuadDist[1],adfQuadValue[1], 
                           iLeftX, panLastY[iLeftX], iX, iY, 
                           pafLastValue[iLeftX] );

                // top right and bottom right do no include center pixel.
                if( iStep == 0 )
                     continue;
                    
                // top right includes current line 
                QUAD_CHECK(adfQuadDist[2],adfQuadValue[2], 
                           iRightX, panTopDownY[iRightX], iX, iY,
                           pafTopDownValue[iRightX] );

                // bottom right
                QUAD_CHECK(adfQuadDist[3],adfQuadValue[3], 
                           iRightX, panLastY[iRightX], iX, iY,
                           pafLastValue[iRightX] );

                // every four steps, recompute maximum distance.
                if( (iStep & 0x3) == 0 )
                    nThisMaxSearchDist = (int) floor(
                        MAX(MAX(adfQuadDist[0],adfQuadDist[1]),
                            MAX(adfQuadDist[2],adfQuadDist[3])) );
            }

            double dfWeightSum = 0.0;
            double dfValueSum = 0.0;
            
            for( iQuad = 0; iQuad < 4; iQuad++ )
            {
                if( adfQuadDist[iQuad] <= dfMaxSearchDist )
                {
                    double dfWeight = 1.0 / adfQuadDist[iQuad];

                    dfWeightSum += dfWeight;
                    dfValueSum += adfQuadValue[iQuad] * dfWeight;
                }
            }

            if( dfWeightSum > 0.0 )
            {
                pabyMask[iX] = 255;
                pabyFiltMask[iX] = 255;
                pafScanline[iX] = (float) (dfValueSum / dfWeightSum);
            }

        }

/* -------------------------------------------------------------------- */
/*      Write out the updated data and mask information.                */
/* -------------------------------------------------------------------- */
        eErr = 
            GDALRasterIO( hTargetBand, GF_Write, 0, iY, nXSize, 1, 
                          pafScanline, nXSize, 1, GDT_Float32, 0, 0 );
        
        if( eErr != CE_None )
            break;

        eErr = 
            GDALRasterIO( hFiltMaskBand, GF_Write, 0, iY, nXSize, 1, 
                          pabyFiltMask, nXSize, 1, GDT_Byte, 0, 0 );
        
        if( eErr != CE_None )
            break;

/* -------------------------------------------------------------------- */
/*      Flip this/last buffers.                                         */
/* -------------------------------------------------------------------- */
        {
            float *pafTmp = pafThisValue;
            pafThisValue = pafLastValue;
            pafLastValue = pafTmp;
            
            GUInt32 *panTmp = panThisY;
            panThisY = panLastY;
            panLastY = panTmp;
        }

/* -------------------------------------------------------------------- */
/*      report progress.                                                */
/* -------------------------------------------------------------------- */
        if( eErr == CE_None
            && !pfnProgress( dfProgressRatio*(0.5+0.5*(nYSize-iY) / (double)nYSize), 
                             "Filling...", pProgressArg ) )
        {
            CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
            eErr = CE_Failure;
        }
    }        

/* ==================================================================== */
/*      Now we will do iterative average filters over the               */
/*      interpolated values to smooth things out and make linear        */
/*      artifacts less obvious.                                         */
/* ==================================================================== */
    if( eErr == CE_None && nSmoothingIterations > 0 )
    {
        // force masks to be to flushed and recomputed.
        GDALFlushRasterCache( hMaskBand );

        void *pScaledProgress;
        pScaledProgress =
            GDALCreateScaledProgress( dfProgressRatio, 1.0, pfnProgress, NULL );

        eErr = GDALMultiFilter( hTargetBand, hMaskBand, hFiltMaskBand, 
                                nSmoothingIterations,
                                GDALScaledProgress, pScaledProgress );

        GDALDestroyScaledProgress( pScaledProgress );
    }

/* -------------------------------------------------------------------- */
/*      Close and clean up temporary files. Free working buffers        */
/* -------------------------------------------------------------------- */
end:
    CPLFree(panLastY);
    CPLFree(panThisY);
    CPLFree(panTopDownY);
    CPLFree(pafLastValue);
    CPLFree(pafThisValue);
    CPLFree(pafTopDownValue);
    CPLFree(pafScanline);
    CPLFree(pabyMask);
    CPLFree(pabyFiltMask);

    GDALClose( hYDS );
    GDALClose( hValDS );
    GDALClose( hFiltMaskDS );

    GDALDeleteDataset( hDriver, osYTmpFile );
    GDALDeleteDataset( hDriver, osValTmpFile );
    GDALDeleteDataset( hDriver, osFiltMaskTmpFile );

    return eErr;
}
Esempio n. 21
0
static int GeoLocGenerateBackMap( GDALGeoLocTransformInfo *psTransform )

{
    int nXSize = psTransform->nGeoLocXSize;
    int nYSize = psTransform->nGeoLocYSize;
    int nMaxIter = 3;

/* -------------------------------------------------------------------- */
/*      Scan forward map for lat/long extents.                          */
/* -------------------------------------------------------------------- */
    double dfMinX=0, dfMaxX=0, dfMinY=0, dfMaxY=0;
    int i, bInit = FALSE;

    for( i = nXSize * nYSize - 1; i >= 0; i-- )
    {
        if( !psTransform->bHasNoData ||
            psTransform->padfGeoLocX[i] != psTransform->dfNoDataX )
        {
            if( bInit )
            {
                dfMinX = MIN(dfMinX,psTransform->padfGeoLocX[i]);
                dfMaxX = MAX(dfMaxX,psTransform->padfGeoLocX[i]);
                dfMinY = MIN(dfMinY,psTransform->padfGeoLocY[i]);
                dfMaxY = MAX(dfMaxY,psTransform->padfGeoLocY[i]);
            }
            else
            {
                bInit = TRUE;
                dfMinX = dfMaxX = psTransform->padfGeoLocX[i];
                dfMinY = dfMaxY = psTransform->padfGeoLocY[i];
            }
        }
    }

/* -------------------------------------------------------------------- */
/*      Decide on resolution for backmap.  We aim for slightly          */
/*      higher resolution than the source but we can't easily           */
/*      establish how much dead space there is in the backmap, so it    */
/*      is approximate.                                                 */
/* -------------------------------------------------------------------- */
    double dfTargetPixels = (nXSize * nYSize * 1.3);
    double dfPixelSize = sqrt((dfMaxX - dfMinX) * (dfMaxY - dfMinY) 
                              / dfTargetPixels);
    int nBMXSize, nBMYSize;

    nBMYSize = psTransform->nBackMapHeight = 
        (int) ((dfMaxY - dfMinY) / dfPixelSize + 1);
    nBMXSize= psTransform->nBackMapWidth =  
        (int) ((dfMaxX - dfMinX) / dfPixelSize + 1);

    if (nBMXSize > INT_MAX / nBMYSize)
    {
        CPLError(CE_Failure, CPLE_AppDefined, "Int overflow : %d x %d",
                 nBMXSize, nBMYSize);
        return FALSE;
    }

    dfMinX -= dfPixelSize/2.0;
    dfMaxY += dfPixelSize/2.0;

    psTransform->adfBackMapGeoTransform[0] = dfMinX;
    psTransform->adfBackMapGeoTransform[1] = dfPixelSize;
    psTransform->adfBackMapGeoTransform[2] = 0.0;
    psTransform->adfBackMapGeoTransform[3] = dfMaxY;
    psTransform->adfBackMapGeoTransform[4] = 0.0;
    psTransform->adfBackMapGeoTransform[5] = -dfPixelSize;

/* -------------------------------------------------------------------- */
/*      Allocate backmap, and initialize to nodata value (-1.0).        */
/* -------------------------------------------------------------------- */
    GByte  *pabyValidFlag;

    pabyValidFlag = (GByte *) 
        VSICalloc(nBMXSize, nBMYSize); 

    psTransform->pafBackMapX = (float *) 
        VSIMalloc3(nBMXSize, nBMYSize, sizeof(float)); 
    psTransform->pafBackMapY = (float *) 
        VSIMalloc3(nBMXSize, nBMYSize, sizeof(float)); 

    if( pabyValidFlag == NULL ||
        psTransform->pafBackMapX == NULL ||
        psTransform->pafBackMapY == NULL )
    {
        CPLError( CE_Failure, CPLE_OutOfMemory, 
                  "Unable to allocate %dx%d back-map for geolocation array transformer.",
                  nBMXSize, nBMYSize );
        CPLFree( pabyValidFlag );
        return FALSE;
    }

    for( i = nBMXSize * nBMYSize - 1; i >= 0; i-- )
    {
        psTransform->pafBackMapX[i] = -1.0;
        psTransform->pafBackMapY[i] = -1.0;
    }

/* -------------------------------------------------------------------- */
/*      Run through the whole geoloc array forward projecting and       */
/*      pushing into the backmap.                                       */
/*      Initialise to the nMaxIter+1 value so we can spot genuinely     */
/*      valid pixels in the hole-filling loop.                          */
/* -------------------------------------------------------------------- */
    int iBMX, iBMY;
    int iX, iY;

    for( iY = 0; iY < nYSize; iY++ )
    {
        for( iX = 0; iX < nXSize; iX++ )
        {
            if( psTransform->bHasNoData &&
                psTransform->padfGeoLocX[iX + iY * nXSize] 
                == psTransform->dfNoDataX )
                continue;

            i = iX + iY * nXSize;

            iBMX = (int) ((psTransform->padfGeoLocX[i] - dfMinX) / dfPixelSize);
            iBMY = (int) ((dfMaxY - psTransform->padfGeoLocY[i]) / dfPixelSize);

            if( iBMX < 0 || iBMY < 0 || iBMX >= nBMXSize || iBMY >= nBMYSize )
                continue;

            psTransform->pafBackMapX[iBMX + iBMY * nBMXSize] = 
                (float)(iX * psTransform->dfPIXEL_STEP + psTransform->dfPIXEL_OFFSET);
            psTransform->pafBackMapY[iBMX + iBMY * nBMXSize] = 
                (float)(iY * psTransform->dfLINE_STEP + psTransform->dfLINE_OFFSET);

            pabyValidFlag[iBMX + iBMY * nBMXSize] = (GByte) (nMaxIter+1);

        }
    }

/* -------------------------------------------------------------------- */
/*      Now, loop over the backmap trying to fill in holes with         */
/*      nearby values.                                                  */
/* -------------------------------------------------------------------- */
    int iIter;
    int nNumValid;

    for( iIter = 0; iIter < nMaxIter; iIter++ )
    {
        nNumValid = 0;
        for( iBMY = 0; iBMY < nBMYSize; iBMY++ )
        {
            for( iBMX = 0; iBMX < nBMXSize; iBMX++ )
            {
                // if this point is already set, ignore it. 
                if( pabyValidFlag[iBMX + iBMY*nBMXSize] )
                {
                    nNumValid++;
                    continue;
                }

                int nCount = 0;
                double dfXSum = 0.0, dfYSum = 0.0;
                int nMarkedAsGood = nMaxIter - iIter;

                // left?
                if( iBMX > 0 &&
                    pabyValidFlag[iBMX-1+iBMY*nBMXSize] > nMarkedAsGood )
                {
                    dfXSum += psTransform->pafBackMapX[iBMX-1+iBMY*nBMXSize];
                    dfYSum += psTransform->pafBackMapY[iBMX-1+iBMY*nBMXSize];
                    nCount++;
                }
                // right?
                if( iBMX + 1 < nBMXSize &&
                    pabyValidFlag[iBMX+1+iBMY*nBMXSize] > nMarkedAsGood )
                {
                    dfXSum += psTransform->pafBackMapX[iBMX+1+iBMY*nBMXSize];
                    dfYSum += psTransform->pafBackMapY[iBMX+1+iBMY*nBMXSize];
                    nCount++;
                }
                // top?
                if( iBMY > 0 &&
                    pabyValidFlag[iBMX+(iBMY-1)*nBMXSize] > nMarkedAsGood )
                {
                    dfXSum += psTransform->pafBackMapX[iBMX+(iBMY-1)*nBMXSize];
                    dfYSum += psTransform->pafBackMapY[iBMX+(iBMY-1)*nBMXSize];
                    nCount++;
                }
                // bottom?
                if( iBMY + 1 < nBMYSize &&
                    pabyValidFlag[iBMX+(iBMY+1)*nBMXSize] > nMarkedAsGood )
                {
                    dfXSum += psTransform->pafBackMapX[iBMX+(iBMY+1)*nBMXSize];
                    dfYSum += psTransform->pafBackMapY[iBMX+(iBMY+1)*nBMXSize];
                    nCount++;
                }
                // top-left?
                if( iBMX > 0 && iBMY > 0 &&
                    pabyValidFlag[iBMX-1+(iBMY-1)*nBMXSize] > nMarkedAsGood )
                {
                    dfXSum += psTransform->pafBackMapX[iBMX-1+(iBMY-1)*nBMXSize];
                    dfYSum += psTransform->pafBackMapY[iBMX-1+(iBMY-1)*nBMXSize];
                    nCount++;
                }
                // top-right?
                if( iBMX + 1 < nBMXSize && iBMY > 0 &&
                    pabyValidFlag[iBMX+1+(iBMY-1)*nBMXSize] > nMarkedAsGood )
                {
                    dfXSum += psTransform->pafBackMapX[iBMX+1+(iBMY-1)*nBMXSize];
                    dfYSum += psTransform->pafBackMapY[iBMX+1+(iBMY-1)*nBMXSize];
                    nCount++;
                }
                // bottom-left?
                if( iBMX > 0 && iBMY + 1 < nBMYSize &&
                    pabyValidFlag[iBMX-1+(iBMY+1)*nBMXSize] > nMarkedAsGood )
                {
                    dfXSum += psTransform->pafBackMapX[iBMX-1+(iBMY+1)*nBMXSize];
                    dfYSum += psTransform->pafBackMapY[iBMX-1+(iBMY+1)*nBMXSize];
                    nCount++;
                }
                // bottom-right?
                if( iBMX + 1 < nBMXSize && iBMY + 1 < nBMYSize &&
                    pabyValidFlag[iBMX+1+(iBMY+1)*nBMXSize] > nMarkedAsGood )
                {
                    dfXSum += psTransform->pafBackMapX[iBMX+1+(iBMY+1)*nBMXSize];
                    dfYSum += psTransform->pafBackMapY[iBMX+1+(iBMY+1)*nBMXSize];
                    nCount++;
                }

                if( nCount > 0 )
                {
                    psTransform->pafBackMapX[iBMX + iBMY * nBMXSize] = (float)(dfXSum/nCount);
                    psTransform->pafBackMapY[iBMX + iBMY * nBMXSize] = (float)(dfYSum/nCount);
                    // genuinely valid points will have value iMaxIter+1
                    // On each iteration mark newly valid points with a
                    // descending value so that it will not be used on the
                    // current iteration only on subsequent ones.
                    pabyValidFlag[iBMX+iBMY*nBMXSize] = (GByte) (nMaxIter - iIter);
                }
            }
        }
        if (nNumValid == nBMXSize * nBMYSize)
            break;
    }

#ifdef notdef
    GDALDatasetH hBMDS = GDALCreate( GDALGetDriverByName( "GTiff" ),
                                     "backmap.tif", nBMXSize, nBMYSize, 2, 
                                     GDT_Float32, NULL );
    GDALSetGeoTransform( hBMDS, psTransform->adfBackMapGeoTransform );
    GDALRasterIO( GDALGetRasterBand(hBMDS,1), GF_Write, 
                  0, 0, nBMXSize, nBMYSize, 
                  psTransform->pafBackMapX, nBMXSize, nBMYSize, 
                  GDT_Float32, 0, 0 );
    GDALRasterIO( GDALGetRasterBand(hBMDS,2), GF_Write, 
                  0, 0, nBMXSize, nBMYSize, 
                  psTransform->pafBackMapY, nBMXSize, nBMYSize, 
                  GDT_Float32, 0, 0 );
    GDALClose( hBMDS );
#endif

    CPLFree( pabyValidFlag );

    return TRUE;
}
Esempio n. 22
0
GDALDataset* SGIDataset::Open(GDALOpenInfo* poOpenInfo)

{
/* -------------------------------------------------------------------- */
/*	First we check to see if the file has the expected header	*/
/*	bytes.								*/    
/* -------------------------------------------------------------------- */
    if(poOpenInfo->nHeaderBytes < 12)
        return NULL;

    ImageRec tmpImage;
    memcpy(&tmpImage, poOpenInfo->pabyHeader, 12);
    tmpImage.Swap();

    if(tmpImage.imagic != 474)
        return NULL;

    if (tmpImage.type != 0 && tmpImage.type != 1)
        return NULL;

    if (tmpImage.bpc != 1 && tmpImage.bpc != 2)
        return NULL;

    if (tmpImage.dim != 1 && tmpImage.dim != 2 && tmpImage.dim != 3)
        return NULL;

    if(tmpImage.bpc != 1)
    {
        CPLError(CE_Failure, CPLE_NotSupported, 
                 "The SGI driver only supports 1 byte channel values.\n");
        return NULL;
    }
  
/* -------------------------------------------------------------------- */
/*      Create a corresponding GDALDataset.                             */
/* -------------------------------------------------------------------- */
    SGIDataset* poDS;

    poDS = new SGIDataset();
    poDS->eAccess = poOpenInfo->eAccess;

/* -------------------------------------------------------------------- */
/*      Open the file using the large file api.                         */
/* -------------------------------------------------------------------- */
    if( poDS->eAccess == GA_ReadOnly )
        poDS->fpImage = VSIFOpenL(poOpenInfo->pszFilename, "rb");
    else
        poDS->fpImage = VSIFOpenL(poOpenInfo->pszFilename, "rb+");
    if(poDS->fpImage == NULL)
    {
        CPLError(CE_Failure, CPLE_OpenFailed, 
                 "VSIFOpenL(%s) failed unexpectedly in sgidataset.cpp\n%s", 
                 poOpenInfo->pszFilename,
                 VSIStrerror( errno ) );
        delete poDS;
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*	Read pre-image data after ensuring the file is rewound.         */
/* -------------------------------------------------------------------- */
    VSIFSeekL(poDS->fpImage, 0, SEEK_SET);
    if(VSIFReadL((void*)(&(poDS->image)), 1, 12, poDS->fpImage) != 12)
    {
        CPLError(CE_Failure, CPLE_OpenFailed, "file read error while reading header in sgidataset.cpp");
        delete poDS;
        return NULL;
    }
    poDS->image.Swap();
    poDS->image.file = poDS->fpImage;
    poDS->image.fileName = poOpenInfo->pszFilename;

/* -------------------------------------------------------------------- */
/*      Capture some information from the file that is of interest.     */
/* -------------------------------------------------------------------- */
    poDS->nRasterXSize = poDS->image.xsize;
    poDS->nRasterYSize = poDS->image.ysize;
    if (poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0)
    {
        CPLError(CE_Failure, CPLE_OpenFailed, 
                     "Invalid image dimensions : %d x %d", poDS->nRasterXSize, poDS->nRasterYSize);
        delete poDS;
        return NULL;
    }
    poDS->nBands = MAX(1,poDS->image.zsize);
    if (poDS->nBands > 256)
    {
        CPLError(CE_Failure, CPLE_OpenFailed, 
                     "Too many bands : %d", poDS->nBands);
        delete poDS;
        return NULL;
    }

    int numItems = (int(poDS->image.bpc) == 1) ? 256 : 65536;
    poDS->image.tmp = (unsigned char*)VSICalloc(poDS->image.xsize,numItems);
    if (poDS->image.tmp == NULL)
    {
        CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
        delete poDS;
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Read RLE Pointer tables.                                        */
/* -------------------------------------------------------------------- */
    if(int(poDS->image.type) == 1) // RLE compressed
    {
        int x = poDS->image.ysize * poDS->nBands * sizeof(GUInt32);
        poDS->image.rowStart = (GUInt32*)VSIMalloc2(poDS->image.ysize, poDS->nBands * sizeof(GUInt32));
        poDS->image.rowSize = (GInt32*)VSIMalloc2(poDS->image.ysize, poDS->nBands * sizeof(GUInt32));
        if (poDS->image.rowStart == NULL || poDS->image.rowSize == NULL)
        {
            CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory");
            delete poDS;
            return NULL;
        }
        memset(poDS->image.rowStart, 0, x);
        memset(poDS->image.rowSize, 0, x);
        poDS->image.rleEnd = 512 + (2 * x);
        VSIFSeekL(poDS->fpImage, 512, SEEK_SET);
        if((int) VSIFReadL(poDS->image.rowStart, 1, x, poDS->image.file) != x)
        {
            delete poDS;
            CPLError(CE_Failure, CPLE_OpenFailed, 
                     "file read error while reading start positions in sgidataset.cpp");
            return NULL;
        }
        if((int) VSIFReadL(poDS->image.rowSize, 1, x, poDS->image.file) != x)
        {
            delete poDS;
            CPLError(CE_Failure, CPLE_OpenFailed, 
                     "file read error while reading row lengths in sgidataset.cpp");
            return NULL;
        }
        ConvertLong(poDS->image.rowStart, x/(int)sizeof(GUInt32));
        ConvertLong((GUInt32*)poDS->image.rowSize, x/(int)sizeof(GInt32));
    }
    else // uncompressed.
    {
        poDS->image.rowStart = NULL;
        poDS->image.rowSize = NULL;
    }

/* -------------------------------------------------------------------- */
/*      Create band information objects.                                */
/* -------------------------------------------------------------------- */
    for(int iBand = 0; iBand < poDS->nBands; iBand++)
        poDS->SetBand(iBand+1, new SGIRasterBand(poDS, iBand+1));

/* -------------------------------------------------------------------- */
/*      Check for world file.                                           */
/* -------------------------------------------------------------------- */
    poDS->bGeoTransformValid = 
        GDALReadWorldFile(poOpenInfo->pszFilename, ".wld", 
                          poDS->adfGeoTransform);

/* -------------------------------------------------------------------- */
/*      Initialize any PAM information.                                 */
/* -------------------------------------------------------------------- */
    poDS->SetDescription(poOpenInfo->pszFilename);
    poDS->TryLoadXML();

/* -------------------------------------------------------------------- */
/*      Check for overviews.                                            */
/* -------------------------------------------------------------------- */
    poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename );

    return poDS;
}
Esempio n. 23
0
int CPL_STDCALL 
GDALDitherRGB2PCT( GDALRasterBandH hRed, 
                   GDALRasterBandH hGreen, 
                   GDALRasterBandH hBlue, 
                   GDALRasterBandH hTarget, 
                   GDALColorTableH hColorTable,
                   GDALProgressFunc pfnProgress, 
                   void * pProgressArg )

{
    VALIDATE_POINTER1( hRed, "GDALDitherRGB2PCT", CE_Failure );
    VALIDATE_POINTER1( hGreen, "GDALDitherRGB2PCT", CE_Failure );
    VALIDATE_POINTER1( hBlue, "GDALDitherRGB2PCT", CE_Failure );
    VALIDATE_POINTER1( hTarget, "GDALDitherRGB2PCT", CE_Failure );
    VALIDATE_POINTER1( hColorTable, "GDALDitherRGB2PCT", CE_Failure );

    int		nXSize, nYSize;
    CPLErr err = CE_None;
    
/* -------------------------------------------------------------------- */
/*      Validate parameters.                                            */
/* -------------------------------------------------------------------- */
    nXSize = GDALGetRasterBandXSize( hRed );
    nYSize = GDALGetRasterBandYSize( hRed );

    if( GDALGetRasterBandXSize( hGreen ) != nXSize 
        || GDALGetRasterBandYSize( hGreen ) != nYSize 
        || GDALGetRasterBandXSize( hBlue ) != nXSize 
        || GDALGetRasterBandYSize( hBlue ) != nYSize )
    {
        CPLError( CE_Failure, CPLE_IllegalArg,
                  "Green or blue band doesn't match size of red band.\n" );

        return CE_Failure;
    }

    if( GDALGetRasterBandXSize( hTarget ) != nXSize 
        || GDALGetRasterBandYSize( hTarget ) != nYSize )
    {
        CPLError( CE_Failure, CPLE_IllegalArg,
                  "GDALDitherRGB2PCT(): "
                  "Target band doesn't match size of source bands.\n" );

        return CE_Failure;
    }

    if( pfnProgress == NULL )
        pfnProgress = GDALDummyProgress;

/* -------------------------------------------------------------------- */
/*      Setup more direct colormap.                                     */
/* -------------------------------------------------------------------- */
    int		nColors, anPCT[768], iColor;

    nColors = GDALGetColorEntryCount( hColorTable );
    
    if (nColors == 0 )
    {
        CPLError( CE_Failure, CPLE_IllegalArg,
                  "GDALDitherRGB2PCT(): "
                  "Color table must not be empty.\n" );

        return CE_Failure;
    }
    else if (nColors > 256)
    {
        CPLError( CE_Failure, CPLE_IllegalArg,
                  "GDALDitherRGB2PCT(): "
                  "Color table cannot have more than 256 entries.\n" );

        return CE_Failure;
    }
    
    for( iColor = 0; iColor < nColors; iColor++ )
    {
        GDALColorEntry	sEntry;

        GDALGetColorEntryAsRGB( hColorTable, iColor, &sEntry );
        
        anPCT[iColor    ] = sEntry.c1;
        anPCT[iColor+256] = sEntry.c2;
        anPCT[iColor+512] = sEntry.c3;
    }
    
/* -------------------------------------------------------------------- */
/*      Build a 24bit to 8 bit color mapping.                           */
/* -------------------------------------------------------------------- */
    GByte	*pabyColorMap;

    pabyColorMap = (GByte *) CPLMalloc(C_LEVELS * C_LEVELS * C_LEVELS 
                                       * sizeof(int));
    
    FindNearestColor( nColors, anPCT, pabyColorMap );

/* -------------------------------------------------------------------- */
/*      Setup various variables.                                        */
/* -------------------------------------------------------------------- */
    GByte	*pabyRed, *pabyGreen, *pabyBlue, *pabyIndex;
    int		*panError;

    pabyRed = (GByte *) VSIMalloc(nXSize);
    pabyGreen = (GByte *) VSIMalloc(nXSize);
    pabyBlue = (GByte *) VSIMalloc(nXSize);

    pabyIndex = (GByte *) VSIMalloc(nXSize);

    panError = (int *) VSICalloc(sizeof(int),(nXSize+2) * 3);
    
    if (pabyRed == NULL ||
        pabyGreen == NULL ||
        pabyBlue == NULL ||
        pabyIndex == NULL ||
        panError == NULL)
    {
        CPLError( CE_Failure, CPLE_OutOfMemory,
                  "VSIMalloc(): Out of memory in GDALDitherRGB2PCT" );
        err = CE_Failure;
        goto end_and_cleanup;
    }

/* ==================================================================== */
/*      Loop over all scanlines of data to process.                     */
/* ==================================================================== */
    int		iScanline;

    for( iScanline = 0; iScanline < nYSize; iScanline++ )
    {
        int	nLastRedError, nLastGreenError, nLastBlueError, i;

/* -------------------------------------------------------------------- */
/*      Report progress                                                 */
/* -------------------------------------------------------------------- */
        if( !pfnProgress( iScanline / (double) nYSize, NULL, pProgressArg ) )
        {
            CPLError( CE_Failure, CPLE_UserInterrupt, "User Terminated" );
            err = CE_Failure;
            goto end_and_cleanup;
        }

/* -------------------------------------------------------------------- */
/*      Read source data.                                               */
/* -------------------------------------------------------------------- */
        GDALRasterIO( hRed, GF_Read, 0, iScanline, nXSize, 1, 
                      pabyRed, nXSize, 1, GDT_Byte, 0, 0 );
        GDALRasterIO( hGreen, GF_Read, 0, iScanline, nXSize, 1, 
                      pabyGreen, nXSize, 1, GDT_Byte, 0, 0 );
        GDALRasterIO( hBlue, GF_Read, 0, iScanline, nXSize, 1, 
                      pabyBlue, nXSize, 1, GDT_Byte, 0, 0 );

/* -------------------------------------------------------------------- */
/*	Apply the error from the previous line to this one.		*/
/* -------------------------------------------------------------------- */
        for( i = 0; i < nXSize; i++ )
        {
            pabyRed[i] = (GByte)
                MAX(0,MIN(255,(pabyRed[i]   + panError[i*3+0+3])));
            pabyGreen[i] = (GByte)
                MAX(0,MIN(255,(pabyGreen[i] + panError[i*3+1+3])));
            pabyBlue[i] =  (GByte)
                MAX(0,MIN(255,(pabyBlue[i]  + panError[i*3+2+3])));
        }

        memset( panError, 0, sizeof(int) * (nXSize+2) * 3 );

/* -------------------------------------------------------------------- */
/*	Figure out the nearest color to the RGB value.			*/
/* -------------------------------------------------------------------- */
        nLastRedError = 0;
        nLastGreenError = 0;
        nLastBlueError = 0;

        for( i = 0; i < nXSize; i++ )
        {
            int		iIndex, nError, nSixth, iRed, iGreen, iBlue;
            int		nRedValue, nGreenValue, nBlueValue;

            nRedValue =   MAX(0,MIN(255, pabyRed[i]   + nLastRedError));
            nGreenValue = MAX(0,MIN(255, pabyGreen[i] + nLastGreenError));
            nBlueValue =  MAX(0,MIN(255, pabyBlue[i]  + nLastBlueError));

            iRed   = nRedValue *   C_LEVELS   / 256;
            iGreen = nGreenValue * C_LEVELS / 256;
            iBlue  = nBlueValue *  C_LEVELS  / 256;
            
            iIndex = pabyColorMap[iRed + iGreen * C_LEVELS 
                                 + iBlue * C_LEVELS * C_LEVELS];
	
            pabyIndex[i] = (GByte) iIndex;

/* -------------------------------------------------------------------- */
/*      Compute Red error, and carry it on to the next error line.      */
/* -------------------------------------------------------------------- */
            nError = nRedValue - anPCT[iIndex    ];
            nSixth = nError / 6;
            
            panError[i*3    ] += nSixth;
            panError[i*3+6  ] = nSixth;
            panError[i*3+3  ] += nError - 5 * nSixth;
            
            nLastRedError = 2 * nSixth;

/* -------------------------------------------------------------------- */
/*      Compute Green error, and carry it on to the next error line.    */
/* -------------------------------------------------------------------- */
            nError = nGreenValue - anPCT[iIndex+256];
            nSixth = nError / 6;

            panError[i*3  +1] += nSixth;
            panError[i*3+6+1] = nSixth;
            panError[i*3+3+1] += nError - 5 * nSixth;
            
            nLastGreenError = 2 * nSixth;

/* -------------------------------------------------------------------- */
/*      Compute Blue error, and carry it on to the next error line.     */
/* -------------------------------------------------------------------- */
            nError = nBlueValue - anPCT[iIndex+512];
            nSixth = nError / 6;
            
            panError[i*3  +2] += nSixth;
            panError[i*3+6+2] = nSixth;
            panError[i*3+3+2] += nError - 5 * nSixth;
            
            nLastBlueError = 2 * nSixth;
        }

/* -------------------------------------------------------------------- */
/*      Write results.                                                  */
/* -------------------------------------------------------------------- */
        GDALRasterIO( hTarget, GF_Write, 0, iScanline, nXSize, 1, 
                      pabyIndex, nXSize, 1, GDT_Byte, 0, 0 );
    }

    pfnProgress( 1.0, NULL, pProgressArg );

/* -------------------------------------------------------------------- */
/*      Cleanup                                                         */
/* -------------------------------------------------------------------- */
end_and_cleanup:
    CPLFree( pabyRed );
    CPLFree( pabyGreen );
    CPLFree( pabyBlue );
    CPLFree( pabyIndex );
    CPLFree( panError );
    CPLFree( pabyColorMap );

    return err;
}
Esempio n. 24
0
const char *HFAField::Initialize( const char * pszInput )

{
    int		i;
    
/* -------------------------------------------------------------------- */
/*      Read the number.                                                */
/* -------------------------------------------------------------------- */
    nItemCount = atoi(pszInput);

    while( *pszInput != '\0' && *pszInput != ':' )
        pszInput++;

    if( *pszInput == '\0' )
        return NULL;
    
    pszInput++;

/* -------------------------------------------------------------------- */
/*      Is this a pointer?                                              */
/* -------------------------------------------------------------------- */
    if( *pszInput == 'p' || *pszInput == '*' )
        chPointer = *(pszInput++);

/* -------------------------------------------------------------------- */
/*      Get the general type                                            */
/* -------------------------------------------------------------------- */
    if( *pszInput == '\0' )
        return NULL;

    chItemType = *(pszInput++);

    if ( strchr( "124cCesStlLfdmMbox", chItemType) == NULL )
    {
        CPLError(CE_Failure, CPLE_AppDefined,
                 "Unrecognized item type : %c", chItemType);
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      If this is an object, we extract the type of the object.        */
/* -------------------------------------------------------------------- */
    if( chItemType == 'o' )
    {
        for( i = 0; pszInput[i] != '\0' && pszInput[i] != ','; i++ ) {}
        if (pszInput[i] == '\0')
            return NULL;

        pszItemObjectType = (char *) CPLMalloc(i+1);
        strncpy( pszItemObjectType, pszInput, i );
        pszItemObjectType[i] = '\0';

        pszInput += i+1;
    }

/* -------------------------------------------------------------------- */
/*      If this is an inline object, we need to skip past the           */
/*      definition, and then extract the object class name.             */
/*                                                                      */
/*      We ignore the actual definition, so if the object type isn't    */
/*      already defined, things will not work properly.  See the        */
/*      file lceugr250_00_pct.aux for an example of inline defs.        */
/* -------------------------------------------------------------------- */
    if( chItemType == 'x' && *pszInput == '{' )
    {
        int nBraceDepth = 1;
        pszInput++;

        // Skip past the definition.
        while( nBraceDepth > 0 && *pszInput != '\0' )
        {
            if( *pszInput == '{' )
                nBraceDepth++;
            else if( *pszInput == '}' )
                nBraceDepth--;
            
            pszInput++;
        }
        if (*pszInput == '\0')
            return NULL;

        chItemType = 'o';

        // find the comma terminating the type name.
        for( i = 0; pszInput[i] != '\0' && pszInput[i] != ','; i++ ) {}
        if (pszInput[i] == '\0')
            return NULL;

        pszItemObjectType = (char *) CPLMalloc(i+1);
        strncpy( pszItemObjectType, pszInput, i );
        pszItemObjectType[i] = '\0';

        pszInput += i+1;
    }

/* -------------------------------------------------------------------- */
/*      If this is an enumeration we have to extract all the            */
/*      enumeration values.                                             */
/* -------------------------------------------------------------------- */
    if( chItemType == 'e' )
    {
        int	nEnumCount = atoi(pszInput);
        int	iEnum;

        if (nEnumCount < 0 || nEnumCount > 100000)
            return NULL;

        pszInput = strchr(pszInput,':');
        if( pszInput == NULL )
            return NULL;

        pszInput++;

        papszEnumNames = (char **) VSICalloc(sizeof(char *), nEnumCount+1);
        if (papszEnumNames == NULL)
            return NULL;
        
        for( iEnum = 0; iEnum < nEnumCount; iEnum++ )
        {
            char	*pszToken;
            
            for( i = 0; pszInput[i] != '\0' && pszInput[i] != ','; i++ ) {}

            if( pszInput[i] != ',' )
                return NULL;

            pszToken = (char *) CPLMalloc(i+1);
            strncpy( pszToken, pszInput, i );
            pszToken[i] = '\0';

            papszEnumNames[iEnum] = pszToken;

            pszInput += i+1;
        }
    }

/* -------------------------------------------------------------------- */
/*      Extract the field name.                                         */
/* -------------------------------------------------------------------- */
    for( i = 0; pszInput[i] != '\0' && pszInput[i] != ','; i++ ) {}
    if (pszInput[i] == '\0')
        return NULL;

    pszFieldName = (char *) CPLMalloc(i+1);
    strncpy( pszFieldName, pszInput, i );
    pszFieldName[i] = '\0';

    pszInput += i+1;
    
    return( pszInput );
}
Esempio n. 25
0
int VizGeorefSpline2D::solve(void)
{
    int r, c;
    int p;
	
    //	No points at all
    if ( _nof_points < 1 )
    {
        type = VIZ_GEOREF_SPLINE_ZERO_POINTS;
        return(0);
    }
	
    // Only one point
    if ( _nof_points == 1 )
    {
        type = VIZ_GEOREF_SPLINE_ONE_POINT;
        return(1);
    }
    // Just 2 points - it is necessarily 1D case
    if ( _nof_points == 2 )
    {
        _dx = x[1] - x[0];
        _dy = y[1] - y[0];	 
        double fact = 1.0 / ( _dx * _dx + _dy * _dy );
        _dx *= fact;
        _dy *= fact;
		
        type = VIZ_GEOREF_SPLINE_TWO_POINTS;
        return(2);
    }
	
    // More than 2 points - first we have to check if it is 1D or 2D case
		
    double xmax = x[0], xmin = x[0], ymax = y[0], ymin = y[0];
    double delx, dely;
    double xx, yy;
    double sumx = 0.0f, sumy= 0.0f, sumx2 = 0.0f, sumy2 = 0.0f, sumxy = 0.0f;
    double SSxx, SSyy, SSxy;
	
    for ( p = 0; p < _nof_points; p++ )
    {
        xx = x[p];
        yy = y[p];
		
        xmax = MAX( xmax, xx );
        xmin = MIN( xmin, xx );
        ymax = MAX( ymax, yy );
        ymin = MIN( ymin, yy );
		
        sumx  += xx;
        sumx2 += xx * xx;
        sumy  += yy;
        sumy2 += yy * yy;
        sumxy += xx * yy;
    }
    delx = xmax - xmin;
    dely = ymax - ymin;
	
    SSxx = sumx2 - sumx * sumx / _nof_points;
    SSyy = sumy2 - sumy * sumy / _nof_points;
    SSxy = sumxy - sumx * sumy / _nof_points;
	
    if ( delx < 0.001 * dely || dely < 0.001 * delx || 
         fabs ( SSxy * SSxy / ( SSxx * SSyy ) ) > 0.99 )
    {
        int p1;
		
        type = VIZ_GEOREF_SPLINE_ONE_DIMENSIONAL;
		
        _dx = _nof_points * sumx2 - sumx * sumx;
        _dy = _nof_points * sumy2 - sumy * sumy;
        double fact = 1.0 / sqrt( _dx * _dx + _dy * _dy );
        _dx *= fact;
        _dy *= fact;
		
        for ( p = 0; p < _nof_points; p++ )
        {
            double dxp = x[p] - x[0];
            double dyp = y[p] - y[0];
            u[p] = _dx * dxp + _dy * dyp;
            unused[p] = 1;
        }
		
        for ( p = 0; p < _nof_points; p++ )
        {
            int min_index = -1;
            double min_u = 0;
            for ( p1 = 0; p1 < _nof_points; p1++ )
            {
                if ( unused[p1] )
                {
                    if ( min_index < 0 || u[p1] < min_u )
                    {
                        min_index = p1;
                        min_u = u[p1];
                    }
                }
            }
            index[p] = min_index;
            unused[min_index] = 0;
        }
		
        return(3);
    }
	
    type = VIZ_GEOREF_SPLINE_FULL;
    // Make the necessary memory allocations

    _nof_eqs = _nof_points + 3;
    
    if( _nof_eqs > INT_MAX / _nof_eqs )
    {
        CPLError(CE_Failure, CPLE_AppDefined, "Too many coefficients. Computation aborted.");
        return 0;
    }
	
    double* _AA = ( double * )VSICalloc( _nof_eqs * _nof_eqs, sizeof( double ) );
    double* _Ainv = ( double * )VSICalloc( _nof_eqs * _nof_eqs, sizeof( double ) );
    
    if( _AA == NULL || _Ainv == NULL )
    {
        CPLError(CE_Failure, CPLE_AppDefined, "Out-of-memory while allocating temporary arrays. Computation aborted.");
        VSIFree(_AA);
        VSIFree(_Ainv);
        return 0;
    }
	
    // Calc the values of the matrix A
    for ( r = 0; r < 3; r++ )
        for ( c = 0; c < 3; c++ )
            A(r,c) = 0.0;
		
    for ( c = 0; c < _nof_points; c++ )
    {
        A(0,c+3) = 1.0;
        A(1,c+3) = x[c];
        A(2,c+3) = y[c];
			
        A(c+3,0) = 1.0;
        A(c+3,1) = x[c];
        A(c+3,2) = y[c];
    }
		
    for ( r = 0; r < _nof_points; r++ )
        for ( c = r; c < _nof_points; c++ )
        {
            A(r+3,c+3) = VizGeorefSpline2DBase_func( x[r], y[r], x[c], y[c] );
            if ( r != c )
                A(c+3,r+3 ) = A(r+3,c+3);
        }
			
#if VIZ_GEOREF_SPLINE_DEBUG
			
    for ( r = 0; r < _nof_eqs; r++ )
    {
        for ( c = 0; c < _nof_eqs; c++ )
            fprintf(stderr, "%f", A(r,c));
        fprintf(stderr, "\n");
    }
			
#endif

    int ret  = 4;
#ifdef HAVE_ARMADILLO
    try
    {
        arma::mat matA(_AA,_nof_eqs,_nof_eqs,false);
        arma::mat matRHS(_nof_eqs, _nof_vars);
        int row, col;
        for(row = 0; row < _nof_eqs; row++)
            for(col = 0; col < _nof_vars; col++)
                matRHS.at(row, col) = rhs[col][row];
        arma::mat matCoefs(_nof_vars, _nof_eqs);
        if( !arma::solve(matCoefs, matA, matRHS) )
        {
            CPLError(CE_Failure, CPLE_AppDefined, "There is a problem to invert the interpolation matrix.");
            ret = 0;
        }
        else
        {
            for(row = 0; row < _nof_eqs; row++)
                for(col = 0; col < _nof_vars; col++)
                    coef[col][row] = matCoefs.at(row, col);
        }
    }
    catch(...)
    {
        CPLError(CE_Failure, CPLE_AppDefined, "There is a problem to invert the interpolation matrix.");
        ret = 0;
    }
#else
    // Invert the matrix
    int status = matrixInvert( _nof_eqs, _AA, _Ainv );
			
    if ( !status )
    {
        CPLError(CE_Failure, CPLE_AppDefined, "There is a problem to invert the interpolation matrix.");
        ret = 0;
    }
    else
    {
        // calc the coefs
        for ( int v = 0; v < _nof_vars; v++ )
            for ( r = 0; r < _nof_eqs; r++ )
            {
                coef[v][r] = 0.0;
                for ( c = 0; c < _nof_eqs; c++ )
                    coef[v][r] += Ainv(r,c) * rhs[v][c];
            }
    }
#endif

    VSIFree(_AA);
    VSIFree(_Ainv);

    return(ret);
}
Esempio n. 26
0
GDALDataset *SDTSDataset::Open( GDALOpenInfo * poOpenInfo )

{
    int         i;
    
/* -------------------------------------------------------------------- */
/*      Before trying SDTSOpen() we first verify that the first         */
/*      record is in fact a SDTS file descriptor record.                */
/* -------------------------------------------------------------------- */
    char        *pachLeader = (char *) poOpenInfo->pabyHeader;
    
    if( poOpenInfo->nHeaderBytes < 24 )
        return NULL;

    if( pachLeader[5] != '1' && pachLeader[5] != '2' && pachLeader[5] != '3' )
        return NULL;

    if( pachLeader[6] != 'L' )
        return NULL;

    if( pachLeader[8] != '1' && pachLeader[8] != ' ' )
        return NULL;

/* -------------------------------------------------------------------- */
/*      Try opening the dataset.                                        */
/* -------------------------------------------------------------------- */
    SDTSTransfer        *poTransfer = new SDTSTransfer;
    
    if( !poTransfer->Open( poOpenInfo->pszFilename ) )
    {
        delete poTransfer;
        return NULL;
    }
    
/* -------------------------------------------------------------------- */
/*      Confirm the requested access is supported.                      */
/* -------------------------------------------------------------------- */
    if( poOpenInfo->eAccess == GA_Update )
    {
        delete poTransfer;
        CPLError( CE_Failure, CPLE_NotSupported, 
                  "The SDTS driver does not support update access to existing"
                  " datasets.\n" );
        return NULL;
    }
    
/* -------------------------------------------------------------------- */
/*      Find the first raster layer.  If there are none, abort          */
/*      returning an error.                                             */
/* -------------------------------------------------------------------- */
    SDTSRasterReader    *poRL = NULL;

    for( i = 0; i < poTransfer->GetLayerCount(); i++ )
    {
        if( poTransfer->GetLayerType( i ) == SLTRaster )
        {
            poRL = poTransfer->GetLayerRasterReader( i );
            break;
        }
    }

    if( poRL == NULL )
    {
        delete poTransfer;
        
        CPLError( CE_Warning, CPLE_AppDefined,
                  "%s is an SDTS transfer, but has no raster cell layers.\n"
                  "Perhaps it is a vector transfer?\n",
                  poOpenInfo->pszFilename );
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Initialize a corresponding GDALDataset.                         */
/* -------------------------------------------------------------------- */
    SDTSDataset *poDS = new SDTSDataset();

    poDS->poTransfer = poTransfer;
    poDS->poRL = poRL;
    
/* -------------------------------------------------------------------- */
/*      Capture some information from the file that is of interest.     */
/* -------------------------------------------------------------------- */
    poDS->nRasterXSize = poRL->GetXSize();
    poDS->nRasterYSize = poRL->GetYSize();
    
/* -------------------------------------------------------------------- */
/*      Create band information objects.                                */
/* -------------------------------------------------------------------- */
    poDS->nBands = 1;
    poDS->papoBands = (GDALRasterBand **)
        VSICalloc(sizeof(GDALRasterBand *),poDS->nBands);

    for( i = 0; i < poDS->nBands; i++ )
        poDS->SetBand( i+1, new SDTSRasterBand( poDS, i+1, poRL ) );

/* -------------------------------------------------------------------- */
/*      Try to establish the projection string.  For now we only        */
/*      support UTM and GEO.                                            */
/* -------------------------------------------------------------------- */
    OGRSpatialReference   oSRS;
    SDTS_XREF   *poXREF = poTransfer->GetXREF();

    if( EQUAL(poXREF->pszSystemName,"UTM") )
    {									
        oSRS.SetUTM( poXREF->nZone );
    }
    else if( EQUAL(poXREF->pszSystemName,"GEO") )
    {
        /* we set datum later */
    }
    else
        oSRS.SetLocalCS( poXREF->pszSystemName );

    if( oSRS.IsLocal() )
        /* don't try to set datum. */;
    else if( EQUAL(poXREF->pszDatum,"NAS") )
        oSRS.SetWellKnownGeogCS( "NAD27" );
    else if( EQUAL(poXREF->pszDatum, "NAX") )
        oSRS.SetWellKnownGeogCS( "NAD83" );
    else if( EQUAL(poXREF->pszDatum, "WGC") )
        oSRS.SetWellKnownGeogCS( "WGS72" );
    else if( EQUAL(poXREF->pszDatum, "WGE") )
        oSRS.SetWellKnownGeogCS( "WGS84" );
    else
        oSRS.SetWellKnownGeogCS( "WGS84" );

    oSRS.Fixup();

    poDS->pszProjection = NULL;
    if( oSRS.exportToWkt( &poDS->pszProjection ) != OGRERR_NONE )
        poDS->pszProjection = CPLStrdup("");


/* -------------------------------------------------------------------- */
/*      Get metadata from the IDEN file.                                */
/* -------------------------------------------------------------------- */
    const char* pszIDENFilePath = poTransfer->GetCATD()->GetModuleFilePath("IDEN");
    if (pszIDENFilePath)
    {
        DDFModule   oIDENFile;
        if( oIDENFile.Open( pszIDENFilePath ) )
        {
            DDFRecord* poRecord;

            while( (poRecord = oIDENFile.ReadRecord()) != NULL )
            {

                if( poRecord->GetStringSubfield( "IDEN", 0, "MODN", 0 ) == NULL )
                    continue;

                static const char* fields[][2] = { { "TITL", "TITLE" },
                                                   { "DAID", "DATASET_ID" },
                                                   { "DAST", "DATA_STRUCTURE" },
                                                   { "MPDT", "MAP_DATE" },
                                                   { "DCDT", "DATASET_CREATION_DATE" } };

                for (i = 0; i < (int)sizeof(fields) / (int)sizeof(fields[0]) ; i++)
                {
                    const char* pszFieldValue =
                            poRecord->GetStringSubfield( "IDEN", 0, fields[i][0], 0 );
                    if ( pszFieldValue )
                        poDS->SetMetadataItem(fields[i][1], pszFieldValue);
                }

                break;
            }
        }
    }

/* -------------------------------------------------------------------- */
/*      Initialize any PAM information.                                 */
/* -------------------------------------------------------------------- */
    poDS->SetDescription( poOpenInfo->pszFilename );
    poDS->TryLoadXML();

    return( poDS );
}
Esempio n. 27
0
GDALDataset *MEMDataset::Create( const char * pszFilename,
                                 int nXSize, int nYSize, int nBands,
                                 GDALDataType eType,
                                 char **papszOptions )

{

/* -------------------------------------------------------------------- */
/*      Do we want a pixel interleaved buffer?  I mostly care about     */
/*      this to test pixel interleaved io in other contexts, but it     */
/*      could be useful to create a directly accessable buffer for      */
/*      some apps.                                                      */
/* -------------------------------------------------------------------- */
    int bPixelInterleaved = FALSE;
    const char *pszOption = CSLFetchNameValue( papszOptions, "INTERLEAVE" );
    if( pszOption && EQUAL(pszOption,"PIXEL") )
        bPixelInterleaved = TRUE;
        
/* -------------------------------------------------------------------- */
/*      First allocate band data, verifying that we can get enough      */
/*      memory.                                                         */
/* -------------------------------------------------------------------- */
    std::vector<GByte*> apbyBandData;
    int   	iBand;
    int         nWordSize = GDALGetDataTypeSize(eType) / 8;
    int         bAllocOK = TRUE;

    GUIntBig nGlobalBigSize = (GUIntBig)nWordSize * nBands * nXSize * nYSize;
    size_t nGlobalSize = (size_t)nGlobalBigSize;
#if SIZEOF_VOIDP == 4
    if( (GUIntBig)nGlobalSize != nGlobalBigSize )
    {
        CPLError( CE_Failure, CPLE_OutOfMemory,
                  "Cannot allocate " CPL_FRMT_GUIB " bytes on this platform.",
                  nGlobalBigSize );
        return NULL;
    }
#endif

    if( bPixelInterleaved )
    {
        apbyBandData.push_back( 
            (GByte *) VSICalloc( 1, nGlobalSize ) );

        if( apbyBandData[0] == NULL )
            bAllocOK = FALSE;
        else
        {
            for( iBand = 1; iBand < nBands; iBand++ )
                apbyBandData.push_back( apbyBandData[0] + iBand * nWordSize );
        }
    }
    else
    {
        for( iBand = 0; iBand < nBands; iBand++ )
        {
            apbyBandData.push_back( 
                (GByte *) VSICalloc( 1, ((size_t)nWordSize) * nXSize * nYSize ) );
            if( apbyBandData[iBand] == NULL )
            {
                bAllocOK = FALSE;
                break;
            }
        }
    }

    if( !bAllocOK )
    {
        for( iBand = 0; iBand < (int) apbyBandData.size(); iBand++ )
        {
            if( apbyBandData[iBand] )
                VSIFree( apbyBandData[iBand] );
        }
        CPLError( CE_Failure, CPLE_OutOfMemory,
                    "Unable to create band arrays ... out of memory." );
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Create the new GTiffDataset object.                             */
/* -------------------------------------------------------------------- */
    MEMDataset *poDS;

    poDS = new MEMDataset();

    poDS->nRasterXSize = nXSize;
    poDS->nRasterYSize = nYSize;
    poDS->eAccess = GA_Update;

    const char *pszPixelType = CSLFetchNameValue( papszOptions, "PIXELTYPE" );
    if( pszPixelType && EQUAL(pszPixelType,"SIGNEDBYTE") )
        poDS->SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" );

    if( bPixelInterleaved )
        poDS->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" );

/* -------------------------------------------------------------------- */
/*      Create band information objects.                                */
/* -------------------------------------------------------------------- */
    for( iBand = 0; iBand < nBands; iBand++ )
    {
        MEMRasterBand *poNewBand;

        if( bPixelInterleaved )
            poNewBand = new MEMRasterBand( poDS, iBand+1, apbyBandData[iBand],
                                           eType, nWordSize * nBands, 0, 
                                           iBand == 0 );
        else
            poNewBand = new MEMRasterBand( poDS, iBand+1, apbyBandData[iBand],
                                           eType, 0, 0, TRUE );

        poDS->SetBand( iBand+1, poNewBand );
    }

/* -------------------------------------------------------------------- */
/*      Try to return a regular handle on the file.                     */
/* -------------------------------------------------------------------- */
    return poDS;
}