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; }
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; }
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; }
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; }
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 ) ); }
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; }
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( §ionLength, 1, sizeof(sectionLength), fp); CPL_MSBPTR32( §ionLength ); 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; }
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; }
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 ); }
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; }