GDALDataset *ELASDataset::Open( GDALOpenInfo * poOpenInfo ) { /* -------------------------------------------------------------------- */ /* First we check to see if the file has the expected header */ /* bytes. */ /* -------------------------------------------------------------------- */ if( poOpenInfo->nHeaderBytes < 256 ) return NULL; if( CPL_MSBWORD32(*((GInt32 *) (poOpenInfo->pabyHeader+0))) != 1024 || CPL_MSBWORD32(*((GInt32 *) (poOpenInfo->pabyHeader+28))) != 4321 ) { return NULL; } /* -------------------------------------------------------------------- */ /* Create a corresponding GDALDataset. */ /* -------------------------------------------------------------------- */ ELASDataset *poDS; const char *pszAccess; if( poOpenInfo->eAccess == GA_Update ) pszAccess = "r+b"; else pszAccess = "rb"; poDS = new ELASDataset(); poDS->fp = VSIFOpen( poOpenInfo->pszFilename, pszAccess ); if( poDS->fp == NULL ) { CPLError( CE_Failure, CPLE_OpenFailed, "Attempt to open `%s' with acces `%s' failed.\n", poOpenInfo->pszFilename, pszAccess ); delete poDS; return NULL; } poDS->eAccess = poOpenInfo->eAccess; /* -------------------------------------------------------------------- */ /* Read the header information. */ /* -------------------------------------------------------------------- */ poDS->bHeaderModified = FALSE; if( VSIFRead( &(poDS->sHeader), 1024, 1, poDS->fp ) != 1 ) { CPLError( CE_Failure, CPLE_FileIO, "Attempt to read 1024 byte header filed on file %s\n", poOpenInfo->pszFilename ); return NULL; } /* -------------------------------------------------------------------- */ /* Extract information of interest from the header. */ /* -------------------------------------------------------------------- */ int nStart, nEnd, nELASDataType, nBytesPerSample; poDS->nLineOffset = CPL_MSBWORD32( poDS->sHeader.NBPR ); nStart = CPL_MSBWORD32( poDS->sHeader.IL ); nEnd = CPL_MSBWORD32( poDS->sHeader.LL ); poDS->nRasterYSize = nEnd - nStart + 1; nStart = CPL_MSBWORD32( poDS->sHeader.IE ); nEnd = CPL_MSBWORD32( poDS->sHeader.LE ); poDS->nRasterXSize = nEnd - nStart + 1; poDS->nBands = CPL_MSBWORD32( poDS->sHeader.NC ); if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) || !GDALCheckBandCount(poDS->nBands, FALSE)) { delete poDS; return NULL; } nELASDataType = (poDS->sHeader.IH19[2] & 0x7e) >> 2; nBytesPerSample = poDS->sHeader.IH19[3]; if( nELASDataType == 0 && nBytesPerSample == 1 ) poDS->eRasterDataType = GDT_Byte; else if( nELASDataType == 1 && nBytesPerSample == 1 ) poDS->eRasterDataType = GDT_Byte; else if( nELASDataType == 16 && nBytesPerSample == 4 ) poDS->eRasterDataType = GDT_Float32; else if( nELASDataType == 17 && nBytesPerSample == 8 ) poDS->eRasterDataType = GDT_Float64; else { delete poDS; CPLError( CE_Failure, CPLE_AppDefined, "Unrecognised image data type %d, with BytesPerSample=%d.\n", nELASDataType, nBytesPerSample ); return NULL; } /* -------------------------------------------------------------------- */ /* Band offsets are always multiples of 256 within a multi-band */ /* scanline of data. */ /* -------------------------------------------------------------------- */ poDS->nBandOffset = (poDS->nRasterXSize * GDALGetDataTypeSize(poDS->eRasterDataType)/8); if( poDS->nBandOffset % 256 != 0 ) { poDS->nBandOffset = poDS->nBandOffset - (poDS->nBandOffset % 256) + 256; } /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ int iBand; for( iBand = 0; iBand < poDS->nBands; iBand++ ) { poDS->SetBand( iBand+1, new ELASRasterBand( poDS, iBand+1 ) ); } /* -------------------------------------------------------------------- */ /* Extract the projection coordinates, if present. */ /* -------------------------------------------------------------------- */ if( poDS->sHeader.XOffset != 0 ) { CPL_MSBPTR32(&(poDS->sHeader.XPixSize)); CPL_MSBPTR32(&(poDS->sHeader.YPixSize)); poDS->adfGeoTransform[0] = (GInt32) CPL_MSBWORD32(poDS->sHeader.XOffset); poDS->adfGeoTransform[1] = poDS->sHeader.XPixSize; poDS->adfGeoTransform[2] = 0.0; poDS->adfGeoTransform[3] = (GInt32) CPL_MSBWORD32(poDS->sHeader.YOffset); poDS->adfGeoTransform[4] = 0.0; poDS->adfGeoTransform[5] = -1.0 * ABS(poDS->sHeader.YPixSize); CPL_MSBPTR32(&(poDS->sHeader.XPixSize)); CPL_MSBPTR32(&(poDS->sHeader.YPixSize)); poDS->adfGeoTransform[0] -= poDS->adfGeoTransform[1] * 0.5; poDS->adfGeoTransform[3] -= poDS->adfGeoTransform[5] * 0.5; } else { poDS->adfGeoTransform[0] = 0.0; poDS->adfGeoTransform[1] = 1.0; poDS->adfGeoTransform[2] = 0.0; poDS->adfGeoTransform[3] = 0.0; poDS->adfGeoTransform[4] = 0.0; poDS->adfGeoTransform[5] = 1.0; } /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription( poOpenInfo->pszFilename ); poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Check for external overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->papszSiblingFiles ); return( poDS ); }
GDALDataset *ELASDataset::Open( GDALOpenInfo * poOpenInfo ) { if( !Identify(poOpenInfo) || poOpenInfo->fpL == nullptr) return nullptr; /* -------------------------------------------------------------------- */ /* Create a corresponding GDALDataset. */ /* -------------------------------------------------------------------- */ ELASDataset *poDS = new ELASDataset(); poDS->eAccess = poOpenInfo->eAccess; poDS->fp = poOpenInfo->fpL; poOpenInfo->fpL = nullptr; /* -------------------------------------------------------------------- */ /* Read the header information. */ /* -------------------------------------------------------------------- */ poDS->bHeaderModified = FALSE; if( VSIFReadL( &(poDS->sHeader), 1024, 1, poDS->fp ) != 1 ) { CPLError( CE_Failure, CPLE_FileIO, "Attempt to read 1024 byte header filed on file %s\n", poOpenInfo->pszFilename ); delete poDS; return nullptr; } /* -------------------------------------------------------------------- */ /* Extract information of interest from the header. */ /* -------------------------------------------------------------------- */ poDS->nLineOffset = CPL_MSBWORD32( poDS->sHeader.NBPR ); int nStart = CPL_MSBWORD32( poDS->sHeader.IL ); int nEnd = CPL_MSBWORD32( poDS->sHeader.LL ); GIntBig nDiff = static_cast<GIntBig>(nEnd) - nStart + 1; if( nDiff <= 0 || nDiff > std::numeric_limits<int>::max() ) { delete poDS; return nullptr; } poDS->nRasterYSize = static_cast<int>(nDiff); nStart = CPL_MSBWORD32( poDS->sHeader.IE ); nEnd = CPL_MSBWORD32( poDS->sHeader.LE ); nDiff = static_cast<GIntBig>(nEnd) - nStart + 1; if( nDiff <= 0 || nDiff > std::numeric_limits<int>::max() ) { delete poDS; return nullptr; } poDS->nRasterXSize = static_cast<int>(nDiff); poDS->nBands = CPL_MSBWORD32( poDS->sHeader.NC ); if (!GDALCheckDatasetDimensions(poDS->nRasterXSize, poDS->nRasterYSize) || !GDALCheckBandCount(poDS->nBands, FALSE)) { delete poDS; return nullptr; } const int nELASDataType = (poDS->sHeader.IH19[2] & 0x7e) >> 2; const int nBytesPerSample = poDS->sHeader.IH19[3]; if( nELASDataType == 0 && nBytesPerSample == 1 ) poDS->eRasterDataType = GDT_Byte; else if( nELASDataType == 1 && nBytesPerSample == 1 ) poDS->eRasterDataType = GDT_Byte; else if( nELASDataType == 16 && nBytesPerSample == 4 ) poDS->eRasterDataType = GDT_Float32; else if( nELASDataType == 17 && nBytesPerSample == 8 ) poDS->eRasterDataType = GDT_Float64; else { delete poDS; CPLError( CE_Failure, CPLE_AppDefined, "Unrecognized image data type %d, with BytesPerSample=%d.\n", nELASDataType, nBytesPerSample ); return nullptr; } /* -------------------------------------------------------------------- */ /* Band offsets are always multiples of 256 within a multi-band */ /* scanline of data. */ /* -------------------------------------------------------------------- */ if( GDALGetDataTypeSizeBytes(poDS->eRasterDataType) > (std::numeric_limits<int>::max() - 256) / poDS->nRasterXSize ) { delete poDS; return nullptr; } poDS->nBandOffset = (poDS->nRasterXSize * GDALGetDataTypeSizeBytes(poDS->eRasterDataType)); if( poDS->nBandOffset > 1000000 ) { VSIFSeekL( poDS->fp, 0, SEEK_END ); if( VSIFTellL( poDS->fp ) < static_cast<vsi_l_offset>(poDS->nBandOffset) ) { CPLError(CE_Failure, CPLE_FileIO, "File too short"); delete poDS; return nullptr; } } if( poDS->nBandOffset % 256 != 0 ) { poDS->nBandOffset = poDS->nBandOffset - (poDS->nBandOffset % 256) + 256; } /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ /* coverity[tainted_data] */ for( int iBand = 0; iBand < poDS->nBands; iBand++ ) { poDS->SetBand( iBand+1, new ELASRasterBand( poDS, iBand+1 ) ); } /* -------------------------------------------------------------------- */ /* Extract the projection coordinates, if present. */ /* -------------------------------------------------------------------- */ if( poDS->sHeader.XOffset != 0 ) { CPL_MSBPTR32(&(poDS->sHeader.XPixSize)); CPL_MSBPTR32(&(poDS->sHeader.YPixSize)); poDS->adfGeoTransform[0] = (GInt32) CPL_MSBWORD32(poDS->sHeader.XOffset); poDS->adfGeoTransform[1] = poDS->sHeader.XPixSize; poDS->adfGeoTransform[2] = 0.0; poDS->adfGeoTransform[3] = (GInt32) CPL_MSBWORD32(poDS->sHeader.YOffset); poDS->adfGeoTransform[4] = 0.0; poDS->adfGeoTransform[5] = -1.0 * std::abs(poDS->sHeader.YPixSize); CPL_MSBPTR32(&(poDS->sHeader.XPixSize)); CPL_MSBPTR32(&(poDS->sHeader.YPixSize)); poDS->adfGeoTransform[0] -= poDS->adfGeoTransform[1] * 0.5; poDS->adfGeoTransform[3] -= poDS->adfGeoTransform[5] * 0.5; } else { poDS->adfGeoTransform[0] = 0.0; poDS->adfGeoTransform[1] = 1.0; poDS->adfGeoTransform[2] = 0.0; poDS->adfGeoTransform[3] = 0.0; poDS->adfGeoTransform[4] = 0.0; poDS->adfGeoTransform[5] = 1.0; } /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription( poOpenInfo->pszFilename ); poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Check for external overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles() ); return poDS; }