Beispiel #1
0
int GDALJP2Box::ReadBox()

{
    GUInt32   nLBox;
    GUInt32   nTBox;

    nBoxOffset = VSIFTellL( fpVSIL );

    if( VSIFReadL( &nLBox, 4, 1, fpVSIL ) != 1
        || VSIFReadL( &nTBox, 4, 1, fpVSIL ) != 1 )
    {
        return FALSE;
    }

    memcpy( szBoxType, &nTBox, 4 );
    szBoxType[4] = '\0';

    nLBox = CPL_MSBWORD32( nLBox );

    if( nLBox != 1 )
    {
        nBoxLength = nLBox;
        nDataOffset = nBoxOffset + 8;
    }
    else
    {
        GByte abyXLBox[8];
        if( VSIFReadL( abyXLBox, 8, 1, fpVSIL ) != 1 )
            return FALSE;

        
        if( sizeof(nBoxLength) == 8 )
        {
            CPL_MSBPTR64( abyXLBox );
            memcpy( &nBoxLength, abyXLBox, 8 );
        }
        else
        {
            CPL_MSBPTR32( abyXLBox+4 );
            memcpy( &nBoxLength, abyXLBox+4, 4 );
        }

        nDataOffset = nBoxOffset + 16;
    }

    if( nBoxLength == 0 )
    {
        VSIFSeekL( fpVSIL, 0, SEEK_END );
        nBoxLength = VSIFTellL( fpVSIL ) - nBoxOffset;
    }

    if( EQUAL(szBoxType,"uuid") )
    {
        VSIFReadL( abyUUID, 16, 1, fpVSIL );
        nDataOffset += 16;
    }

    return TRUE;
}
Beispiel #2
0
CPLErr GTXDataset::SetGeoTransform( double * padfTransform )

{
    if( padfTransform[2] != 0.0 || padfTransform[4] != 0.0 )
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                  "Attempt to write skewed or rotated geotransform to gtx." );
        return CE_Failure;
    }

    memcpy( adfGeoTransform, padfTransform, sizeof(double)*6 );

    unsigned char header[32];
    double dfXOrigin, dfYOrigin, dfWidth, dfHeight;

    dfXOrigin = adfGeoTransform[0] + 0.5 * adfGeoTransform[1];
    dfYOrigin = adfGeoTransform[3] + (nRasterYSize-0.5) * adfGeoTransform[5];
    dfWidth = adfGeoTransform[1];
    dfHeight = - adfGeoTransform[5];
    

    memcpy( header + 0, &dfYOrigin, 8 );
    CPL_MSBPTR64( header + 0 );

    memcpy( header + 8, &dfXOrigin, 8 );
    CPL_MSBPTR64( header + 8 );

    memcpy( header + 16, &dfHeight, 8 );
    CPL_MSBPTR64( header + 16 );

    memcpy( header + 24, &dfWidth, 8 );
    CPL_MSBPTR64( header + 24 );

    if( VSIFSeekL( fpImage, SEEK_SET, 0 ) != 0 
        || VSIFWriteL( header, 32, 1, fpImage ) != 1 )
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                  "Attempt to write geotrasform header to gtx failed." );
        return CE_Failure;
    }

    return CE_None;
}
Beispiel #3
0
double RDataset::ReadFloat()

{
    if( bASCII )
    {
        return CPLAtof(ASCIIFGets());
    }

    double dfValue = 0.0;

    if( VSIFReadL(&dfValue, 8, 1, fp) != 1 )
        return -1;
    CPL_MSBPTR64(&dfValue);

    return dfValue;
}
Beispiel #4
0
GDALDataset *
RCreateCopy( const char * pszFilename,
             GDALDataset *poSrcDS,
             CPL_UNUSED int bStrict,
             char ** papszOptions,
             GDALProgressFunc pfnProgress,
             void * pProgressData )
{
    const int nBands = poSrcDS->GetRasterCount();
    const int nXSize = poSrcDS->GetRasterXSize();
    const int nYSize = poSrcDS->GetRasterYSize();
    const bool bASCII = CPLFetchBool(papszOptions, "ASCII", false);
    const bool bCompressed = CPLFetchBool(papszOptions, "COMPRESS", !bASCII);

    // Some some rudimentary checks.

    // Setup the filename to actually use.  We prefix with
    // /vsigzip/ if we want compressed output.
    const CPLString osAdjustedFilename =
        std::string(bCompressed ? "/vsigzip/" : "") + pszFilename;

    // Create the file.
    VSILFILE *fp = VSIFOpenL(osAdjustedFilename, "wb");
    if( fp == NULL )
    {
        CPLError(CE_Failure, CPLE_OpenFailed,
                 "Unable to create file %s.",
                 pszFilename);
        return NULL;
    }

    // Write header with version, etc.
    if( bASCII )
    {
        const char *pszHeader = "RDA2\nA\n";
        VSIFWriteL(pszHeader, 1, strlen(pszHeader), fp);
    }
    else
    {
        const char *pszHeader = "RDX2\nX\n";
        VSIFWriteL(pszHeader, 1, strlen(pszHeader), fp);
    }

    RWriteInteger(fp, bASCII, 2);
    RWriteInteger(fp, bASCII, 133377);
    RWriteInteger(fp, bASCII, 131840);

    // Establish the primary pairlist with one component object.
    RWriteInteger(fp, bASCII, 1026);
    RWriteInteger(fp, bASCII, 1);

    // Write the object name.  Eventually we should derive this
    // from the filename, possible with override by a creation option.
    RWriteString(fp, bASCII, "gg");

    // For now we write the raster as a numeric array with attributes (526).
    RWriteInteger(fp, bASCII, 526);
    RWriteInteger(fp, bASCII, nXSize * nYSize * nBands);

    // Write the raster data.
    CPLErr eErr = CE_None;

    double *padfScanline =
        static_cast<double *>(CPLMalloc(nXSize * sizeof(double)));

    for( int iBand = 0; iBand < nBands; iBand++ )
    {
        GDALRasterBand *poBand = poSrcDS->GetRasterBand(iBand + 1);

        for( int iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ )
        {
            eErr = poBand->RasterIO(GF_Read, 0, iLine, nXSize, 1,
                                    padfScanline, nXSize, 1, GDT_Float64,
                                    sizeof(double), 0, NULL);

            if( bASCII )
            {
                for( int iValue = 0; iValue < nXSize; iValue++ )
                {
                    char szValue[128] = { '\0' };
                    CPLsnprintf(szValue, sizeof(szValue), "%.16g\n",
                                padfScanline[iValue]);
                    VSIFWriteL(szValue, 1, strlen(szValue), fp);
                }
            }
            else
            {
                for( int iValue = 0; iValue < nXSize; iValue++ )
                    CPL_MSBPTR64(padfScanline + iValue);

                VSIFWriteL(padfScanline, 8, nXSize, fp);
            }

            if( eErr == CE_None &&
                !pfnProgress((iLine + 1) / static_cast<double>(nYSize),
                             NULL, pProgressData) )
            {
                eErr = CE_Failure;
                CPLError(CE_Failure, CPLE_UserInterrupt,
                         "User terminated CreateCopy()");
            }
        }
    }

    CPLFree(padfScanline);

    // Write out the dims attribute.
    RWriteInteger(fp, bASCII, 1026);
    RWriteInteger(fp, bASCII, 1);

    RWriteString(fp, bASCII, "dim");

    RWriteInteger(fp, bASCII, 13);
    RWriteInteger(fp, bASCII, 3);
    RWriteInteger(fp, bASCII, nXSize);
    RWriteInteger(fp, bASCII, nYSize);
    RWriteInteger(fp, bASCII, nBands);

    RWriteInteger(fp, bASCII, 254);

    // Terminate overall pairlist.
    RWriteInteger(fp, bASCII, 254);

    // Cleanup.
    VSIFCloseL(fp);

    if( eErr != CE_None )
        return NULL;

    // Re-open dataset, and copy any auxiliary pam information.
    GDALPamDataset *poDS =
        static_cast<GDALPamDataset *>(GDALOpen(pszFilename, GA_ReadOnly));

    if( poDS )
        poDS->CloneInfo(poSrcDS, GCIF_PAM_DEFAULT);

    return poDS;
}
Beispiel #5
0
GDALDataset *GTXDataset::Create( const char * pszFilename,
                                 int nXSize,
                                 int nYSize,
                                 int /* nBands */,
                                 GDALDataType eType,
                                 char ** /* papszOptions */ )
{
    if( eType != GDT_Float32 )
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                  "Attempt to create gtx file with unsupported data type '%s'.",
                  GDALGetDataTypeName( eType ) );
        return NULL;
    }

    if( !EQUAL(CPLGetExtension(pszFilename),"gtx") )
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                  "Attempt to create gtx file with extension other than gtx." );
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Try to create the file.                                         */
/* -------------------------------------------------------------------- */
    VSILFILE *fp = VSIFOpenL( pszFilename, "wb" );
    if( fp == NULL )
    {
        CPLError( CE_Failure, CPLE_OpenFailed,
                  "Attempt to create file `%s' failed.\n",
                  pszFilename );
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Write out the header with stub georeferencing.                  */
/* -------------------------------------------------------------------- */

    unsigned char header[40] = { '\0' };
    double dfYOrigin = 0.0;
    memcpy( header + 0, &dfYOrigin, 8 );
    CPL_MSBPTR64( header + 0 );

    double dfXOrigin = 0.0;
    memcpy( header + 8, &dfXOrigin, 8 );
    CPL_MSBPTR64( header + 8 );

    double dfYSize = 0.01;
    memcpy( header + 16, &dfYSize, 8 );
    CPL_MSBPTR64( header + 16 );

    double dfXSize = 0.01;
    memcpy( header + 24, &dfXSize, 8 );
    CPL_MSBPTR64( header + 24 );

    GInt32 nYSize32 = nYSize;
    memcpy( header + 32, &nYSize32, 4 );
    CPL_MSBPTR32( header + 32 );

    GInt32 nXSize32 = nXSize;
    memcpy( header + 36, &nXSize32, 4 );
    CPL_MSBPTR32( header + 36 );

    CPL_IGNORE_RET_VAL(VSIFWriteL( header, 40, 1, fp ));
    CPL_IGNORE_RET_VAL(VSIFCloseL( fp ));

    return reinterpret_cast<GDALDataset *>(
        GDALOpen( pszFilename, GA_Update ) );
}
Beispiel #6
0
GDALDataset *GTXDataset::Open( GDALOpenInfo * poOpenInfo )

{
    if( !Identify( poOpenInfo ) )
        return NULL;

/* -------------------------------------------------------------------- */
/*      Create a corresponding GDALDataset.                             */
/* -------------------------------------------------------------------- */
    GTXDataset *poDS = new GTXDataset();

    poDS->eAccess = poOpenInfo->eAccess;

/* -------------------------------------------------------------------- */
/*      Open the file.                                                  */
/* -------------------------------------------------------------------- */
    if( poOpenInfo->eAccess == GA_ReadOnly )
        poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
    else
        poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb+" );

    if( poDS->fpImage == NULL )
    {
        delete poDS;
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Read the header.                                                */
/* -------------------------------------------------------------------- */
    poDS->adfGeoTransform[2] = 0.0;
    poDS->adfGeoTransform[4] = 0.0;

    CPL_IGNORE_RET_VAL(VSIFReadL( poDS->adfGeoTransform+3, 8, 1,
                                  poDS->fpImage ));
    CPL_IGNORE_RET_VAL(VSIFReadL( poDS->adfGeoTransform+0, 8, 1,
                                  poDS->fpImage ));
    CPL_IGNORE_RET_VAL(VSIFReadL( poDS->adfGeoTransform+5, 8, 1,
                                  poDS->fpImage ));
    CPL_IGNORE_RET_VAL(VSIFReadL( poDS->adfGeoTransform+1, 8, 1,
                                  poDS->fpImage ));

    CPL_IGNORE_RET_VAL(VSIFReadL( &(poDS->nRasterYSize), 4, 1, poDS->fpImage ));
    CPL_IGNORE_RET_VAL(VSIFReadL( &(poDS->nRasterXSize), 4, 1, poDS->fpImage ));

    CPL_MSBPTR32( &(poDS->nRasterYSize) );
    CPL_MSBPTR32( &(poDS->nRasterXSize) );

    CPL_MSBPTR64( poDS->adfGeoTransform + 0 );
    CPL_MSBPTR64( poDS->adfGeoTransform + 1 );
    CPL_MSBPTR64( poDS->adfGeoTransform + 3 );
    CPL_MSBPTR64( poDS->adfGeoTransform + 5 );

    poDS->adfGeoTransform[3] +=
        poDS->adfGeoTransform[5] * (poDS->nRasterYSize-1);

    poDS->adfGeoTransform[0] -= poDS->adfGeoTransform[1] * 0.5;
    poDS->adfGeoTransform[3] += poDS->adfGeoTransform[5] * 0.5;

    poDS->adfGeoTransform[5] *= -1;

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

/* -------------------------------------------------------------------- */
/*      Guess the data type. Since October 1, 2009, it should be        */
/*      Float32. Before it was double.                                  */
/* -------------------------------------------------------------------- */
    CPL_IGNORE_RET_VAL(VSIFSeekL(poDS->fpImage, 0, SEEK_END));
    const vsi_l_offset nSize = VSIFTellL(poDS->fpImage);

    GDALDataType eDT = GDT_Float32;
    if( nSize == 40 + 8 * static_cast<vsi_l_offset>(poDS->nRasterXSize) *
        poDS->nRasterYSize )
        eDT = GDT_Float64;
    const int nDTSize = GDALGetDataTypeSizeBytes(eDT);

/* -------------------------------------------------------------------- */
/*      Create band information object.                                 */
/* -------------------------------------------------------------------- */
    RawRasterBand *poBand = new RawRasterBand(
        poDS, 1, poDS->fpImage,
        (poDS->nRasterYSize-1) * poDS->nRasterXSize*nDTSize + 40,
        nDTSize, poDS->nRasterXSize * -nDTSize,
        eDT,
        !CPL_IS_LSB, TRUE, FALSE );
    poBand->SetNoDataValue( -88.8888 );
    poDS->SetBand( 1, poBand );

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

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

    return poDS;
}
Beispiel #7
0
RPFToc* RPFTOCReadFromBuffer(const char* pszFilename, VSILFILE* fp, const char* tocHeader)
{
    tocHeader += 1; /* skip endian */
    tocHeader += 2; /* skip header length */
    tocHeader += 12; /* skip file name : this should be A.TOC (padded) */
    tocHeader += 1; /* skip new  */
    tocHeader += 15; /* skip standard_num  */
    tocHeader += 8; /* skip standard_date  */
    tocHeader += 1; /* skip classification  */
    tocHeader += 2; /* skip country  */
    tocHeader += 2; /* skip release  */

    unsigned int locationSectionPhysicalLocation;
    memcpy(&locationSectionPhysicalLocation, tocHeader, sizeof(unsigned int));
    CPL_MSBPTR32(&locationSectionPhysicalLocation);

    if( VSIFSeekL( fp, locationSectionPhysicalLocation, SEEK_SET ) != 0)
    {
        CPLError( CE_Failure, CPLE_NotSupported,
                  "Invalid TOC file. Unable to seek to locationSectionPhysicalLocation at offset %d.",
                   locationSectionPhysicalLocation );
        return nullptr;
    }

    int nSections;
    NITFLocation* pasLocations = NITFReadRPFLocationTable(fp, &nSections);

    unsigned int boundaryRectangleSectionSubHeaderPhysIndex = 0;
    unsigned int boundaryRectangleTablePhysIndex = 0;
    unsigned int frameFileIndexSectionSubHeaderPhysIndex = 0;
    unsigned int frameFileIndexSubsectionPhysIndex = 0;

    for( int i = 0; i < nSections; i++ )
    {
        if (pasLocations[i].nLocId == LID_BoundaryRectangleSectionSubheader)
        {
            boundaryRectangleSectionSubHeaderPhysIndex = pasLocations[i].nLocOffset;
        }
        else if (pasLocations[i].nLocId == LID_BoundaryRectangleTable)
        {
            boundaryRectangleTablePhysIndex = pasLocations[i].nLocOffset;
        }
        else if (pasLocations[i].nLocId == LID_FrameFileIndexSectionSubHeader)
        {
            frameFileIndexSectionSubHeaderPhysIndex = pasLocations[i].nLocOffset;
        }
        else if (pasLocations[i].nLocId == LID_FrameFileIndexSubsection)
        {
            frameFileIndexSubsectionPhysIndex = pasLocations[i].nLocOffset;
        }
    }

    CPLFree(pasLocations);

    if (boundaryRectangleSectionSubHeaderPhysIndex == 0)
    {
        CPLError( CE_Failure, CPLE_NotSupported,
                  "Invalid TOC file. Can't find LID_BoundaryRectangleSectionSubheader." );
        return nullptr;
    }
    if (boundaryRectangleTablePhysIndex == 0)
    {
        CPLError( CE_Failure, CPLE_NotSupported,
                  "Invalid TOC file. Can't find LID_BoundaryRectangleTable." );
        return nullptr;
    }
    if (frameFileIndexSectionSubHeaderPhysIndex == 0)
    {
        CPLError( CE_Failure, CPLE_NotSupported,
                  "Invalid TOC file. Can't find LID_FrameFileIndexSectionSubHeader." );
        return nullptr;
    }
    if (frameFileIndexSubsectionPhysIndex == 0)
    {
        CPLError( CE_Failure, CPLE_NotSupported,
                  "Invalid TOC file. Can't find LID_FrameFileIndexSubsection." );
        return nullptr;
    }

    if( VSIFSeekL( fp, boundaryRectangleSectionSubHeaderPhysIndex, SEEK_SET ) != 0)
    {
        CPLError( CE_Failure, CPLE_NotSupported,
                  "Invalid TOC file. Unable to seek to boundaryRectangleSectionSubHeaderPhysIndex at offset %d.",
                   boundaryRectangleSectionSubHeaderPhysIndex );
        return nullptr;
    }

    unsigned int boundaryRectangleTableOffset;
    bool bOK = VSIFReadL( &boundaryRectangleTableOffset, sizeof(boundaryRectangleTableOffset), 1, fp) == 1;
    CPL_MSBPTR32( &boundaryRectangleTableOffset );

    unsigned short boundaryRectangleCount;
    bOK &= VSIFReadL( &boundaryRectangleCount, sizeof(boundaryRectangleCount), 1, fp) == 1;
    CPL_MSBPTR16( &boundaryRectangleCount );

    if( !bOK || VSIFSeekL( fp, boundaryRectangleTablePhysIndex, SEEK_SET ) != 0)
    {
        CPLError( CE_Failure, CPLE_NotSupported,
                  "Invalid TOC file. Unable to seek to boundaryRectangleTablePhysIndex at offset %d.",
                   boundaryRectangleTablePhysIndex );
        return nullptr;
    }

    RPFToc* toc = reinterpret_cast<RPFToc *>( CPLMalloc( sizeof( RPFToc ) ) );
    toc->nEntries = boundaryRectangleCount;
    toc->entries = reinterpret_cast<RPFTocEntry *>(
        CPLMalloc( boundaryRectangleCount * sizeof(RPFTocEntry) ) );
    memset(toc->entries, 0, boundaryRectangleCount * sizeof(RPFTocEntry));

    for( int i = 0; i < toc->nEntries; i++ )
    {
        toc->entries[i].isOverviewOrLegend = 0;

        bOK &= VSIFReadL( toc->entries[i].type, 1, 5, fp) == 5;
        toc->entries[i].type[5] = 0;
        RPFTOCTrim(toc->entries[i].type);

        bOK &= VSIFReadL( toc->entries[i].compression, 1, 5, fp) == 5;
        toc->entries[i].compression[5] = 0;
        RPFTOCTrim(toc->entries[i].compression);

        bOK &= VSIFReadL( toc->entries[i].scale, 1, 12, fp) == 12;
        toc->entries[i].scale[12] = 0;
        RPFTOCTrim(toc->entries[i].scale);
        if (toc->entries[i].scale[0] == '1' &&
            toc->entries[i].scale[1] == ':')
        {
            memmove(toc->entries[i].scale,
                    toc->entries[i].scale+2,
                    strlen(toc->entries[i].scale+2)+1);
        }

        bOK &= VSIFReadL( toc->entries[i].zone, 1, 1, fp) == 1;
        toc->entries[i].zone[1] = 0;
        RPFTOCTrim(toc->entries[i].zone);

        bOK &= VSIFReadL( toc->entries[i].producer, 1, 5, fp) == 5;
        toc->entries[i].producer[5] = 0;
        RPFTOCTrim(toc->entries[i].producer);

        bOK &= VSIFReadL( &toc->entries[i].nwLat, sizeof(double), 1, fp) == 1;
        CPL_MSBPTR64( &toc->entries[i].nwLat);

        bOK &= VSIFReadL( &toc->entries[i].nwLong, sizeof(double), 1, fp) == 1;
        CPL_MSBPTR64( &toc->entries[i].nwLong);

        bOK &= VSIFReadL( &toc->entries[i].swLat, sizeof(double), 1, fp) == 1;
        CPL_MSBPTR64( &toc->entries[i].swLat);

        bOK &= VSIFReadL( &toc->entries[i].swLong, sizeof(double), 1, fp) == 1;
        CPL_MSBPTR64( &toc->entries[i].swLong);

        bOK &= VSIFReadL( &toc->entries[i].neLat, sizeof(double), 1, fp) == 1;
        CPL_MSBPTR64( &toc->entries[i].neLat);

        bOK &= VSIFReadL( &toc->entries[i].neLong, sizeof(double), 1, fp) == 1;
        CPL_MSBPTR64( &toc->entries[i].neLong);

        bOK &= VSIFReadL( &toc->entries[i].seLat, sizeof(double), 1, fp) == 1;
        CPL_MSBPTR64( &toc->entries[i].seLat);

        bOK &= VSIFReadL( &toc->entries[i].seLong, sizeof(double), 1, fp) == 1;
        CPL_MSBPTR64( &toc->entries[i].seLong);

        bOK &= VSIFReadL( &toc->entries[i].vertResolution, sizeof(double), 1, fp) == 1;
        CPL_MSBPTR64( &toc->entries[i].vertResolution);

        bOK &= VSIFReadL( &toc->entries[i].horizResolution, sizeof(double), 1, fp) == 1;
        CPL_MSBPTR64( &toc->entries[i].horizResolution);

        bOK &= VSIFReadL( &toc->entries[i].vertInterval, sizeof(double), 1, fp) == 1;
        CPL_MSBPTR64( &toc->entries[i].vertInterval);

        bOK &= VSIFReadL( &toc->entries[i].horizInterval, sizeof(double), 1, fp) == 1;
        CPL_MSBPTR64( &toc->entries[i].horizInterval);

        bOK &= VSIFReadL( &toc->entries[i].nVertFrames, sizeof(int), 1, fp) == 1;
        CPL_MSBPTR32( &toc->entries[i].nVertFrames );

        bOK &= VSIFReadL( &toc->entries[i].nHorizFrames, sizeof(int), 1, fp) == 1;
        CPL_MSBPTR32( &toc->entries[i].nHorizFrames );

        if( !bOK )
        {
            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
            toc->entries[i].nVertFrames = 0;
            toc->entries[i].nHorizFrames = 0;
            RPFTOCFree(toc);
            return nullptr;
        }

        if( toc->entries[i].vertInterval <= 1e-10 ||
            !CPLIsFinite(toc->entries[i].vertInterval) ||
            toc->entries[i].horizInterval <= 1e-10 ||
            !CPLIsFinite(toc->entries[i].horizInterval) ||
            !(fabs(toc->entries[i].seLong) <= 360.0) ||
            !(fabs(toc->entries[i].nwLong) <= 360.0) ||
            !(fabs(toc->entries[i].nwLat) <= 90.0) ||
            !(fabs(toc->entries[i].seLat) <= 90.0) ||
            toc->entries[i].seLong < toc->entries[i].nwLong ||
            toc->entries[i].nwLat < toc->entries[i].seLat ||
            toc->entries[i].nHorizFrames == 0 ||
            toc->entries[i].nVertFrames == 0 ||
            toc->entries[i].nHorizFrames > INT_MAX / toc->entries[i].nVertFrames )
        {
            CPLError(CE_Failure, CPLE_FileIO, "Invalid TOC entry");
            toc->entries[i].nVertFrames = 0;
            toc->entries[i].nHorizFrames = 0;
            RPFTOCFree(toc);
            return nullptr;
        }

        // TODO: We could probably use another data structure, like a list,
        // instead of an array referenced by the frame coordinate...
        if( static_cast<int>(toc->entries[i].nHorizFrames *
                                  toc->entries[i].nVertFrames) >
                 atoi(CPLGetConfigOption("RPFTOC_MAX_FRAME_COUNT", "1000000")) )
        {
            CPLError(CE_Failure, CPLE_AppDefined,
                     "nHorizFrames=%d x nVertFrames=%d > %d. Please raise "
                     "the value of the RPFTOC_MAX_FRAME_COUNT configuration "
                     "option to more than %d if this dataset is legitimate.",
                     toc->entries[i].nHorizFrames, toc->entries[i].nVertFrames,
                     atoi(CPLGetConfigOption("RPFTOC_MAX_FRAME_COUNT", "1000000")),
                     toc->entries[i].nHorizFrames * toc->entries[i].nVertFrames );
            toc->entries[i].frameEntries = nullptr;
        }
        else
        {
            toc->entries[i].frameEntries = reinterpret_cast<RPFTocFrameEntry*>(
                VSI_CALLOC_VERBOSE( toc->entries[i].nVertFrames * toc->entries[i].nHorizFrames,
                                    sizeof(RPFTocFrameEntry) ) );
        }
        if (toc->entries[i].frameEntries == nullptr)
        {
            toc->entries[i].nVertFrames = 0;
            toc->entries[i].nHorizFrames = 0;
            RPFTOCFree(toc);
            return nullptr;
        }

        CPLDebug("RPFTOC", "[%d] type=%s, compression=%s, scale=%s, zone=%s, producer=%s, nVertFrames=%d, nHorizFrames=%d",
                 i, toc->entries[i].type, toc->entries[i].compression, toc->entries[i].scale,
                 toc->entries[i].zone, toc->entries[i].producer, toc->entries[i].nVertFrames, toc->entries[i].nHorizFrames);
    }

    if( VSIFSeekL( fp, frameFileIndexSectionSubHeaderPhysIndex, SEEK_SET ) != 0)
    {
        CPLError( CE_Failure, CPLE_NotSupported,
                  "Invalid TOC file. Unable to seek to frameFileIndexSectionSubHeaderPhysIndex at offset %d.",
                   frameFileIndexSectionSubHeaderPhysIndex );
        RPFTOCFree(toc);
        return nullptr;
    }

    /* Skip 1 byte security classification */
    bOK &= VSIFSeekL( fp, 1, SEEK_CUR ) == 0;

    unsigned int frameIndexTableOffset;
    bOK &= VSIFReadL( &frameIndexTableOffset, sizeof(frameIndexTableOffset), 1, fp) == 1;
    CPL_MSBPTR32( &frameIndexTableOffset );

    unsigned int nFrameFileIndexRecords;
    bOK &= VSIFReadL( &nFrameFileIndexRecords, sizeof(nFrameFileIndexRecords), 1, fp) == 1;
    CPL_MSBPTR32( &nFrameFileIndexRecords );

    unsigned short nFrameFilePathnameRecords;
    bOK &= VSIFReadL( &nFrameFilePathnameRecords, sizeof(nFrameFilePathnameRecords), 1, fp) == 1;
    CPL_MSBPTR16( &nFrameFilePathnameRecords );

    unsigned short frameFileIndexRecordLength;
    bOK &= VSIFReadL( &frameFileIndexRecordLength, sizeof(frameFileIndexRecordLength), 1, fp) == 1;
    CPL_MSBPTR16( &frameFileIndexRecordLength );
    if( frameFileIndexRecordLength < 3 * sizeof(short) )
    {
        CPLError(CE_Failure, CPLE_FileIO, "Invalid file");
        RPFTOCFree(toc);
        return nullptr;
    }

    if( !bOK )
    {
        CPLError(CE_Failure, CPLE_FileIO, "I/O error");
        RPFTOCFree(toc);
        return nullptr;
    }

    int newBoundaryId = 0;

    for( int i = 0; i < static_cast<int>( nFrameFileIndexRecords ); i++ )
    {
        if( VSIFSeekL( fp, frameFileIndexSubsectionPhysIndex + frameFileIndexRecordLength * i, SEEK_SET ) != 0)
        {
            CPLError( CE_Failure, CPLE_NotSupported,
                    "Invalid TOC file. Unable to seek to frameFileIndexSubsectionPhysIndex(%d) at offset %d.",
                     i, frameFileIndexSubsectionPhysIndex + frameFileIndexRecordLength * i);
            RPFTOCFree(toc);
            return nullptr;
        }

        unsigned short boundaryId;
        if( VSIFReadL( &boundaryId, sizeof(boundaryId), 1, fp) != 1 )
        {
            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
            RPFTOCFree(toc);
            return nullptr;
        }
        CPL_MSBPTR16( &boundaryId );

        if (i == 0 && boundaryId == 0)
            newBoundaryId = 1;
        if (newBoundaryId == 0)
            boundaryId--;

        if (boundaryId >= toc->nEntries)
        {
            CPLError( CE_Failure, CPLE_NotSupported,
                    "Invalid TOC file. Bad boundary id (%d) for frame file index %d.",
                     boundaryId, i);
            RPFTOCFree(toc);
            return nullptr;
        }

        RPFTocEntry* entry = &toc->entries[boundaryId];
        entry->boundaryId = boundaryId;

        unsigned short frameRow;
        bOK &= VSIFReadL( &frameRow, sizeof(frameRow), 1, fp) == 1;
        CPL_MSBPTR16( &frameRow );

        unsigned short frameCol;
        bOK &= VSIFReadL( &frameCol, sizeof(frameCol), 1, fp) == 1;
        CPL_MSBPTR16( &frameCol );
        if( !bOK )
        {
            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
            RPFTOCFree(toc);
            return nullptr;
        }

        if (newBoundaryId == 0)
        {
            frameRow--;
            frameCol--;
        }
        else
        {
            /* Trick so that frames are numbered north to south */
            frameRow = (unsigned short)((entry->nVertFrames-1) - frameRow);
        }

        if (frameRow >= entry->nVertFrames)
        {
            CPLError( CE_Failure, CPLE_NotSupported,
                        "Invalid TOC file. Bad row num (%d) for frame file index %d.",
                        frameRow, i);
            RPFTOCFree(toc);
            return nullptr;
        }

        if (frameCol >= entry->nHorizFrames)
        {
            CPLError( CE_Failure, CPLE_NotSupported,
                        "Invalid TOC file. Bad col num (%d) for frame file index %d.",
                        frameCol, i);
            RPFTOCFree(toc);
            return nullptr;
        }

        RPFTocFrameEntry* frameEntry
            = &entry->frameEntries[frameRow * entry->nHorizFrames + frameCol ];
        frameEntry->frameRow = frameRow;
        frameEntry->frameCol = frameCol;

        if (frameEntry->exists)
        {
            CPLError( CE_Warning, CPLE_AppDefined,
                      "Frame entry(%d,%d) for frame file index %d was already found.",
                      frameRow, frameCol, i);
            CPLFree(frameEntry->directory);
            frameEntry->directory = nullptr;
            CPLFree(frameEntry->fullFilePath);
            frameEntry->fullFilePath = nullptr;
            frameEntry->exists = 0;
        }

        unsigned int offsetFrameFilePathName;
        bOK &= VSIFReadL( &offsetFrameFilePathName, sizeof(offsetFrameFilePathName), 1, fp) == 1;
        CPL_MSBPTR32( &offsetFrameFilePathName );

        bOK &= VSIFReadL( frameEntry->filename, 1, 12, fp) == 12;
        if( !bOK )
        {
            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
            RPFTOCFree(toc);
            return nullptr;
        }
        frameEntry->filename[12] = '\0';
        bOK &= strlen(frameEntry->filename) > 0;

        /* Check if the filename is an overview or legend */
        for( int j = 0; j < 12; j++ )
        {
            if (strcmp(&(frameEntry->filename[j]),".OVR") == 0 ||
                strcmp(&(frameEntry->filename[j]),".ovr") == 0 ||
                strcmp(&(frameEntry->filename[j]),".LGD") == 0 ||
                strcmp(&(frameEntry->filename[j]),".lgd") == 0)
            {
                entry->isOverviewOrLegend = TRUE;
                break;
            }
        }

        /* Extract series code */
        if (entry->seriesAbbreviation == nullptr)
        {
            const NITFSeries* series = NITFGetSeriesInfo(frameEntry->filename);
            if (series)
            {
                entry->seriesAbbreviation = series->abbreviation;
                entry->seriesName = series->name;
            }
        }

        /* Get file geo reference */
        bOK &= VSIFReadL( frameEntry->georef, 1, 6, fp) == 6;
        frameEntry->georef[6] = '\0';

        /* Go to start of pathname record */
        /* New path_off offset from start of frame file index section of TOC?? */
        /* Add pathoffset wrt frame file index table subsection (loc[3]) */
        if( !bOK || VSIFSeekL( fp, frameFileIndexSubsectionPhysIndex + offsetFrameFilePathName, SEEK_SET ) != 0)
        {
            CPLError( CE_Failure, CPLE_NotSupported,
                      "Invalid TOC file. Unable to seek to "
                      "frameFileIndexSubsectionPhysIndex + "
                      "offsetFrameFilePathName(%d) at offset %d.",
                     i, frameFileIndexSubsectionPhysIndex + offsetFrameFilePathName);
            RPFTOCFree(toc);
            return nullptr;
        }

        unsigned short pathLength;
        bOK &= VSIFReadL( &pathLength, sizeof(pathLength), 1, fp) == 1;
        CPL_MSBPTR16( &pathLength );

        /* if nFrameFileIndexRecords == 65535 and pathLength == 65535 for each record,
           this leads to 4 GB allocation... Protect against this case */
        if (!bOK || pathLength == 0 || pathLength > 256)
        {
            CPLError( CE_Failure, CPLE_NotSupported,
                      "Path length is invalid : %d. Probably corrupted TOC file.",
                      static_cast<int>( pathLength ) );
            RPFTOCFree(toc);
            return nullptr;
        }

        frameEntry->directory = reinterpret_cast<char *>( CPLMalloc(pathLength+1) );
        bOK &= VSIFReadL( frameEntry->directory, 1, pathLength, fp) == pathLength;
        if( !bOK )
        {
            CPLError(CE_Failure, CPLE_FileIO, "I/O error");
            RPFTOCFree(toc);
            return nullptr;
        }
        frameEntry->directory[pathLength] = 0;
        if (pathLength > 0 && frameEntry->directory[pathLength-1] == '/')
            frameEntry->directory[pathLength-1] = 0;

        if (frameEntry->directory[0] == '.' && frameEntry->directory[1] == '/')
        {
            memmove(frameEntry->directory, frameEntry->directory+2, strlen(frameEntry->directory+2)+1);

            // Some A.TOC have subdirectory names like ".//X/" ... (#5979)
            // Check if it was not intended to be "./X/" instead.
            VSIStatBufL sStatBuf;
            if( frameEntry->directory[0] == '/' &&
                VSIStatL(CPLFormFilename(CPLGetDirname(pszFilename), frameEntry->directory+1, nullptr), &sStatBuf) == 0 &&
                VSI_ISDIR(sStatBuf.st_mode) )
            {
                memmove(frameEntry->directory, frameEntry->directory+1, strlen(frameEntry->directory+1)+1);
            }
        }

        {
            char* baseDir = CPLStrdup(CPLGetDirname(pszFilename));
            VSIStatBufL sStatBuf;
            char* subdir = nullptr;
            if (CPLIsFilenameRelative(frameEntry->directory) == FALSE)
                subdir = CPLStrdup(frameEntry->directory);
            else if (frameEntry->directory[0] == '.' && frameEntry->directory[1] == 0)
                subdir = CPLStrdup(baseDir);
            else
                subdir = CPLStrdup(CPLFormFilename(baseDir, frameEntry->directory, nullptr));
#if !defined(_WIN32) && !defined(_WIN32_CE)
            if( VSIStatL( subdir, &sStatBuf ) != 0 && strlen(subdir) > strlen(baseDir) && subdir[strlen(baseDir)] != 0)
            {
                char* c = subdir + strlen(baseDir)+1;
                while(*c)
                {
                    if (*c >= 'A' && *c <= 'Z')
                        *c += 'a' - 'A';
                    c++;
                }
            }
#endif
            frameEntry->fullFilePath = CPLStrdup(CPLFormFilename(
                    subdir,
                    frameEntry->filename, nullptr));
            if( VSIStatL( frameEntry->fullFilePath, &sStatBuf ) != 0 )
            {
#if !defined(_WIN32) && !defined(_WIN32_CE)
                if( strlen(frameEntry->fullFilePath) > strlen(subdir) )
                {
                    char* c = frameEntry->fullFilePath + strlen(subdir)+1;
                    while(*c)
                    {
                        if (*c >= 'A' && *c <= 'Z')
                            *c += 'a' - 'A';
                        c++;
                    }
                }
                if( VSIStatL( frameEntry->fullFilePath, &sStatBuf ) != 0 )
#endif
                {
                    frameEntry->fileExists = 0;
                    CPLError( CE_Warning, CPLE_AppDefined,
                        "File %s does not exist.", frameEntry->fullFilePath );
                }
#if !defined(_WIN32) && !defined(_WIN32_CE)
                else
                {
                    frameEntry->fileExists = 1;
                }
#endif
            }
            else
            {
                frameEntry->fileExists = 1;
            }
            CPLFree(subdir);
            CPLFree(baseDir);
        }

        CPLDebug("RPFTOC", "Entry %d : %s,%s (%d, %d)", boundaryId, frameEntry->directory, frameEntry->filename, frameRow, frameCol);

        frameEntry->exists = 1;
    }

    return toc;
}
RPFToc* RPFTOCReadFromBuffer(const char* pszFilename, FILE* fp, const char* tocHeader)
{
    int i, j;
    unsigned int locationSectionPhysicalLocation;
    
    unsigned short nSections;
    unsigned int boundaryRectangleSectionSubHeaderPhysIndex = 0, boundaryRectangleSectionSubHeaderLength = 0;
    unsigned int boundaryRectangleTablePhysIndex = 0, boundaryRectangleTableLength = 0;
    unsigned int frameFileIndexSectionSubHeaderPhysIndex = 0, frameFileIndexSectionSubHeaderLength = 0;
    unsigned int frameFileIndexSubsectionPhysIndex = 0, frameFileIndexSubsectionLength = 0;
    
    unsigned int boundaryRectangleTableOffset;
    unsigned short boundaryRectangleCount;
    
    unsigned int frameIndexTableOffset;
    unsigned int nFrameFileIndexRecords;
    unsigned short nFrameFilePathnameRecords;
    unsigned short frameFileIndexRecordLength;

    int newBoundaryId = 0;

    RPFToc* toc;
    
    tocHeader += 1; /* skip endian */
    tocHeader += 2; /* skip header length */
    tocHeader += 12; /* skip file name : this should be A.TOC (padded) */
    tocHeader += 1; /* skip new  */
    tocHeader += 15; /* skip standard_num  */
    tocHeader += 8; /* skip standard_date  */
    tocHeader += 1; /* skip classification  */
    tocHeader += 2; /* skip country  */
    tocHeader += 2; /* skip release  */
    
    memcpy(&locationSectionPhysicalLocation, tocHeader, sizeof(unsigned int));
    CPL_MSBPTR32(&locationSectionPhysicalLocation);
    
    if( VSIFSeekL( fp, locationSectionPhysicalLocation, SEEK_SET ) != 0)
    {
        CPLError( CE_Failure, CPLE_NotSupported, 
                  "Invalid TOC file. Unable to seek to locationSectionPhysicalLocation at offset %d.",
                   locationSectionPhysicalLocation );
        return NULL;
    }
    
    /* Skip location section length (4) and component location table offset (2)*/
    VSIFSeekL( fp, 4 + 2, SEEK_CUR);
    
    /* How many sections: # of section location records */
    VSIFReadL( &nSections, 1, sizeof(nSections), fp);
    CPL_MSBPTR16( &nSections );
    
    /* Skip location record length(2) + component aggregate length(4) */
    VSIFSeekL( fp, 2 + 4, SEEK_CUR);
    
    for (i = 0; i < nSections; i++)
    {
        unsigned short id;
        unsigned int sectionLength, physIndex;
        VSIFReadL( &id, 1, sizeof(id), fp);
        CPL_MSBPTR16( &id );
        
        VSIFReadL( &sectionLength, 1, sizeof(sectionLength), fp);
        CPL_MSBPTR32( &sectionLength );
        
        VSIFReadL( &physIndex, 1, sizeof(physIndex), fp);
        CPL_MSBPTR32( &physIndex );
        
        if (id == LID_BoundaryRectangleSectionSubheader)
        {
            boundaryRectangleSectionSubHeaderPhysIndex = physIndex;
            boundaryRectangleSectionSubHeaderLength = sectionLength;
        }
        else if (id == LID_BoundaryRectangleTable)
        {
            boundaryRectangleTablePhysIndex = physIndex;
            boundaryRectangleTableLength = sectionLength;
        }
        else if (id == LID_FrameFileIndexSectionSubHeader)
        {
            frameFileIndexSectionSubHeaderPhysIndex = physIndex;
            frameFileIndexSectionSubHeaderLength = sectionLength;
        }
        else if (id == LID_FrameFileIndexSubsection)
        {
            frameFileIndexSubsectionPhysIndex = physIndex;
            frameFileIndexSubsectionLength = sectionLength;
        }
    }
    
    if (boundaryRectangleSectionSubHeaderPhysIndex == 0)
    {
        CPLError( CE_Failure, CPLE_NotSupported, 
                  "Invalid TOC file. Can't find LID_BoundaryRectangleSectionSubheader." );
        return NULL;
    }
    if (boundaryRectangleTablePhysIndex == 0)
    {
        CPLError( CE_Failure, CPLE_NotSupported, 
                  "Invalid TOC file. Can't find LID_BoundaryRectangleTable." );
        return NULL;
    }
    if (frameFileIndexSectionSubHeaderPhysIndex == 0)
    {
        CPLError( CE_Failure, CPLE_NotSupported, 
                  "Invalid TOC file. Can't find LID_FrameFileIndexSectionSubHeader." );
        return NULL;
    }
    if (frameFileIndexSubsectionPhysIndex == 0)
    {
        CPLError( CE_Failure, CPLE_NotSupported, 
                  "Invalid TOC file. Can't find LID_FrameFileIndexSubsection." );
        return NULL;
    }
    
    if( VSIFSeekL( fp, boundaryRectangleSectionSubHeaderPhysIndex, SEEK_SET ) != 0)
    {
        CPLError( CE_Failure, CPLE_NotSupported, 
                  "Invalid TOC file. Unable to seek to boundaryRectangleSectionSubHeaderPhysIndex at offset %d.",
                   boundaryRectangleSectionSubHeaderPhysIndex );
        return NULL;
    }
    
    VSIFReadL( &boundaryRectangleTableOffset, 1, sizeof(boundaryRectangleTableOffset), fp);
    CPL_MSBPTR32( &boundaryRectangleTableOffset );
    
    VSIFReadL( &boundaryRectangleCount, 1, sizeof(boundaryRectangleCount), fp);
    CPL_MSBPTR16( &boundaryRectangleCount );
    
    if( VSIFSeekL( fp, boundaryRectangleTablePhysIndex, SEEK_SET ) != 0)
    {
        CPLError( CE_Failure, CPLE_NotSupported, 
                  "Invalid TOC file. Unable to seek to boundaryRectangleTablePhysIndex at offset %d.",
                   boundaryRectangleTablePhysIndex );
        return NULL;
    }
    
    toc = (RPFToc*)CPLMalloc(sizeof(RPFToc));
    toc->nEntries = boundaryRectangleCount;
    toc->entries = (RPFTocEntry*)CPLMalloc(boundaryRectangleCount * sizeof(RPFTocEntry));
    memset(toc->entries, 0, boundaryRectangleCount * sizeof(RPFTocEntry));
    
    for(i=0;i<toc->nEntries;i++)
    {
        toc->entries[i].isOverviewOrLegend = 0;
        
        VSIFReadL( toc->entries[i].type, 1, 5, fp);
        toc->entries[i].type[5] = 0;
        RPFTOCTrim(toc->entries[i].type);
        
        VSIFReadL( toc->entries[i].compression, 1, 5, fp);
        toc->entries[i].compression[5] = 0;
        RPFTOCTrim(toc->entries[i].compression);
        
        VSIFReadL( toc->entries[i].scale, 1, 12, fp);
        toc->entries[i].scale[12] = 0;
        RPFTOCTrim(toc->entries[i].scale);
        if (toc->entries[i].scale[0] == '1' &&
            toc->entries[i].scale[1] == ':')
        {
            memmove(toc->entries[i].scale,
                    toc->entries[i].scale+2,
                    strlen(toc->entries[i].scale+2)+1);
        }
        
        VSIFReadL( toc->entries[i].zone, 1, 1, fp);
        toc->entries[i].zone[1] = 0;
        RPFTOCTrim(toc->entries[i].zone);
        
        VSIFReadL( toc->entries[i].producer, 1, 5, fp);
        toc->entries[i].producer[5] = 0;
        RPFTOCTrim(toc->entries[i].producer);

        VSIFReadL( &toc->entries[i].nwLat, 1, sizeof(double), fp);
        CPL_MSBPTR64( &toc->entries[i].nwLat);

        VSIFReadL( &toc->entries[i].nwLong, 1, sizeof(double), fp);
        CPL_MSBPTR64( &toc->entries[i].nwLong);

        VSIFReadL( &toc->entries[i].swLat, 1, sizeof(double), fp);
        CPL_MSBPTR64( &toc->entries[i].swLat);

        VSIFReadL( &toc->entries[i].swLong, 1, sizeof(double), fp);
        CPL_MSBPTR64( &toc->entries[i].swLong);

        VSIFReadL( &toc->entries[i].neLat, 1, sizeof(double), fp);
        CPL_MSBPTR64( &toc->entries[i].neLat);

        VSIFReadL( &toc->entries[i].neLong, 1, sizeof(double), fp);
        CPL_MSBPTR64( &toc->entries[i].neLong);

        VSIFReadL( &toc->entries[i].seLat, 1, sizeof(double), fp);
        CPL_MSBPTR64( &toc->entries[i].seLat);
        
        VSIFReadL( &toc->entries[i].seLong, 1, sizeof(double), fp);
        CPL_MSBPTR64( &toc->entries[i].seLong);
        
        VSIFReadL( &toc->entries[i].vertResolution, 1, sizeof(double), fp);
        CPL_MSBPTR64( &toc->entries[i].vertResolution);
        
        VSIFReadL( &toc->entries[i].horizResolution, 1, sizeof(double), fp);
        CPL_MSBPTR64( &toc->entries[i].horizResolution);
        
        VSIFReadL( &toc->entries[i].vertInterval, 1, sizeof(double), fp);
        CPL_MSBPTR64( &toc->entries[i].vertInterval);

        VSIFReadL( &toc->entries[i].horizInterval, 1, sizeof(double), fp);
        CPL_MSBPTR64( &toc->entries[i].horizInterval);
        
        VSIFReadL( &toc->entries[i].nVertFrames, 1, sizeof(int), fp);
        CPL_MSBPTR32( &toc->entries[i].nVertFrames );
        
        VSIFReadL( &toc->entries[i].nHorizFrames, 1, sizeof(int), fp);
        CPL_MSBPTR32( &toc->entries[i].nHorizFrames );
        
        toc->entries[i].frameEntries = (RPFTocFrameEntry*)
                VSIMalloc3(toc->entries[i].nVertFrames, toc->entries[i].nHorizFrames, sizeof(RPFTocFrameEntry));
        if (toc->entries[i].frameEntries == NULL)
        {
            CPLError( CE_Failure, CPLE_OutOfMemory,
                      "RPFTOCReadFromBuffer : Out of memory. Probably due to corrupted TOC file.");
            RPFTOCFree(toc);
            return NULL;
        }
        memset(toc->entries[i].frameEntries, 0,
               toc->entries[i].nVertFrames * toc->entries[i].nHorizFrames * sizeof(RPFTocFrameEntry));
        
        CPLDebug("RPFTOC", "[%d] type=%s, compression=%s, scale=%s, zone=%s, producer=%s, nVertFrames=%d, nHorizFrames=%d",
                 i, toc->entries[i].type, toc->entries[i].compression, toc->entries[i].scale,
                 toc->entries[i].zone, toc->entries[i].producer, toc->entries[i].nVertFrames, toc->entries[i].nHorizFrames);
    }
    
    if( VSIFSeekL( fp, frameFileIndexSectionSubHeaderPhysIndex, SEEK_SET ) != 0)
    {
        CPLError( CE_Failure, CPLE_NotSupported, 
                  "Invalid TOC file. Unable to seek to frameFileIndexSectionSubHeaderPhysIndex at offset %d.",
                   frameFileIndexSectionSubHeaderPhysIndex );
        RPFTOCFree(toc);
        return NULL;
    }
    
    /* Skip 1 byte security classification */
    VSIFSeekL( fp, 1, SEEK_CUR );
    
    VSIFReadL( &frameIndexTableOffset, 1, sizeof(frameIndexTableOffset), fp);
    CPL_MSBPTR32( &frameIndexTableOffset );
    
    VSIFReadL( &nFrameFileIndexRecords, 1, sizeof(nFrameFileIndexRecords), fp);
    CPL_MSBPTR32( &nFrameFileIndexRecords );
    
    VSIFReadL( &nFrameFilePathnameRecords, 1, sizeof(nFrameFilePathnameRecords), fp);
    CPL_MSBPTR16( &nFrameFilePathnameRecords );
    
    VSIFReadL( &frameFileIndexRecordLength, 1, sizeof(frameFileIndexRecordLength), fp);
    CPL_MSBPTR16( &frameFileIndexRecordLength );
    
    for (i=0;i<(int)nFrameFileIndexRecords;i++)
    {
        RPFTocEntry* entry;
        RPFTocFrameEntry* frameEntry;
        unsigned short boundaryId, frameRow, frameCol;
        unsigned int offsetFrameFilePathName;
        unsigned short pathLength;
        
        if( VSIFSeekL( fp, frameFileIndexSubsectionPhysIndex + frameFileIndexRecordLength * i, SEEK_SET ) != 0)
        {
            CPLError( CE_Failure, CPLE_NotSupported, 
                    "Invalid TOC file. Unable to seek to frameFileIndexSubsectionPhysIndex(%d) at offset %d.",
                     i, frameFileIndexSubsectionPhysIndex + frameFileIndexRecordLength * i);
            RPFTOCFree(toc);
            return NULL;
        }

        VSIFReadL( &boundaryId, 1, sizeof(boundaryId), fp);
        CPL_MSBPTR16( &boundaryId );
        
        if (i == 0 && boundaryId == 0)
            newBoundaryId = 1;
        if (newBoundaryId == 0)
            boundaryId--;
        
        if (boundaryId >= toc->nEntries)
        {
            CPLError( CE_Failure, CPLE_NotSupported, 
                    "Invalid TOC file. Bad boundary id (%d) for frame file index %d.",
                     boundaryId, i);
            RPFTOCFree(toc);
            return NULL;
        }
        
        entry = &toc->entries[boundaryId];
        entry->boundaryId = boundaryId;
        
        VSIFReadL( &frameRow, 1, sizeof(frameRow), fp);
        CPL_MSBPTR16( &frameRow );
        
        VSIFReadL( &frameCol, 1, sizeof(frameCol), fp);
        CPL_MSBPTR16( &frameCol );


        if (newBoundaryId == 0)
        {
            frameRow--;
            frameCol--;
        }
        else
        {
            /* Trick so that frames are numbered north to south */
            frameRow = (unsigned short)((entry->nVertFrames-1) - frameRow);
        }
   
        if (frameRow >= entry->nVertFrames)
        {
            CPLError( CE_Failure, CPLE_NotSupported, 
                        "Invalid TOC file. Bad row num (%d) for frame file index %d.",
                        frameRow, i);
            RPFTOCFree(toc);
            return NULL;
        }
        
        if (frameCol >= entry->nHorizFrames)
        {
            CPLError( CE_Failure, CPLE_NotSupported, 
                        "Invalid TOC file. Bad col num (%d) for frame file index %d.",
                        frameCol, i);
            RPFTOCFree(toc);
            return NULL;
        }

        frameEntry = &entry->frameEntries[frameRow * entry->nHorizFrames + frameCol ];
        frameEntry->frameRow = frameRow;
        frameEntry->frameCol = frameCol;

        if (frameEntry->exists)
        {
            CPLError( CE_Failure, CPLE_NotSupported, 
                      "Invalid TOC file. Frame entry(%d,%d) for frame file index %d is a duplicate.",
                      frameRow, frameCol, i);
            RPFTOCFree(toc);
            return NULL;
        }
        
        VSIFReadL( &offsetFrameFilePathName, 1, sizeof(offsetFrameFilePathName), fp);
        CPL_MSBPTR32( &offsetFrameFilePathName );
        

        VSIFReadL( frameEntry->filename, 1, 12, fp);
        frameEntry->filename[12] = '\0';

        /* Check if the filename is an overview or legend */
        for (j=0;j<12;j++)
        {
            if (strcmp(&(frameEntry->filename[j]),".OVR") == 0 ||
                strcmp(&(frameEntry->filename[j]),".ovr") == 0 ||
                strcmp(&(frameEntry->filename[j]),".LGD") == 0 ||
                strcmp(&(frameEntry->filename[j]),".lgd") == 0)
            {
                entry->isOverviewOrLegend = TRUE;
                break;
            }
        }
        
        /* Extract series code */
        if (entry->seriesAbbreviation == NULL)
        {
            const NITFSeries* series = NITFGetSeriesInfo(frameEntry->filename);
            if (series)
            {
                entry->seriesAbbreviation = series->abbreviation;
                entry->seriesName = series->name;
            }
        }

        /* Get file geo reference */
        VSIFReadL( frameEntry->georef, 1, 6, fp);
        frameEntry->georef[6] = '\0';

        /* Go to start of pathname record */
        /* New path_off offset from start of frame file index section of TOC?? */
        /* Add pathoffset wrt frame file index table subsection (loc[3]) */
        if( VSIFSeekL( fp, frameFileIndexSubsectionPhysIndex + offsetFrameFilePathName, SEEK_SET ) != 0)
        {
            CPLError( CE_Failure, CPLE_NotSupported, 
                    "Invalid TOC file. Unable to seek to frameFileIndexSubsectionPhysIndex + offsetFrameFilePathName(%d) at offset %d.",
                     i, frameFileIndexSubsectionPhysIndex + offsetFrameFilePathName);
            RPFTOCFree(toc);
            return NULL;
        }

        VSIFReadL( &pathLength, 1, sizeof(pathLength), fp);
        CPL_MSBPTR16( &pathLength );
        
        /* if nFrameFileIndexRecords == 65535 and pathLength == 65535 for each record,
           this leads to 4 GB allocation... Protect against this case */
        if (pathLength > 256)
        {
            CPLError( CE_Failure, CPLE_NotSupported,
                      "Path length is big : %d. Probably corrupted TOC file.", (int)pathLength);
            RPFTOCFree(toc);
            return NULL;
        }
        
        frameEntry->directory = (char *)CPLMalloc(pathLength+1);
        VSIFReadL( frameEntry->directory, 1, pathLength, fp);
        frameEntry->directory[pathLength] = 0;
        if (pathLength > 0 && frameEntry->directory[pathLength-1] == '/')
            frameEntry->directory[pathLength-1] = 0;
        
        if (frameEntry->directory[0] == '.' && frameEntry->directory[1] == '/')
            memmove(frameEntry->directory, frameEntry->directory+2, strlen(frameEntry->directory+2)+1);
        
        {
            char* baseDir = CPLStrdup(CPLGetDirname(pszFilename));
            VSIStatBufL sStatBuf;
            char* subdir;
            if (CPLIsFilenameRelative(frameEntry->directory) == FALSE)
                subdir = CPLStrdup(frameEntry->directory);
            else if (frameEntry->directory[0] == '.' && frameEntry->directory[1] == 0)
                subdir = CPLStrdup(baseDir);
            else
                subdir = CPLStrdup(CPLFormFilename(baseDir, frameEntry->directory, NULL));
#if !defined(_WIN32) && !defined(_WIN32_CE)
            if( VSIStatL( subdir, &sStatBuf ) != 0 && subdir[strlen(baseDir)] != 0)
            {
                char* c = subdir + strlen(baseDir)+1;
                while(*c)
                {
                    if (*c >= 'A' && *c <= 'Z')
                        *c += 'a' - 'A';
                    c++;
                }
            }
#endif
            frameEntry->fullFilePath = CPLStrdup(CPLFormFilename(
                    subdir,
                    frameEntry->filename, NULL));
            if( VSIStatL( frameEntry->fullFilePath, &sStatBuf ) != 0 )
            {
#if !defined(_WIN32) && !defined(_WIN32_CE)
                char* c = frameEntry->fullFilePath + strlen(subdir)+1;
                while(*c)
                {
                    if (*c >= 'A' && *c <= 'Z')
                        *c += 'a' - 'A';
                    c++;
                }
                if( VSIStatL( frameEntry->fullFilePath, &sStatBuf ) != 0 )
#endif
                {
                    frameEntry->fileExists = 0;
                    CPLError( CE_Warning, CPLE_AppDefined, 
                        "File %s does not exist.", frameEntry->fullFilePath );
                }
#if !defined(_WIN32) && !defined(_WIN32_CE)
                else
                {
                    frameEntry->fileExists = 1;
                }
#endif
            }
            else
            {
                frameEntry->fileExists = 1;
            }
            CPLFree(subdir);
            CPLFree(baseDir);
        }

        CPLDebug("RPFTOC", "Entry %d : %s,%s (%d, %d)", boundaryId, frameEntry->directory, frameEntry->filename, frameRow, frameCol);

        frameEntry->exists = 1;
    }
    
    return toc;
}
Beispiel #9
0
NITFDES *NITFDESAccess( NITFFile *psFile, int iSegment )

{
    NITFDES   *psDES;
    char      *pachHeader;
    NITFSegmentInfo *psSegInfo;
    char       szDESID[26];
    int        nOffset;
    int        bHasDESOFLW;
    int        nDESSHL;

/* -------------------------------------------------------------------- */
/*      Verify segment, and return existing DES accessor if there       */
/*      is one.                                                         */
/* -------------------------------------------------------------------- */
    if( iSegment < 0 || iSegment >= psFile->nSegmentCount )
        return NULL;

    psSegInfo = psFile->pasSegmentInfo + iSegment;

    if( !EQUAL(psSegInfo->szSegmentType,"DE") )
        return NULL;

    if( psSegInfo->hAccess != NULL )
        return (NITFDES *) psSegInfo->hAccess;

/* -------------------------------------------------------------------- */
/*      Read the DES subheader.                                         */
/* -------------------------------------------------------------------- */
    if (psSegInfo->nSegmentHeaderSize < 200)
    {
        CPLError(CE_Failure, CPLE_AppDefined,
                    "DES header too small");
        return NULL;
    }

    pachHeader = (char*) VSI_MALLOC_VERBOSE(psSegInfo->nSegmentHeaderSize);
    if (pachHeader == NULL)
    {
        return NULL;
    }

retry:
    if( VSIFSeekL( psFile->fp, psSegInfo->nSegmentHeaderStart,
                  SEEK_SET ) != 0
        || VSIFReadL( pachHeader, 1, psSegInfo->nSegmentHeaderSize,
                     psFile->fp ) != psSegInfo->nSegmentHeaderSize )
    {
        CPLError( CE_Failure, CPLE_FileIO,
                  "Failed to read %u byte DES subheader from " CPL_FRMT_GUIB ".",
                  psSegInfo->nSegmentHeaderSize,
                  psSegInfo->nSegmentHeaderStart );
        CPLFree(pachHeader);
        return NULL;
    }

    if (!STARTS_WITH_CI(pachHeader, "DE"))
    {
        if (STARTS_WITH_CI(pachHeader + 4, "DERegistered"))
        {
            /* BAO_46_Ed1/rpf/conc/concz10/000fz010.ona and cie are buggy */
            CPLDebug("NITF", "Patching nSegmentHeaderStart and nSegmentStart for DE segment %d", iSegment);
            psSegInfo->nSegmentHeaderStart += 4;
            psSegInfo->nSegmentStart += 4;
            goto retry;
        }

        CPLError(CE_Failure, CPLE_AppDefined,
                 "Invalid segment prefix for DE segment %d", iSegment);

        CPLFree(pachHeader);
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Initialize DES object.                                          */
/* -------------------------------------------------------------------- */
    psDES = (NITFDES *) CPLCalloc(sizeof(NITFDES),1);

    psDES->psFile = psFile;
    psDES->iSegment = iSegment;
    psDES->pachHeader = pachHeader;

    psSegInfo->hAccess = psDES;

/* -------------------------------------------------------------------- */
/*      Collect a variety of information as metadata.                   */
/* -------------------------------------------------------------------- */
#define GetMD( length, name )              \
    do { NITFExtractMetadata( &(psDES->papszMetadata), pachHeader,    \
                         nOffset, length,                        \
                         "NITF_" #name ); \
    nOffset += length; } while(0)

    nOffset = 2;
    GetMD( 25, DESID  );
    GetMD(  2, DESVER );
    GetMD(  1, DECLAS );
    GetMD(  2, DESCLSY );
    GetMD( 11, DESCODE );
    GetMD(  2, DESCTLH );
    GetMD( 20, DESREL  );
    GetMD(  2, DESDCTP );
    GetMD(  8, DESDCDT );
    GetMD(  4, DESDCXM );
    GetMD(  1, DESDG   );
    GetMD(  8, DESDGDT );
    GetMD( 43, DESCLTX );
    GetMD(  1, DESCATP );
    GetMD( 40, DESCAUT );
    GetMD(  1, DESCRSN );
    GetMD(  8, DESSRDT );
    GetMD( 15, DESCTLN );

    /* Load DESID */
    NITFGetField( szDESID, pachHeader, 2, 25);

    /* For NITF < 02.10, we cannot rely on DESID=TRE_OVERFLOW to detect */
    /* if DESOFLW and DESITEM are present. So if the next 4 bytes are non */
    /* numeric, we'll assume that DESOFLW is there */
    bHasDESOFLW = STARTS_WITH_CI(szDESID, "TRE_OVERFLOW") ||
       (!((pachHeader[nOffset+0] >= '0' && pachHeader[nOffset+0] <= '9') &&
          (pachHeader[nOffset+1] >= '0' && pachHeader[nOffset+1] <= '9') &&
          (pachHeader[nOffset+2] >= '0' && pachHeader[nOffset+2] <= '9') &&
          (pachHeader[nOffset+3] >= '0' && pachHeader[nOffset+3] <= '9')));

    if (bHasDESOFLW)
    {
        if ((int)psSegInfo->nSegmentHeaderSize < nOffset + 6 + 3 )
        {
            CPLError(CE_Failure, CPLE_AppDefined,
                        "DES header too small");
            NITFDESDeaccess(psDES);
            return NULL;
        }
        GetMD(  6, DESOFLW );
        GetMD(  3, DESITEM );
    }

    if ((int)psSegInfo->nSegmentHeaderSize < nOffset + 4 )
    {
        CPLError(CE_Failure, CPLE_AppDefined,
                    "DES header too small");
        NITFDESDeaccess(psDES);
        return NULL;
    }

    GetMD( 4, DESSHL );
    nDESSHL = atoi(CSLFetchNameValue( psDES->papszMetadata, "NITF_DESSHL" ) );

    if (nDESSHL < 0)
    {
        CPLError(CE_Failure, CPLE_AppDefined,
                    "Invalid value for DESSHL");
        NITFDESDeaccess(psDES);
        return NULL;
    }
    if ( (int)psSegInfo->nSegmentHeaderSize < nOffset + nDESSHL)
    {
        CPLError(CE_Failure, CPLE_AppDefined,
                    "DES header too small");
        NITFDESDeaccess(psDES);
        return NULL;
    }

    if (STARTS_WITH_CI(szDESID, "CSSHPA DES"))
    {
        if ( nDESSHL != 62 && nDESSHL != 80)
        {
            CPLError(CE_Failure, CPLE_AppDefined,
                     "Invalid DESSHL for CSSHPA DES");
            NITFDESDeaccess(psDES);
            return NULL;
        }

        GetMD( 25, SHAPE_USE );
        GetMD( 10, SHAPE_CLASS );
        if (nDESSHL == 80)
            GetMD( 18, CC_SOURCE );
        GetMD(  3, SHAPE1_NAME );
        GetMD(  6, SHAPE1_START );
        GetMD(  3, SHAPE2_NAME );
        GetMD(  6, SHAPE2_START );
        GetMD(  3, SHAPE3_NAME );
        GetMD(  6, SHAPE3_START );
    }
    else if (STARTS_WITH_CI(szDESID, "XML_DATA_CONTENT"))
    {
        /* TODO : handle nDESSHL = 0005 and 0283 */
        if (nDESSHL >= 5)
        {
            GetMD( 5, DESCRC );
            if (nDESSHL >= 283)
            {
                GetMD( 8, DESSHFT );
                GetMD( 20, DESSHDT );
                GetMD( 40, DESSHRP );
                GetMD( 60, DESSHSI );
                GetMD( 10, DESSHSV );
                GetMD( 20, DESSHSD );
                GetMD( 120, DESSHTN );
                if (nDESSHL >= 773)
                {
                    GetMD( 125, DESSHLPG );
                    GetMD( 25, DESSHLPT );
                    GetMD( 20, DESSHLI );
                    GetMD( 120, DESSHLIN );
                    GetMD( 200, DESSHABS );
                }
            }
        }
    }
    else if (STARTS_WITH_CI(szDESID, "CSATTA DES") && nDESSHL == 52)
    {
        GetMD( 12, ATT_TYPE );
        GetMD( 14, DT_ATT );
        GetMD( 8, DATE_ATT );
        GetMD( 13, T0_ATT );
        GetMD( 5, NUM_ATT );
    }
    else if (nDESSHL > 0)
        GetMD(  nDESSHL, DESSHF );

    if ((int)psSegInfo->nSegmentHeaderSize > nOffset)
    {
        char* pszEscapedDESDATA =
                CPLEscapeString( pachHeader + nOffset,
                                 (int)psSegInfo->nSegmentHeaderSize - nOffset,
                                 CPLES_BackslashQuotable );
        psDES->papszMetadata = CSLSetNameValue( psDES->papszMetadata,
                                                "NITF_DESDATA",
                                                pszEscapedDESDATA );
        CPLFree(pszEscapedDESDATA);
    }
    else
    {

#define TEN_MEGABYTES 10485760

        if (psSegInfo->nSegmentSize > TEN_MEGABYTES)
        {
            const char* pszOffset = CPLSPrintf(CPL_FRMT_GUIB, psFile->pasSegmentInfo[iSegment].nSegmentStart);
            const char* pszSize = CPLSPrintf(CPL_FRMT_GUIB, psFile->pasSegmentInfo[iSegment].nSegmentSize);

            psDES->papszMetadata = CSLSetNameValue( psDES->papszMetadata,
                                                    "NITF_DESDATA_OFFSET",
                                                    pszOffset );
            psDES->papszMetadata = CSLSetNameValue( psDES->papszMetadata,
                                                    "NITF_DESDATA_LENGTH",
                                                    pszSize);
        }
        else
        {
            char* pachData = (char*)VSI_MALLOC_VERBOSE((size_t)psSegInfo->nSegmentSize);
            if (pachData == NULL )
            {
                /* nothing */
            }
            else if( VSIFSeekL( psFile->fp, psSegInfo->nSegmentStart,
                        SEEK_SET ) != 0
                || VSIFReadL( pachData, 1, (size_t)psSegInfo->nSegmentSize,
                            psFile->fp ) != psSegInfo->nSegmentSize )
            {
                CPLDebug("NITF",
                        "Failed to read " CPL_FRMT_GUIB" bytes DES data from " CPL_FRMT_GUIB ".",
                        psSegInfo->nSegmentSize,
                        psSegInfo->nSegmentStart );
            }
            else
            {
                char* pszEscapedDESDATA =
                        CPLEscapeString( pachData,
                                        (int)psSegInfo->nSegmentSize,
                                        CPLES_BackslashQuotable );
                psDES->papszMetadata = CSLSetNameValue( psDES->papszMetadata,
                                                        "NITF_DESDATA",
                                                        pszEscapedDESDATA );
                CPLFree(pszEscapedDESDATA);
            }
            CPLFree(pachData);
        }

#ifdef notdef
        /* Disabled because might generate a huge amount of elements */
        if (STARTS_WITH_CI(szDESID, "CSATTA DES"))
        {
            int nNumAtt = atoi(CSLFetchNameValueDef(psDES->papszMetadata, "NITF_NUM_ATT", "0"));
            if (nNumAtt * 8 * 4 == psSegInfo->nSegmentSize)
            {
                int nMDSize = CSLCount(psDES->papszMetadata);
                char** papszMD = (char**)VSIRealloc(psDES->papszMetadata, (nMDSize + nNumAtt * 4 + 1) * sizeof(char*));
                if (papszMD)
                {
                    int i, j;
                    const GByte* pachDataIter = pachData;

                    psDES->papszMetadata = papszMD;
                    for(i=0;i<nNumAtt;i++)
                    {
                        char szAttrNameValue[64+1+256+1];
                        double dfVal;
                        for(j=0;j<4;j++)
                        {
                            memcpy(&dfVal, pachDataIter, 8);
                            CPL_MSBPTR64(&dfVal);
                            pachDataIter += 8;
                            CPLsprintf(szAttrNameValue, "NITF_ATT_Q%d_%d=%.16g", j+1, i, dfVal);
                            papszMD[nMDSize + i * 4 + j] = CPLStrdup(szAttrNameValue);
                        }
                    }
                    papszMD[nMDSize + nNumAtt * 4] = NULL;
                }
            }
        }
#endif

    }

    return psDES;
}
int NGSGEOIDDataset::GetHeaderInfo( const GByte* pBuffer,
                                    double* padfGeoTransform,
                                    int* pnRows,
                                    int* pnCols,
                                    int* pbIsLittleEndian )
{
    double dfSLAT;
    double dfWLON;
    double dfDLAT;
    double dfDLON;
    int nNLAT;
    int nNLON;
    int nIKIND;

    /* First check IKIND marker to determine if the file */
    /* is in little or big-endian order, and if it is a valid */
    /* NGSGEOID dataset */
    memcpy(&nIKIND, pBuffer + HEADER_SIZE - 4, 4);
    CPL_LSBPTR32(&nIKIND);
    if (nIKIND == 1)
    {
        *pbIsLittleEndian = TRUE;
    }
    else
    {
        memcpy(&nIKIND, pBuffer + HEADER_SIZE - 4, 4);
        CPL_MSBPTR32(&nIKIND);
        if (nIKIND == 1)
        {
            *pbIsLittleEndian = FALSE;
        }
        else
        {
            return FALSE;
        }
    }

    memcpy(&dfSLAT, pBuffer, 8);
    if (*pbIsLittleEndian)
    {
        CPL_LSBPTR64(&dfSLAT);
    }
    else
    {
        CPL_MSBPTR64(&dfSLAT);
    }
    pBuffer += 8;
    memcpy(&dfWLON, pBuffer, 8);
    if (*pbIsLittleEndian)
    {
        CPL_LSBPTR64(&dfWLON);
    }
    else
    {
        CPL_MSBPTR64(&dfWLON);
    }
    pBuffer += 8;
    memcpy(&dfDLAT, pBuffer, 8);
    if (*pbIsLittleEndian)
    {
        CPL_LSBPTR64(&dfDLAT);
    }
    else
    {
        CPL_MSBPTR64(&dfDLAT);
    }
    pBuffer += 8;
    memcpy(&dfDLON, pBuffer, 8);
    if (*pbIsLittleEndian)
    {
        CPL_LSBPTR64(&dfDLON);
    }
    else
    {
        CPL_MSBPTR64(&dfDLON);
    }
    pBuffer += 8;
    memcpy(&nNLAT, pBuffer, 4);
    if (*pbIsLittleEndian)
    {
        CPL_LSBPTR32(&nNLAT);
    }
    else
    {
        CPL_MSBPTR32(&nNLAT);
    }
    pBuffer += 4;
    memcpy(&nNLON, pBuffer, 4);
    if (*pbIsLittleEndian)
    {
        CPL_LSBPTR32(&nNLON);
    }
    else
    {
        CPL_MSBPTR32(&nNLON);
    }
    pBuffer += 4;

    /*CPLDebug("NGSGEOID", "SLAT=%f, WLON=%f, DLAT=%f, DLON=%f, NLAT=%d, NLON=%d, IKIND=%d",
             dfSLAT, dfWLON, dfDLAT, dfDLON, nNLAT, nNLON, nIKIND);*/

    if (nNLAT <= 0 || nNLON <= 0 || dfDLAT <= 0.0 || dfDLON <= 0.0)
        return FALSE;

    /* Grids go over +180 in longitude */
    if (dfSLAT < -90.0 || dfSLAT + nNLAT * dfDLAT > 90.0 ||
        dfWLON < -180.0 || dfWLON + nNLON * dfDLON > 360.0)
        return FALSE;

    padfGeoTransform[0] = dfWLON - dfDLON / 2;
    padfGeoTransform[1] = dfDLON;
    padfGeoTransform[2] = 0.0;
    padfGeoTransform[3] = dfSLAT + nNLAT * dfDLAT - dfDLAT / 2;
    padfGeoTransform[4] = 0.0;
    padfGeoTransform[5] = -dfDLAT;

    *pnRows = nNLAT;
    *pnCols = nNLON;

    return TRUE;
}
Beispiel #11
0
GDALDataset *GTXDataset::Open( GDALOpenInfo * poOpenInfo )

{
    if( !Identify( poOpenInfo ) )
        return NULL;
        
/* -------------------------------------------------------------------- */
/*      Create a corresponding GDALDataset.                             */
/* -------------------------------------------------------------------- */
    GTXDataset 	*poDS;

    poDS = new GTXDataset();

    poDS->eAccess = poOpenInfo->eAccess;

/* -------------------------------------------------------------------- */
/*      Open the file.                                                  */
/* -------------------------------------------------------------------- */
    if( poOpenInfo->eAccess == GA_ReadOnly )
        poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb" );
    else
        poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb+" );

    if( poDS->fpImage == NULL )
    {
        delete poDS;
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Read the header.                                                */
/* -------------------------------------------------------------------- */
    poDS->adfGeoTransform[2] = 0.0;
    poDS->adfGeoTransform[4] = 0.0;

    VSIFReadL( poDS->adfGeoTransform+3, 8, 1, poDS->fpImage );
    VSIFReadL( poDS->adfGeoTransform+0, 8, 1, poDS->fpImage );
    VSIFReadL( poDS->adfGeoTransform+5, 8, 1, poDS->fpImage );
    VSIFReadL( poDS->adfGeoTransform+1, 8, 1, poDS->fpImage );

    VSIFReadL( &(poDS->nRasterYSize), 4, 1, poDS->fpImage );
    VSIFReadL( &(poDS->nRasterXSize), 4, 1, poDS->fpImage );

    CPL_MSBPTR32( &(poDS->nRasterYSize) );
    CPL_MSBPTR32( &(poDS->nRasterXSize) );

    CPL_MSBPTR64( poDS->adfGeoTransform + 0 );
    CPL_MSBPTR64( poDS->adfGeoTransform + 1 );
    CPL_MSBPTR64( poDS->adfGeoTransform + 3 );
    CPL_MSBPTR64( poDS->adfGeoTransform + 5 );

    poDS->adfGeoTransform[3] += 
        poDS->adfGeoTransform[5] * (poDS->nRasterYSize-1);

    poDS->adfGeoTransform[0] -= poDS->adfGeoTransform[1] * 0.5;
    poDS->adfGeoTransform[3] += poDS->adfGeoTransform[5] * 0.5;

    poDS->adfGeoTransform[5] *= -1;

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

/* -------------------------------------------------------------------- */
/*      Create band information object.                                 */
/* -------------------------------------------------------------------- */
    poDS->SetBand( 
        1, new RawRasterBand( poDS, 1, poDS->fpImage, 
                              (poDS->nRasterYSize-1)*poDS->nRasterXSize*4 + 40,
                              4, poDS->nRasterXSize * -4,
                              GDT_Float32,
                              !CPL_IS_LSB, TRUE, FALSE ) );

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

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

    return( poDS );
}
Beispiel #12
0
GDALDataset *
RCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
             int bStrict, char ** papszOptions, 
             GDALProgressFunc pfnProgress, void * pProgressData )

{
    int  nBands = poSrcDS->GetRasterCount();
    int  nXSize = poSrcDS->GetRasterXSize();
    int  nYSize = poSrcDS->GetRasterYSize();
    int  bASCII = CSLFetchBoolean( papszOptions, "ASCII", FALSE );
    int  bCompressed = CSLFetchBoolean( papszOptions, "COMPRESS", !bASCII );

/* -------------------------------------------------------------------- */
/*      Some some rudimentary checks                                    */
/* -------------------------------------------------------------------- */

/* -------------------------------------------------------------------- */
/*      Setup the filename to actually use.  We prefix with             */
/*      /vsigzip/ if we want compressed output.                         */
/* -------------------------------------------------------------------- */
    CPLString osAdjustedFilename;

    if( bCompressed )
        osAdjustedFilename = "/vsigzip/";

    osAdjustedFilename += pszFilename;

/* -------------------------------------------------------------------- */
/*      Create the file.                                                */
/* -------------------------------------------------------------------- */
    FILE	*fp;

    fp = VSIFOpenL( osAdjustedFilename, "wb" );
    if( fp == NULL )
    {
        CPLError( CE_Failure, CPLE_OpenFailed, 
                  "Unable to create file %s.\n", 
                  pszFilename );
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Write header with version, etc.                                 */
/* -------------------------------------------------------------------- */
    if( bASCII )
    {
        const char *pszHeader = "RDA2\nA\n";
        VSIFWriteL( pszHeader, 1, strlen(pszHeader), fp );
    }
    else
    {
        const char *pszHeader = "RDX2\nX\n";
        VSIFWriteL( pszHeader, 1, strlen(pszHeader), fp );
    }

    RWriteInteger( fp, bASCII, 2 );
    RWriteInteger( fp, bASCII, 133377 );
    RWriteInteger( fp, bASCII, 131840 );

/* -------------------------------------------------------------------- */
/*      Establish the primary pairlist with one component object.       */
/* -------------------------------------------------------------------- */
    RWriteInteger( fp, bASCII, 1026 );
    RWriteInteger( fp, bASCII, 1 );  

/* -------------------------------------------------------------------- */
/*      Write the object name.  Eventually we should derive this        */
/*      from the filename, possible with override by a creation         */
/*      option.                                                         */
/* -------------------------------------------------------------------- */
    RWriteString( fp, bASCII, "gg" );

/* -------------------------------------------------------------------- */
/*      For now we write the raster as a numeric array with             */
/*      attributes (526).                                               */
/* -------------------------------------------------------------------- */
    RWriteInteger( fp, bASCII, 526 );
    RWriteInteger( fp, bASCII, nXSize * nYSize * nBands );

/* -------------------------------------------------------------------- */
/*      Write the raster data.                                          */
/* -------------------------------------------------------------------- */
    double 	*padfScanline;
    CPLErr      eErr = CE_None;
    int         iLine;

    padfScanline = (double *) CPLMalloc( nXSize * sizeof(double) );

    for( int iBand = 0; iBand < nBands; iBand++ )
    {
        GDALRasterBand * poBand = poSrcDS->GetRasterBand( iBand+1 );

        for( iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ )
        {
            int iValue;

            eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
                                     padfScanline, nXSize, 1, GDT_Float64,
                                     sizeof(double), 0 );

            if( bASCII )
            {
                for( iValue = 0; iValue < nXSize; iValue++ )
                {
                    char szValue[128];
                    sprintf(szValue,"%.16g\n", padfScanline[iValue] );
                    VSIFWriteL( szValue, 1, strlen(szValue), fp );
                }
            }
            else
            {
                for( iValue = 0; iValue < nXSize; iValue++ )
                    CPL_MSBPTR64( padfScanline + iValue );

                VSIFWriteL( padfScanline, 8, nXSize, fp );
            }
            
            if( eErr == CE_None
                && !pfnProgress( (iLine+1) / (double) nYSize,
                                 NULL, pProgressData ) )
            {
                eErr = CE_Failure;
                CPLError( CE_Failure, CPLE_UserInterrupt,
                          "User terminated CreateCopy()" );
            }
        }
    }

    CPLFree( padfScanline );

/* -------------------------------------------------------------------- */
/*      Write out the dims attribute.                                   */
/* -------------------------------------------------------------------- */
    RWriteInteger( fp, bASCII, 1026 );
    RWriteInteger( fp, bASCII, 1 );  
    
    RWriteString( fp, bASCII, "dim" );

    RWriteInteger( fp, bASCII, 13 );
    RWriteInteger( fp, bASCII, 3 );
    RWriteInteger( fp, bASCII, nXSize );
    RWriteInteger( fp, bASCII, nYSize );
    RWriteInteger( fp, bASCII, nBands );

    RWriteInteger( fp, bASCII, 254 );

/* -------------------------------------------------------------------- */
/*      Terminate overall pairlist.                                     */
/* -------------------------------------------------------------------- */
    RWriteInteger( fp, bASCII, 254 );

/* -------------------------------------------------------------------- */
/*      Cleanup.                                                        */
/* -------------------------------------------------------------------- */
    VSIFCloseL( fp );

    if( eErr != CE_None )
        return NULL;

/* -------------------------------------------------------------------- */
/*      Re-open dataset, and copy any auxilary pam information.         */
/* -------------------------------------------------------------------- */
    GDALPamDataset *poDS = 
        (GDALPamDataset *) GDALOpen( pszFilename, GA_ReadOnly );

    if( poDS )
        poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );

    return poDS;
}