GDALDataset *BTDataset::Create( const char * pszFilename, int nXSize, int nYSize, int nBands, GDALDataType eType, CPL_UNUSED char ** papszOptions ) { /* -------------------------------------------------------------------- */ /* Verify input options. */ /* -------------------------------------------------------------------- */ if( eType != GDT_Int16 && eType != GDT_Int32 && eType != GDT_Float32 ) { CPLError( CE_Failure, CPLE_AppDefined, "Attempt to create .bt dataset with an illegal " "data type (%s), only Int16, Int32 and Float32 supported.", GDALGetDataTypeName(eType) ); return NULL; } if( nBands != 1 ) { CPLError( CE_Failure, CPLE_AppDefined, "Attempt to create .bt dataset with %d bands, only 1 supported", nBands ); 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.", pszFilename ); return NULL; } /* -------------------------------------------------------------------- */ /* Setup base header. */ /* -------------------------------------------------------------------- */ unsigned char abyHeader[256] = {}; memcpy( abyHeader, "binterr1.3", 10 ); GInt32 nTemp = CPL_LSBWORD32( nXSize ); memcpy( abyHeader+10, &nTemp, 4 ); nTemp = CPL_LSBWORD32( nYSize ); memcpy( abyHeader+14, &nTemp, 4 ); GInt16 nShortTemp = static_cast<GInt16>( CPL_LSBWORD16( (GInt16)(GDALGetDataTypeSize( eType ) / 8 )) ); memcpy( abyHeader + 18, &nShortTemp, 2 ); if( eType == GDT_Float32 ) abyHeader[20] = 1; else abyHeader[20] = 0; nShortTemp = CPL_LSBWORD16( 1 ); /* meters */ memcpy( abyHeader + 22, &nShortTemp, 2 ); nShortTemp = CPL_LSBWORD16( 0 ); /* not utm */ memcpy( abyHeader + 24, &nShortTemp, 2 ); nShortTemp = CPL_LSBWORD16( -2 ); /* datum unknown */ memcpy( abyHeader + 26, &nShortTemp, 2 ); /* -------------------------------------------------------------------- */ /* Set dummy extents. */ /* -------------------------------------------------------------------- */ double dfLeft = 0.0; double dfRight = nXSize; double dfTop = nYSize; double dfBottom = 0.0; memcpy( abyHeader + 28, &dfLeft, 8 ); memcpy( abyHeader + 36, &dfRight, 8 ); memcpy( abyHeader + 44, &dfBottom, 8 ); memcpy( abyHeader + 52, &dfTop, 8 ); CPL_LSBPTR64( abyHeader + 28 ); CPL_LSBPTR64( abyHeader + 36 ); CPL_LSBPTR64( abyHeader + 44 ); CPL_LSBPTR64( abyHeader + 52 ); /* -------------------------------------------------------------------- */ /* Set dummy scale. */ /* -------------------------------------------------------------------- */ float fScale = 1.0; memcpy( abyHeader + 62, &fScale, 4 ); CPL_LSBPTR32( abyHeader + 62 ); /* -------------------------------------------------------------------- */ /* Write to disk. */ /* -------------------------------------------------------------------- */ if( VSIFWriteL( (void *) abyHeader, 256, 1, fp ) != 1 || VSIFSeekL( fp, (GDALGetDataTypeSize(eType)/8) * nXSize * (vsi_l_offset)nYSize - 1, SEEK_CUR ) != 0 || VSIFWriteL( abyHeader+255, 1, 1, fp ) != 1 ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to extent file to its full size, out of disk space?" ); CPL_IGNORE_RET_VAL(VSIFCloseL( fp )); VSIUnlink( pszFilename ); return NULL; } if( VSIFCloseL( fp ) != 0 ) { CPLError( CE_Failure, CPLE_FileIO, "Failed to extent file to its full size, out of disk space?" ); VSIUnlink( pszFilename ); return NULL; } return (GDALDataset *) GDALOpen( pszFilename, GA_Update ); }
GDALDataset *BTDataset::Open( GDALOpenInfo * poOpenInfo ) { /* -------------------------------------------------------------------- */ /* Verify that this is some form of binterr file. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->nHeaderBytes < 256) return NULL; if( !STARTS_WITH((const char *) poOpenInfo->pabyHeader, "binterr") ) return NULL; /* -------------------------------------------------------------------- */ /* Create the dataset. */ /* -------------------------------------------------------------------- */ BTDataset *poDS = new BTDataset(); memcpy( poDS->abyHeader, poOpenInfo->pabyHeader, 256 ); /* -------------------------------------------------------------------- */ /* Get the version. */ /* -------------------------------------------------------------------- */ char szVersion[4] = {}; strncpy( szVersion, (char *) (poDS->abyHeader + 7), 3 ); szVersion[3] = '\0'; poDS->nVersionCode = static_cast<int>(CPLAtof(szVersion) * 10); /* -------------------------------------------------------------------- */ /* Extract core header information, being careful about the */ /* version. */ /* -------------------------------------------------------------------- */ GInt32 nIntTemp = 0; memcpy( &nIntTemp, poDS->abyHeader + 10, 4 ); poDS->nRasterXSize = CPL_LSBWORD32( nIntTemp ); memcpy( &nIntTemp, poDS->abyHeader + 14, 4 ); poDS->nRasterYSize = CPL_LSBWORD32( nIntTemp ); if( !GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) ) { delete poDS; return NULL; } GInt16 nDataSize = 0; memcpy( &nDataSize, poDS->abyHeader+18, 2 ); nDataSize = CPL_LSBWORD16( nDataSize ); GDALDataType eType = GDT_Unknown; if( poDS->abyHeader[20] != 0 && nDataSize == 4 ) eType = GDT_Float32; else if( poDS->abyHeader[20] == 0 && nDataSize == 4 ) eType = GDT_Int32; else if( poDS->abyHeader[20] == 0 && nDataSize == 2 ) eType = GDT_Int16; else { CPLError( CE_Failure, CPLE_AppDefined, ".bt file data type unknown, got datasize=%d.", nDataSize ); delete poDS; return NULL; } /* rcg, apr 7/06: read offset 62 for vert. units. If zero, assume 1.0 as per spec. */ memcpy( &poDS->m_fVscale, poDS->abyHeader + 62, 4 ); CPL_LSBPTR32(&poDS->m_fVscale); if(poDS->m_fVscale == 0.0f) poDS->m_fVscale = 1.0f; /* -------------------------------------------------------------------- */ /* Try to read a .prj file if it is indicated. */ /* -------------------------------------------------------------------- */ OGRSpatialReference oSRS; if( poDS->nVersionCode >= 12 && poDS->abyHeader[60] != 0 ) { const char *pszPrjFile = CPLResetExtension( poOpenInfo->pszFilename, "prj" ); VSILFILE *fp = VSIFOpenL( pszPrjFile, "rt" ); if( fp != NULL ) { const int nBufMax = 10000; char *pszBuffer = static_cast<char *>(CPLMalloc(nBufMax)); const int nBytes = static_cast<int>(VSIFReadL( pszBuffer, 1, nBufMax-1, fp )); CPL_IGNORE_RET_VAL(VSIFCloseL( fp )); pszBuffer[nBytes] = '\0'; char *pszBufPtr = pszBuffer; if( oSRS.importFromWkt( &pszBufPtr ) != OGRERR_NONE ) { CPLError( CE_Warning, CPLE_AppDefined, "Unable to parse .prj file, " "coordinate system missing." ); } CPLFree( pszBuffer ); } } /* -------------------------------------------------------------------- */ /* If we didn't find a .prj file, try to use internal info. */ /* -------------------------------------------------------------------- */ if( oSRS.GetRoot() == NULL ) { GInt16 nUTMZone = 0; memcpy( &nUTMZone, poDS->abyHeader + 24, 2 ); nUTMZone = CPL_LSBWORD16( nUTMZone ); GInt16 nDatum = 0; memcpy( &nDatum, poDS->abyHeader + 26, 2 ); nDatum = CPL_LSBWORD16( nDatum ); GInt16 nHUnits = 0; memcpy( &nHUnits, poDS->abyHeader + 22, 2 ); nHUnits = CPL_LSBWORD16( nHUnits ); if( nUTMZone != 0 ) oSRS.SetUTM( std::abs(static_cast<int>(nUTMZone)), nUTMZone > 0 ); else if( nHUnits != 0 ) oSRS.SetLocalCS( "Unknown" ); if( nHUnits == 1 ) oSRS.SetLinearUnits( SRS_UL_METER, 1.0 ); else if( nHUnits == 2 ) oSRS.SetLinearUnits( SRS_UL_FOOT, CPLAtof(SRS_UL_FOOT_CONV) ); else if( nHUnits == 3 ) oSRS.SetLinearUnits( SRS_UL_US_FOOT, CPLAtof(SRS_UL_US_FOOT_CONV) ); // Translate some of the more obvious old USGS datum codes if( nDatum == 0 ) nDatum = 6201; else if( nDatum == 1 ) nDatum = 6209; else if( nDatum == 2 ) nDatum = 6210; else if( nDatum == 3 ) nDatum = 6202; else if( nDatum == 4 ) nDatum = 6203; else if( nDatum == 6 ) nDatum = 6222; else if( nDatum == 7 ) nDatum = 6230; else if( nDatum == 13 ) nDatum = 6267; else if( nDatum == 14 ) nDatum = 6269; else if( nDatum == 17 ) nDatum = 6277; else if( nDatum == 19 ) nDatum = 6284; else if( nDatum == 21 ) nDatum = 6301; else if( nDatum == 22 ) nDatum = 6322; else if( nDatum == 23 ) nDatum = 6326; if( !oSRS.IsLocal() ) { if( nDatum >= 6000 ) { char szName[32]; snprintf( szName, sizeof(szName), "EPSG:%d", nDatum-2000 ); oSRS.SetWellKnownGeogCS( szName ); } else oSRS.SetWellKnownGeogCS( "WGS84" ); } } /* -------------------------------------------------------------------- */ /* Convert coordinate system back to WKT. */ /* -------------------------------------------------------------------- */ if( oSRS.GetRoot() != NULL ) oSRS.exportToWkt( &poDS->pszProjection ); /* -------------------------------------------------------------------- */ /* Get georeferencing bounds. */ /* -------------------------------------------------------------------- */ if( poDS->nVersionCode >= 11 ) { double dfLeft = 0.0; memcpy( &dfLeft, poDS->abyHeader + 28, 8 ); CPL_LSBPTR64( &dfLeft ); double dfRight = 0.0; memcpy( &dfRight, poDS->abyHeader + 36, 8 ); CPL_LSBPTR64( &dfRight ); double dfBottom = 0.0; memcpy( &dfBottom, poDS->abyHeader + 44, 8 ); CPL_LSBPTR64( &dfBottom ); double dfTop = 0.0; memcpy( &dfTop, poDS->abyHeader + 52, 8 ); CPL_LSBPTR64( &dfTop ); poDS->adfGeoTransform[0] = dfLeft; poDS->adfGeoTransform[1] = (dfRight - dfLeft) / poDS->nRasterXSize; poDS->adfGeoTransform[2] = 0.0; poDS->adfGeoTransform[3] = dfTop; poDS->adfGeoTransform[4] = 0.0; poDS->adfGeoTransform[5] = (dfBottom - dfTop) / poDS->nRasterYSize; poDS->bGeoTransformValid = TRUE; } /* -------------------------------------------------------------------- */ /* Re-open the file with the desired access. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->eAccess == GA_Update ) poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb+" ); else poDS->fpImage = VSIFOpenL( poOpenInfo->pszFilename, "rb" ); if( poDS->fpImage == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "Failed to re-open %s within BT driver.\n", poOpenInfo->pszFilename ); delete poDS; return NULL; } poDS->eAccess = poOpenInfo->eAccess; /* -------------------------------------------------------------------- */ /* Create band information objects */ /* -------------------------------------------------------------------- */ poDS->SetBand( 1, new BTRasterBand( poDS, poDS->fpImage, eType ) ); #ifdef notdef poDS->bGeoTransformValid = GDALReadWorldFile( poOpenInfo->pszFilename, ".wld", poDS->adfGeoTransform ); #endif /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription( poOpenInfo->pszFilename ); poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Check for overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename ); return poDS; }
CPLErr BTDataset::SetProjection( const char *pszNewProjection ) { CPLErr eErr = CE_None; CPLFree( pszProjection ); pszProjection = CPLStrdup( pszNewProjection ); bHeaderModified = TRUE; /* -------------------------------------------------------------------- */ /* Parse projection. */ /* -------------------------------------------------------------------- */ OGRSpatialReference oSRS( pszProjection ); GInt16 nShortTemp = 0; /* -------------------------------------------------------------------- */ /* Linear units. */ /* -------------------------------------------------------------------- */ if( oSRS.IsGeographic() ) { // nShortTemp = 0; } else { const double dfLinear = oSRS.GetLinearUnits(); if( std::abs(dfLinear - 0.3048) < 0.0000001 ) nShortTemp = 2; else if( std::abs(dfLinear - CPLAtof(SRS_UL_US_FOOT_CONV)) < 0.00000001 ) nShortTemp = 3; else nShortTemp = 1; } nShortTemp = CPL_LSBWORD16( 1 ); memcpy( abyHeader + 22, &nShortTemp, 2 ); /* -------------------------------------------------------------------- */ /* UTM Zone */ /* -------------------------------------------------------------------- */ int bNorth = FALSE; nShortTemp = (GInt16) oSRS.GetUTMZone( &bNorth ); if( bNorth ) nShortTemp = -nShortTemp; nShortTemp = CPL_LSBWORD16( nShortTemp ); memcpy( abyHeader + 24, &nShortTemp, 2 ); /* -------------------------------------------------------------------- */ /* Datum */ /* -------------------------------------------------------------------- */ if( oSRS.GetAuthorityName( "GEOGCS|DATUM" ) != NULL && EQUAL(oSRS.GetAuthorityName( "GEOGCS|DATUM" ),"EPSG") ) nShortTemp = static_cast<GInt16>( atoi(oSRS.GetAuthorityCode( "GEOGCS|DATUM" )) + 2000); else nShortTemp = -2; nShortTemp = CPL_LSBWORD16( nShortTemp ); /* datum unknown */ memcpy( abyHeader + 26, &nShortTemp, 2 ); /* -------------------------------------------------------------------- */ /* Write out the projection to a .prj file. */ /* -------------------------------------------------------------------- */ const char *pszPrjFile = CPLResetExtension( GetDescription(), "prj" ); VSILFILE * fp = VSIFOpenL( pszPrjFile, "wt" ); if( fp != NULL ) { CPL_IGNORE_RET_VAL(VSIFPrintfL( fp, "%s\n", pszProjection )); CPL_IGNORE_RET_VAL(VSIFCloseL( fp )); abyHeader[60] = 1; } else { CPLError( CE_Failure, CPLE_AppDefined, "Unable to write out .prj file." ); eErr = CE_Failure; } return eErr; }
CPLErr GSBGDataset::WriteHeader( VSILFILE *fp, GInt16 nXSize, GInt16 nYSize, double dfMinX, double dfMaxX, double dfMinY, double dfMaxY, double dfMinZ, double dfMaxZ ) { if( VSIFSeekL( fp, 0, SEEK_SET ) != 0 ) { CPLError( CE_Failure, CPLE_FileIO, "Unable to seek to start of grid file.\n" ); return CE_Failure; } if( VSIFWriteL( (void *)"DSBB", 1, 4, fp ) != 4 ) { CPLError( CE_Failure, CPLE_FileIO, "Unable to write signature to grid file.\n" ); return CE_Failure; } GInt16 nTemp = CPL_LSBWORD16(nXSize); if( VSIFWriteL( (void *)&nTemp, 2, 1, fp ) != 1 ) { CPLError( CE_Failure, CPLE_FileIO, "Unable to write raster X size to grid file.\n" ); return CE_Failure; } nTemp = CPL_LSBWORD16(nYSize); if( VSIFWriteL( (void *)&nTemp, 2, 1, fp ) != 1 ) { CPLError( CE_Failure, CPLE_FileIO, "Unable to write raster Y size to grid file.\n" ); return CE_Failure; } double dfTemp = dfMinX; CPL_LSBPTR64( &dfTemp ); if( VSIFWriteL( (void *)&dfTemp, 8, 1, fp ) != 1 ) { CPLError( CE_Failure, CPLE_FileIO, "Unable to write minimum X value to grid file.\n" ); return CE_Failure; } dfTemp = dfMaxX; CPL_LSBPTR64( &dfTemp ); if( VSIFWriteL( (void *)&dfTemp, 8, 1, fp ) != 1 ) { CPLError( CE_Failure, CPLE_FileIO, "Unable to write maximum X value to grid file.\n" ); return CE_Failure; } dfTemp = dfMinY; CPL_LSBPTR64( &dfTemp ); if( VSIFWriteL( (void *)&dfTemp, 8, 1, fp ) != 1 ) { CPLError( CE_Failure, CPLE_FileIO, "Unable to write minimum Y value to grid file.\n" ); return CE_Failure; } dfTemp = dfMaxY; CPL_LSBPTR64( &dfTemp ); if( VSIFWriteL( (void *)&dfTemp, 8, 1, fp ) != 1 ) { CPLError( CE_Failure, CPLE_FileIO, "Unable to write maximum Y value to grid file.\n" ); return CE_Failure; } dfTemp = dfMinZ; CPL_LSBPTR64( &dfTemp ); if( VSIFWriteL( (void *)&dfTemp, 8, 1, fp ) != 1 ) { CPLError( CE_Failure, CPLE_FileIO, "Unable to write minimum Z value to grid file.\n" ); return CE_Failure; } dfTemp = dfMaxZ; CPL_LSBPTR64( &dfTemp ); if( VSIFWriteL( (void *)&dfTemp, 8, 1, fp ) != 1 ) { CPLError( CE_Failure, CPLE_FileIO, "Unable to write maximum Z value to grid file.\n" ); return CE_Failure; } return CE_None; }
GDALDataset *GSBGDataset::Open( GDALOpenInfo * poOpenInfo ) { if( !Identify(poOpenInfo) ) { return NULL; } /* -------------------------------------------------------------------- */ /* Create a corresponding GDALDataset. */ /* -------------------------------------------------------------------- */ GSBGDataset *poDS = new GSBGDataset(); /* -------------------------------------------------------------------- */ /* Open file with large file API. */ /* -------------------------------------------------------------------- */ poDS->eAccess = poOpenInfo->eAccess; if( poOpenInfo->eAccess == GA_ReadOnly ) poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "rb" ); else poDS->fp = VSIFOpenL( poOpenInfo->pszFilename, "r+b" ); if( poDS->fp == NULL ) { delete poDS; CPLError( CE_Failure, CPLE_OpenFailed, "VSIFOpenL(%s) failed unexpectedly.", poOpenInfo->pszFilename ); return NULL; } /* -------------------------------------------------------------------- */ /* Read the header. */ /* -------------------------------------------------------------------- */ if( VSIFSeekL( poDS->fp, 4, SEEK_SET ) != 0 ) { delete poDS; CPLError( CE_Failure, CPLE_FileIO, "Unable to seek to start of grid file header.\n" ); return NULL; } /* Parse number of X axis grid rows */ GInt16 nTemp; if( VSIFReadL( (void *)&nTemp, 2, 1, poDS->fp ) != 1 ) { delete poDS; CPLError( CE_Failure, CPLE_FileIO, "Unable to read raster X size.\n" ); return NULL; } poDS->nRasterXSize = CPL_LSBWORD16( nTemp ); if( VSIFReadL( (void *)&nTemp, 2, 1, poDS->fp ) != 1 ) { delete poDS; CPLError( CE_Failure, CPLE_FileIO, "Unable to read raster Y size.\n" ); return NULL; } poDS->nRasterYSize = CPL_LSBWORD16( nTemp ); if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize)) { delete poDS; return NULL; } /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ GSBGRasterBand *poBand = new GSBGRasterBand( poDS, 1 ); double dfTemp; if( VSIFReadL( (void *)&dfTemp, 8, 1, poDS->fp ) != 1 ) { delete poDS; delete poBand; CPLError( CE_Failure, CPLE_FileIO, "Unable to read minimum X value.\n" ); return NULL; } CPL_LSBPTR64( &dfTemp ); poBand->dfMinX = dfTemp; if( VSIFReadL( (void *)&dfTemp, 8, 1, poDS->fp ) != 1 ) { delete poDS; delete poBand; CPLError( CE_Failure, CPLE_FileIO, "Unable to read maximum X value.\n" ); return NULL; } CPL_LSBPTR64( &dfTemp ); poBand->dfMaxX = dfTemp; if( VSIFReadL( (void *)&dfTemp, 8, 1, poDS->fp ) != 1 ) { delete poDS; delete poBand; CPLError( CE_Failure, CPLE_FileIO, "Unable to read minimum Y value.\n" ); return NULL; } CPL_LSBPTR64( &dfTemp ); poBand->dfMinY = dfTemp; if( VSIFReadL( (void *)&dfTemp, 8, 1, poDS->fp ) != 1 ) { delete poDS; delete poBand; CPLError( CE_Failure, CPLE_FileIO, "Unable to read maximum Y value.\n" ); return NULL; } CPL_LSBPTR64( &dfTemp ); poBand->dfMaxY = dfTemp; if( VSIFReadL( (void *)&dfTemp, 8, 1, poDS->fp ) != 1 ) { delete poDS; delete poBand; CPLError( CE_Failure, CPLE_FileIO, "Unable to read minimum Z value.\n" ); return NULL; } CPL_LSBPTR64( &dfTemp ); poBand->dfMinZ = dfTemp; if( VSIFReadL( (void *)&dfTemp, 8, 1, poDS->fp ) != 1 ) { delete poDS; delete poBand; CPLError( CE_Failure, CPLE_FileIO, "Unable to read maximum Z value.\n" ); return NULL; } CPL_LSBPTR64( &dfTemp ); poBand->dfMaxZ = dfTemp; poDS->SetBand( 1, poBand ); /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription( poOpenInfo->pszFilename ); poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Check for external overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles() ); return poDS; }
void CALSDataset::WriteLEInt16( VSILFILE* fp, GInt16 nVal ) { nVal = CPL_LSBWORD16(nVal); VSIFWriteL(&nVal, 1, 2, fp); }