void GDALPamRasterBand::PamInitialize() { if( psPam ) return; GDALDataset* poNonPamParentDS = GetDataset(); if( poNonPamParentDS == NULL || !(poNonPamParentDS->GetMOFlags() & GMO_PAM_CLASS) ) return; GDALPamDataset *poParentDS = (GDALPamDataset *) poNonPamParentDS; poParentDS->PamInitialize(); if( poParentDS->psPam == NULL ) return; // Often (always?) initializing our parent will have initialized us. if( psPam != NULL ) return; psPam = (GDALRasterBandPamInfo *) VSI_CALLOC_VERBOSE(sizeof(GDALRasterBandPamInfo),1); if( psPam == NULL ) return; psPam->dfScale = 1.0; psPam->poParentDS = poParentDS; psPam->dfNoDataValue = -1e10; psPam->poDefaultRAT = NULL; }
static FindFileTLS* CPLGetFindFileTLS() { int bMemoryError = FALSE; FindFileTLS* pTLSData = reinterpret_cast<FindFileTLS *>( CPLGetTLSEx( CTLS_FINDFILE, &bMemoryError ) ); if( bMemoryError ) return NULL; if (pTLSData == NULL) { pTLSData = static_cast<FindFileTLS *>( VSI_CALLOC_VERBOSE(1, sizeof(FindFileTLS) ) ); if( pTLSData == NULL ) return NULL; CPLSetTLSWithFreeFunc( CTLS_FINDFILE, pTLSData, CPLFindFileFreeTLS ); } return pTLSData; }
OGRGeometryCollection::OGRGeometryCollection( const OGRGeometryCollection& other ) : OGRGeometry(other), nGeomCount(0), papoGeoms(nullptr) { // Do not use addGeometry() as it is virtual. papoGeoms = static_cast<OGRGeometry **>( VSI_CALLOC_VERBOSE(sizeof(void*), other.nGeomCount)); if( papoGeoms ) { nGeomCount = other.nGeomCount; for( int i = 0; i < other.nGeomCount; i++ ) { papoGeoms[i] = other.papoGeoms[i]->clone(); } } }
AAIGRasterBand::AAIGRasterBand( AAIGDataset *poDSIn, int nDataStart ) : panLineOffset(nullptr) { poDS = poDSIn; nBand = 1; eDataType = poDSIn->eDataType; nBlockXSize = poDSIn->nRasterXSize; nBlockYSize = 1; panLineOffset = static_cast<GUIntBig *>( VSI_CALLOC_VERBOSE(poDSIn->nRasterYSize, sizeof(GUIntBig))); if (panLineOffset == nullptr) { return; } panLineOffset[0] = nDataStart; }
void GDALPamRasterBand::PamInitialize() { if( psPam ) return; GDALDataset* poNonPamParentDS = GetDataset(); if( poNonPamParentDS == nullptr || !(poNonPamParentDS->GetMOFlags() & GMO_PAM_CLASS) ) return; GDALPamDataset *poParentDS = dynamic_cast<GDALPamDataset *>( poNonPamParentDS ); if( poParentDS == nullptr ) { // Should never happen. CPLAssert(false); return; } poParentDS->PamInitialize(); if( poParentDS->psPam == nullptr ) return; // Often (always?) initializing our parent will have initialized us. if( psPam != nullptr ) return; psPam = static_cast<GDALRasterBandPamInfo *>( VSI_CALLOC_VERBOSE(sizeof(GDALRasterBandPamInfo), 1) ); if( psPam == nullptr ) return; psPam->dfScale = 1.0; psPam->poParentDS = poParentDS; psPam->dfNoDataValue = -1e10; psPam->poDefaultRAT = nullptr; }
GDALDataset *AAIGDataset::CommonOpen( GDALOpenInfo *poOpenInfo, GridFormat eFormat ) { if( poOpenInfo->fpL == nullptr ) return nullptr; // Create a corresponding GDALDataset. AAIGDataset *poDS = nullptr; if (eFormat == FORMAT_AAIG) poDS = new AAIGDataset(); else poDS = new GRASSASCIIDataset(); const char *pszDataTypeOption = eFormat == FORMAT_AAIG ? "AAIGRID_DATATYPE" : "GRASSASCIIGRID_DATATYPE"; const char *pszDataType = CPLGetConfigOption(pszDataTypeOption, nullptr); if( pszDataType == nullptr ) pszDataType = CSLFetchNameValue(poOpenInfo->papszOpenOptions, "DATATYPE"); if (pszDataType != nullptr) { poDS->eDataType = GDALGetDataTypeByName(pszDataType); if (!(poDS->eDataType == GDT_Int32 || poDS->eDataType == GDT_Float32 || poDS->eDataType == GDT_Float64)) { CPLError(CE_Warning, CPLE_NotSupported, "Unsupported value for %s : %s", pszDataTypeOption, pszDataType); poDS->eDataType = GDT_Int32; pszDataType = nullptr; } } // Parse the header. if (!poDS->ParseHeader((const char *)poOpenInfo->pabyHeader, pszDataType)) { delete poDS; return nullptr; } poDS->fp = poOpenInfo->fpL; poOpenInfo->fpL = nullptr; // Find the start of real data. int nStartOfData = 0; for( int i = 2; true; i++ ) { if( poOpenInfo->pabyHeader[i] == '\0' ) { CPLError(CE_Failure, CPLE_AppDefined, "Couldn't find data values in ASCII Grid file."); delete poDS; return nullptr; } if( poOpenInfo->pabyHeader[i - 1] == '\n' || poOpenInfo->pabyHeader[i - 2] == '\n' || poOpenInfo->pabyHeader[i - 1] == '\r' || poOpenInfo->pabyHeader[i - 2] == '\r' ) { if( !isalpha(poOpenInfo->pabyHeader[i]) && poOpenInfo->pabyHeader[i] != '\n' && poOpenInfo->pabyHeader[i] != '\r') { nStartOfData = i; // Beginning of real data found. break; } } } // Recognize the type of data. CPLAssert(nullptr != poDS->fp); if( pszDataType == nullptr && poDS->eDataType != GDT_Float32 && poDS->eDataType != GDT_Float64) { // Allocate 100K chunk + 1 extra byte for NULL character. constexpr size_t nChunkSize = 1024 * 100; GByte *pabyChunk = static_cast<GByte *>( VSI_CALLOC_VERBOSE(nChunkSize + 1, sizeof(GByte))); if (pabyChunk == nullptr) { delete poDS; return nullptr; } pabyChunk[nChunkSize] = '\0'; if( VSIFSeekL(poDS->fp, nStartOfData, SEEK_SET) < 0 ) { delete poDS; VSIFree(pabyChunk); return nullptr; } // Scan for dot in subsequent chunks of data. while( !VSIFEofL(poDS->fp) ) { CPL_IGNORE_RET_VAL(VSIFReadL(pabyChunk, nChunkSize, 1, poDS->fp)); for( int i = 0; i < static_cast<int>(nChunkSize); i++) { GByte ch = pabyChunk[i]; if (ch == '.' || ch == ',' || ch == 'e' || ch == 'E') { poDS->eDataType = GDT_Float32; break; } } } // Deallocate chunk. VSIFree(pabyChunk); } // Create band information objects. AAIGRasterBand *band = new AAIGRasterBand(poDS, nStartOfData); poDS->SetBand(1, band); if (band->panLineOffset == nullptr) { delete poDS; return nullptr; } // Try to read projection file. char *const pszDirname = CPLStrdup(CPLGetPath(poOpenInfo->pszFilename)); char *const pszBasename = CPLStrdup(CPLGetBasename(poOpenInfo->pszFilename)); poDS->osPrjFilename = CPLFormFilename(pszDirname, pszBasename, "prj"); int nRet = 0; { VSIStatBufL sStatBuf; nRet = VSIStatL(poDS->osPrjFilename, &sStatBuf); } if( nRet != 0 && VSIIsCaseSensitiveFS(poDS->osPrjFilename) ) { poDS->osPrjFilename = CPLFormFilename(pszDirname, pszBasename, "PRJ"); VSIStatBufL sStatBuf; nRet = VSIStatL(poDS->osPrjFilename, &sStatBuf); } if( nRet == 0 ) { poDS->papszPrj = CSLLoad(poDS->osPrjFilename); CPLDebug("AAIGrid", "Loaded SRS from %s", poDS->osPrjFilename.c_str()); OGRSpatialReference oSRS; if( oSRS.importFromESRI(poDS->papszPrj) == OGRERR_NONE ) { // If geographic values are in seconds, we must transform. // Is there a code for minutes too? if( oSRS.IsGeographic() && EQUAL(OSR_GDS(poDS->papszPrj, "Units", ""), "DS") ) { poDS->adfGeoTransform[0] /= 3600.0; poDS->adfGeoTransform[1] /= 3600.0; poDS->adfGeoTransform[2] /= 3600.0; poDS->adfGeoTransform[3] /= 3600.0; poDS->adfGeoTransform[4] /= 3600.0; poDS->adfGeoTransform[5] /= 3600.0; } CPLFree(poDS->pszProjection); oSRS.exportToWkt(&(poDS->pszProjection)); } } CPLFree(pszDirname); CPLFree(pszBasename); // Initialize any PAM information. poDS->SetDescription(poOpenInfo->pszFilename); poDS->TryLoadXML(); // Check for external overviews. poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename, poOpenInfo->GetSiblingFiles()); 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; }
NITFLocation* NITFReadRPFLocationTable(VSILFILE* fp, int* pnLocCount) { GUInt16 nLocSectionLength; GUInt32 nLocSectionOffset; GUInt16 iLoc; GUInt16 nLocCount; GUInt16 nLocRecordLength; GUInt32 nLocComponentAggregateLength; NITFLocation* pasLocations = NULL; int bSuccess; GUIntBig nCurOffset; if (fp == NULL || pnLocCount == NULL) return NULL; *pnLocCount = 0; nCurOffset = VSIFTellL(fp); bSuccess = TRUE; nLocSectionLength = NITFReadMSBGUInt16(fp, &bSuccess); nLocSectionOffset = NITFReadMSBGUInt32(fp, &bSuccess); if (nLocSectionOffset != 14) { CPLDebug("NITF", "Unusual location section offset : %d", nLocSectionOffset); } nLocCount = NITFReadMSBGUInt16(fp, &bSuccess); if (!bSuccess || nLocCount == 0) { return NULL; } nLocRecordLength = NITFReadMSBGUInt16(fp, &bSuccess); if (nLocRecordLength != 10) { CPLError(CE_Failure, CPLE_AppDefined, "Did not get expected record length : %d", nLocRecordLength); return NULL; } nLocComponentAggregateLength = NITFReadMSBGUInt32(fp, &bSuccess); VSIFSeekL(fp, nCurOffset + nLocSectionOffset, SEEK_SET); pasLocations = (NITFLocation *) VSI_CALLOC_VERBOSE(sizeof(NITFLocation), nLocCount); if (pasLocations == NULL) { return NULL; } /* -------------------------------------------------------------------- */ /* Process the locations. */ /* -------------------------------------------------------------------- */ for( iLoc = 0; iLoc < nLocCount; iLoc++ ) { pasLocations[iLoc].nLocId = NITFReadMSBGUInt16(fp, &bSuccess); pasLocations[iLoc].nLocSize = NITFReadMSBGUInt32(fp, &bSuccess); pasLocations[iLoc].nLocOffset = NITFReadMSBGUInt32(fp, &bSuccess); } if (!bSuccess) { CPLFree(pasLocations); return NULL; } *pnLocCount = nLocCount; return pasLocations; }
CPLErr CPL_STDCALL GDALFillNodata( GDALRasterBandH hTargetBand, GDALRasterBandH hMaskBand, double dfMaxSearchDist, CPL_UNUSED int bDeprecatedOption, int nSmoothingIterations, char **papszOptions, GDALProgressFunc pfnProgress, void * pProgressArg ) { VALIDATE_POINTER1( hTargetBand, "GDALFillNodata", CE_Failure ); const int nXSize = GDALGetRasterBandXSize(hTargetBand); const int nYSize = GDALGetRasterBandYSize(hTargetBand); if( dfMaxSearchDist == 0.0 ) dfMaxSearchDist = std::max(nXSize, nYSize) + 1; const int nMaxSearchDist = static_cast<int>(floor(dfMaxSearchDist)); // Special "x" pixel values identifying pixels as special. GDALDataType eType = GDT_UInt16; GUInt32 nNoDataVal = 65535; if( nXSize > 65533 || nYSize > 65533 ) { eType = GDT_UInt32; nNoDataVal = 4000002; } if( hMaskBand == nullptr ) hMaskBand = GDALGetMaskBand( hTargetBand ); // If there are smoothing iterations, reserve 10% of the progress for them. const double dfProgressRatio = nSmoothingIterations > 0 ? 0.9 : 1.0; const char* pszNoData = CSLFetchNameValue(papszOptions, "NODATA"); bool bHasNoData = false; float fNoData = 0.0f; if( pszNoData ) { bHasNoData = true; fNoData = static_cast<float>(CPLAtof(pszNoData)); } /* -------------------------------------------------------------------- */ /* Initialize progress counter. */ /* -------------------------------------------------------------------- */ if( pfnProgress == nullptr ) pfnProgress = GDALDummyProgress; if( !pfnProgress( 0.0, "Filling...", pProgressArg ) ) { CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" ); return CE_Failure; } /* -------------------------------------------------------------------- */ /* Determine format driver for temp work files. */ /* -------------------------------------------------------------------- */ CPLString osTmpFileDriver = CSLFetchNameValueDef( papszOptions, "TEMP_FILE_DRIVER", "GTiff"); GDALDriverH hDriver = GDALGetDriverByName(osTmpFileDriver.c_str()); if( hDriver == nullptr ) { CPLError(CE_Failure, CPLE_AppDefined, "Given driver is not registered"); return CE_Failure; } if( GDALGetMetadataItem(hDriver, GDAL_DCAP_CREATE, nullptr) == nullptr ) { CPLError(CE_Failure, CPLE_AppDefined, "Given driver is incapable of creating temp work files"); return CE_Failure; } char **papszWorkFileOptions = nullptr; if( osTmpFileDriver == "GTiff" ) { papszWorkFileOptions = CSLSetNameValue( papszWorkFileOptions, "COMPRESS", "LZW"); papszWorkFileOptions = CSLSetNameValue( papszWorkFileOptions, "BIGTIFF", "IF_SAFER"); } /* -------------------------------------------------------------------- */ /* Create a work file to hold the Y "last value" indices. */ /* -------------------------------------------------------------------- */ const CPLString osTmpFile = CPLGenerateTempFilename(""); const CPLString osYTmpFile = osTmpFile + "fill_y_work.tif"; GDALDatasetH hYDS = GDALCreate( hDriver, osYTmpFile, nXSize, nYSize, 1, eType, papszWorkFileOptions ); if( hYDS == nullptr ) { CPLError( CE_Failure, CPLE_AppDefined, "Could not create Y index work file. Check driver capabilities."); return CE_Failure; } GDALRasterBandH hYBand = GDALGetRasterBand( hYDS, 1 ); /* -------------------------------------------------------------------- */ /* Create a work file to hold the pixel value associated with */ /* the "last xy value" pixel. */ /* -------------------------------------------------------------------- */ const CPLString osValTmpFile = osTmpFile + "fill_val_work.tif"; GDALDatasetH hValDS = GDALCreate( hDriver, osValTmpFile, nXSize, nYSize, 1, GDALGetRasterDataType( hTargetBand ), papszWorkFileOptions ); if( hValDS == nullptr ) { CPLError(CE_Failure, CPLE_AppDefined, "Could not create XY value work file. Check driver capabilities."); return CE_Failure; } GDALRasterBandH hValBand = GDALGetRasterBand( hValDS, 1 ); /* -------------------------------------------------------------------- */ /* Create a mask file to make it clear what pixels can be filtered */ /* on the filtering pass. */ /* -------------------------------------------------------------------- */ const CPLString osFiltMaskTmpFile = osTmpFile + "fill_filtmask_work.tif"; GDALDatasetH hFiltMaskDS = GDALCreate( hDriver, osFiltMaskTmpFile, nXSize, nYSize, 1, GDT_Byte, papszWorkFileOptions ); if( hFiltMaskDS == nullptr ) { CPLError(CE_Failure, CPLE_AppDefined, "Could not create mask work file. Check driver capabilities."); return CE_Failure; } GDALRasterBandH hFiltMaskBand = GDALGetRasterBand( hFiltMaskDS, 1 ); /* -------------------------------------------------------------------- */ /* Allocate buffers for last scanline and this scanline. */ /* -------------------------------------------------------------------- */ GUInt32 *panLastY = static_cast<GUInt32 *>(VSI_CALLOC_VERBOSE(nXSize, sizeof(GUInt32))); GUInt32 *panThisY = static_cast<GUInt32 *>(VSI_CALLOC_VERBOSE(nXSize, sizeof(GUInt32))); GUInt32 *panTopDownY = static_cast<GUInt32 *>(VSI_CALLOC_VERBOSE(nXSize, sizeof(GUInt32))); float *pafLastValue = static_cast<float *>(VSI_CALLOC_VERBOSE(nXSize, sizeof(float))); float *pafThisValue = static_cast<float *>(VSI_CALLOC_VERBOSE(nXSize, sizeof(float))); float *pafTopDownValue = static_cast<float *>(VSI_CALLOC_VERBOSE(nXSize, sizeof(float))); float *pafScanline = static_cast<float *>(VSI_CALLOC_VERBOSE(nXSize, sizeof(float))); GByte *pabyMask = static_cast<GByte *>(VSI_CALLOC_VERBOSE(nXSize, 1)); GByte *pabyFiltMask = static_cast<GByte *>(VSI_CALLOC_VERBOSE(nXSize, 1)); CPLErr eErr = CE_None; if( panLastY == nullptr || panThisY == nullptr || panTopDownY == nullptr || pafLastValue == nullptr || pafThisValue == nullptr || pafTopDownValue == nullptr || pafScanline == nullptr || pabyMask == nullptr || pabyFiltMask == nullptr ) { eErr = CE_Failure; goto end; } for( int iX = 0; iX < nXSize; iX++ ) { panLastY[iX] = nNoDataVal; } /* ==================================================================== */ /* Make first pass from top to bottom collecting the "last */ /* known value" for each column and writing it out to the work */ /* files. */ /* ==================================================================== */ for( int iY = 0; iY < nYSize && eErr == CE_None; iY++ ) { /* -------------------------------------------------------------------- */ /* Read data and mask for this line. */ /* -------------------------------------------------------------------- */ eErr = GDALRasterIO( hMaskBand, GF_Read, 0, iY, nXSize, 1, pabyMask, nXSize, 1, GDT_Byte, 0, 0 ); if( eErr != CE_None ) break; eErr = GDALRasterIO( hTargetBand, GF_Read, 0, iY, nXSize, 1, pafScanline, nXSize, 1, GDT_Float32, 0, 0 ); if( eErr != CE_None ) break; /* -------------------------------------------------------------------- */ /* Figure out the most recent pixel for each column. */ /* -------------------------------------------------------------------- */ for( int iX = 0; iX < nXSize; iX++ ) { if( pabyMask[iX] ) { pafThisValue[iX] = pafScanline[iX]; panThisY[iX] = iY; } else if( iY <= dfMaxSearchDist + panLastY[iX] ) { pafThisValue[iX] = pafLastValue[iX]; panThisY[iX] = panLastY[iX]; } else { panThisY[iX] = nNoDataVal; } } /* -------------------------------------------------------------------- */ /* Write out best index/value to working files. */ /* -------------------------------------------------------------------- */ eErr = GDALRasterIO( hYBand, GF_Write, 0, iY, nXSize, 1, panThisY, nXSize, 1, GDT_UInt32, 0, 0 ); if( eErr != CE_None ) break; eErr = GDALRasterIO( hValBand, GF_Write, 0, iY, nXSize, 1, pafThisValue, nXSize, 1, GDT_Float32, 0, 0 ); if( eErr != CE_None ) break; /* -------------------------------------------------------------------- */ /* Flip this/last buffers. */ /* -------------------------------------------------------------------- */ std::swap(pafThisValue, pafLastValue); std::swap(panThisY, panLastY); /* -------------------------------------------------------------------- */ /* report progress. */ /* -------------------------------------------------------------------- */ if( eErr == CE_None && !pfnProgress( dfProgressRatio * (0.5*(iY+1) / static_cast<double>(nYSize)), "Filling...", pProgressArg ) ) { CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" ); eErr = CE_Failure; } } for( int iX = 0; iX < nXSize; iX++ ) { panLastY[iX] = nNoDataVal; } /* ==================================================================== */ /* Now we will do collect similar this/last information from */ /* bottom to top and use it in combination with the top to */ /* bottom search info to interpolate. */ /* ==================================================================== */ for( int iY = nYSize-1; iY >= 0 && eErr == CE_None; iY-- ) { eErr = GDALRasterIO( hMaskBand, GF_Read, 0, iY, nXSize, 1, pabyMask, nXSize, 1, GDT_Byte, 0, 0 ); if( eErr != CE_None ) break; eErr = GDALRasterIO( hTargetBand, GF_Read, 0, iY, nXSize, 1, pafScanline, nXSize, 1, GDT_Float32, 0, 0 ); if( eErr != CE_None ) break; /* -------------------------------------------------------------------- */ /* Figure out the most recent pixel for each column. */ /* -------------------------------------------------------------------- */ for( int iX = 0; iX < nXSize; iX++ ) { if( pabyMask[iX] ) { pafThisValue[iX] = pafScanline[iX]; panThisY[iX] = iY; } else if( panLastY[iX] - iY <= dfMaxSearchDist ) { pafThisValue[iX] = pafLastValue[iX]; panThisY[iX] = panLastY[iX]; } else { panThisY[iX] = nNoDataVal; } } /* -------------------------------------------------------------------- */ /* Load the last y and corresponding value from the top down pass. */ /* -------------------------------------------------------------------- */ eErr = GDALRasterIO( hYBand, GF_Read, 0, iY, nXSize, 1, panTopDownY, nXSize, 1, GDT_UInt32, 0, 0 ); if( eErr != CE_None ) break; eErr = GDALRasterIO( hValBand, GF_Read, 0, iY, nXSize, 1, pafTopDownValue, nXSize, 1, GDT_Float32, 0, 0 ); if( eErr != CE_None ) break; /* -------------------------------------------------------------------- */ /* Attempt to interpolate any pixels that are nodata. */ /* -------------------------------------------------------------------- */ memset( pabyFiltMask, 0, nXSize ); for( int iX = 0; iX < nXSize; iX++ ) { int nThisMaxSearchDist = nMaxSearchDist; // If this was a valid target - no change. if( pabyMask[iX] ) continue; // Quadrants 0:topleft, 1:bottomleft, 2:topright, 3:bottomright double adfQuadDist[4] = {}; float fQuadValue[4] = {}; for( int iQuad = 0; iQuad < 4; iQuad++ ) { adfQuadDist[iQuad] = dfMaxSearchDist + 1.0; fQuadValue[iQuad] = 0.0; } // Step left and right by one pixel searching for the closest // target value for each quadrant. for( int iStep = 0; iStep <= nThisMaxSearchDist; iStep++ ) { const int iLeftX = std::max(0, iX - iStep); const int iRightX = std::min(nXSize - 1, iX + iStep); // Top left includes current line. QUAD_CHECK(adfQuadDist[0], fQuadValue[0], iLeftX, panTopDownY[iLeftX], iX, iY, pafTopDownValue[iLeftX], nNoDataVal ); // Bottom left. QUAD_CHECK(adfQuadDist[1], fQuadValue[1], iLeftX, panLastY[iLeftX], iX, iY, pafLastValue[iLeftX], nNoDataVal ); // Top right and bottom right do no include center pixel. if( iStep == 0 ) continue; // Top right includes current line. QUAD_CHECK(adfQuadDist[2], fQuadValue[2], iRightX, panTopDownY[iRightX], iX, iY, pafTopDownValue[iRightX], nNoDataVal ); // Bottom right. QUAD_CHECK(adfQuadDist[3], fQuadValue[3], iRightX, panLastY[iRightX], iX, iY, pafLastValue[iRightX], nNoDataVal ); // Every four steps, recompute maximum distance. if( (iStep & 0x3) == 0 ) nThisMaxSearchDist = static_cast<int>(floor( std::max(std::max(adfQuadDist[0], adfQuadDist[1]), std::max(adfQuadDist[2], adfQuadDist[3])))); } double dfWeightSum = 0.0; double dfValueSum = 0.0; bool bHasSrcValues = false; for( int iQuad = 0; iQuad < 4; iQuad++ ) { if( adfQuadDist[iQuad] <= dfMaxSearchDist ) { const double dfWeight = 1.0 / adfQuadDist[iQuad]; bHasSrcValues = dfWeight != 0; if( !bHasNoData || fQuadValue[iQuad] != fNoData ) { dfWeightSum += dfWeight; dfValueSum += fQuadValue[iQuad] * dfWeight; } } } if( bHasSrcValues ) { pabyMask[iX] = 255; pabyFiltMask[iX] = 255; if( dfWeightSum > 0.0 ) pafScanline[iX] = static_cast<float>(dfValueSum / dfWeightSum); else pafScanline[iX] = fNoData; } } /* -------------------------------------------------------------------- */ /* Write out the updated data and mask information. */ /* -------------------------------------------------------------------- */ eErr = GDALRasterIO( hTargetBand, GF_Write, 0, iY, nXSize, 1, pafScanline, nXSize, 1, GDT_Float32, 0, 0 ); if( eErr != CE_None ) break; eErr = GDALRasterIO( hFiltMaskBand, GF_Write, 0, iY, nXSize, 1, pabyFiltMask, nXSize, 1, GDT_Byte, 0, 0 ); if( eErr != CE_None ) break; /* -------------------------------------------------------------------- */ /* Flip this/last buffers. */ /* -------------------------------------------------------------------- */ std::swap(pafThisValue, pafLastValue); std::swap(panThisY, panLastY); /* -------------------------------------------------------------------- */ /* report progress. */ /* -------------------------------------------------------------------- */ if( eErr == CE_None && !pfnProgress( dfProgressRatio*(0.5+0.5*(nYSize-iY) / static_cast<double>(nYSize)), "Filling...", pProgressArg) ) { CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" ); eErr = CE_Failure; } } /* ==================================================================== */ /* Now we will do iterative average filters over the */ /* interpolated values to smooth things out and make linear */ /* artifacts less obvious. */ /* ==================================================================== */ if( eErr == CE_None && nSmoothingIterations > 0 ) { // Force masks to be to flushed and recomputed. GDALFlushRasterCache( hMaskBand ); void *pScaledProgress = GDALCreateScaledProgress( dfProgressRatio, 1.0, pfnProgress, nullptr ); eErr = GDALMultiFilter( hTargetBand, hMaskBand, hFiltMaskBand, nSmoothingIterations, GDALScaledProgress, pScaledProgress ); GDALDestroyScaledProgress( pScaledProgress ); } /* -------------------------------------------------------------------- */ /* Close and clean up temporary files. Free working buffers */ /* -------------------------------------------------------------------- */ end: CPLFree(panLastY); CPLFree(panThisY); CPLFree(panTopDownY); CPLFree(pafLastValue); CPLFree(pafThisValue); CPLFree(pafTopDownValue); CPLFree(pafScanline); CPLFree(pabyMask); CPLFree(pabyFiltMask); GDALClose( hYDS ); GDALClose( hValDS ); GDALClose( hFiltMaskDS ); CSLDestroy(papszWorkFileOptions); GDALDeleteDataset( hDriver, osYTmpFile ); GDALDeleteDataset( hDriver, osValTmpFile ); GDALDeleteDataset( hDriver, osFiltMaskTmpFile ); return eErr; }
OGRErr OGRGeometryCollection::importFromWkbInternal( const unsigned char * pabyData, int nSize, int nRecLevel, OGRwkbVariant eWkbVariant, int& nBytesConsumedOut ) { nBytesConsumedOut = -1; // Arbitrary value, but certainly large enough for reasonable use cases. if( nRecLevel == 32 ) { CPLError( CE_Failure, CPLE_AppDefined, "Too many recursion levels (%d) while parsing WKB geometry.", nRecLevel ); return OGRERR_CORRUPT_DATA; } nGeomCount = 0; OGRwkbByteOrder eByteOrder = wkbXDR; int nDataOffset = 0; OGRErr eErr = importPreambleOfCollectionFromWkb( pabyData, nSize, nDataOffset, eByteOrder, 9, nGeomCount, eWkbVariant ); if( eErr != OGRERR_NONE ) return eErr; // coverity[tainted_data] papoGeoms = static_cast<OGRGeometry **>( VSI_CALLOC_VERBOSE(sizeof(void*), nGeomCount)); if( nGeomCount != 0 && papoGeoms == nullptr ) { nGeomCount = 0; return OGRERR_NOT_ENOUGH_MEMORY; } /* -------------------------------------------------------------------- */ /* Get the Geoms. */ /* -------------------------------------------------------------------- */ for( int iGeom = 0; iGeom < nGeomCount; iGeom++ ) { // Parses sub-geometry. const unsigned char* pabySubData = pabyData + nDataOffset; if( nSize < 9 && nSize != -1 ) return OGRERR_NOT_ENOUGH_DATA; OGRwkbGeometryType eSubGeomType = wkbUnknown; eErr = OGRReadWKBGeometryType( pabySubData, eWkbVariant, &eSubGeomType ); if( eErr != OGRERR_NONE ) return eErr; if( !isCompatibleSubType(eSubGeomType) ) { nGeomCount = iGeom; CPLDebug( "OGR", "Cannot add geometry of type (%d) to geometry of type (%d)", eSubGeomType, getGeometryType()); return OGRERR_CORRUPT_DATA; } OGRGeometry* poSubGeom = nullptr; int nSubGeomBytesConsumed = -1; if( OGR_GT_IsSubClassOf(eSubGeomType, wkbGeometryCollection) ) { poSubGeom = OGRGeometryFactory::createGeometry( eSubGeomType ); if( poSubGeom == nullptr ) eErr = OGRERR_FAILURE; else eErr = poSubGeom->toGeometryCollection()-> importFromWkbInternal( pabySubData, nSize, nRecLevel + 1, eWkbVariant, nSubGeomBytesConsumed ); } else { eErr = OGRGeometryFactory:: createFromWkb( pabySubData, nullptr, &poSubGeom, nSize, eWkbVariant, nSubGeomBytesConsumed ); } if( eErr != OGRERR_NONE ) { nGeomCount = iGeom; delete poSubGeom; return eErr; } papoGeoms[iGeom] = poSubGeom; if( papoGeoms[iGeom]->Is3D() ) flags |= OGR_G_3D; if( papoGeoms[iGeom]->IsMeasured() ) flags |= OGR_G_MEASURED; CPLAssert( nSubGeomBytesConsumed > 0 ); if( nSize != -1 ) { CPLAssert( nSize >= nSubGeomBytesConsumed ); nSize -= nSubGeomBytesConsumed; } nDataOffset += nSubGeomBytesConsumed; } nBytesConsumedOut = nDataOffset; return OGRERR_NONE; }
GDALDataset* SGIDataset::Open(GDALOpenInfo* poOpenInfo) { /* -------------------------------------------------------------------- */ /* First we check to see if the file has the expected header */ /* bytes. */ /* -------------------------------------------------------------------- */ if(poOpenInfo->nHeaderBytes < 12 || poOpenInfo->fpL == nullptr ) return nullptr; ImageRec tmpImage; memcpy(&tmpImage.imagic, poOpenInfo->pabyHeader + 0, 2); memcpy(&tmpImage.type, poOpenInfo->pabyHeader + 2, 1); memcpy(&tmpImage.bpc, poOpenInfo->pabyHeader + 3, 1); memcpy(&tmpImage.dim, poOpenInfo->pabyHeader + 4, 2); memcpy(&tmpImage.xsize, poOpenInfo->pabyHeader + 6, 2); memcpy(&tmpImage.ysize, poOpenInfo->pabyHeader + 8, 2); memcpy(&tmpImage.zsize, poOpenInfo->pabyHeader + 10, 2); tmpImage.Swap(); if(tmpImage.imagic != 474) return nullptr; if (tmpImage.type != 0 && tmpImage.type != 1) return nullptr; if (tmpImage.bpc != 1 && tmpImage.bpc != 2) return nullptr; if (tmpImage.dim != 1 && tmpImage.dim != 2 && tmpImage.dim != 3) return nullptr; if(tmpImage.bpc != 1) { CPLError(CE_Failure, CPLE_NotSupported, "The SGI driver only supports 1 byte channel values.\n"); return nullptr; } /* -------------------------------------------------------------------- */ /* Create a corresponding GDALDataset. */ /* -------------------------------------------------------------------- */ SGIDataset* poDS = new SGIDataset(); poDS->eAccess = poOpenInfo->eAccess; poDS->fpImage = poOpenInfo->fpL; poOpenInfo->fpL = nullptr; /* -------------------------------------------------------------------- */ /* Read pre-image data after ensuring the file is rewound. */ /* -------------------------------------------------------------------- */ VSIFSeekL(poDS->fpImage, 0, SEEK_SET); if(VSIFReadL(reinterpret_cast<void*>( &(poDS->image) ), 1, 12, poDS->fpImage) != 12) { CPLError(CE_Failure, CPLE_OpenFailed, "file read error while reading header in sgidataset.cpp"); delete poDS; return nullptr; } poDS->image.Swap(); poDS->image.file = poDS->fpImage; poDS->image.fileName = poOpenInfo->pszFilename; /* -------------------------------------------------------------------- */ /* Capture some information from the file that is of interest. */ /* -------------------------------------------------------------------- */ poDS->nRasterXSize = poDS->image.xsize; poDS->nRasterYSize = poDS->image.ysize; if (poDS->nRasterXSize <= 0 || poDS->nRasterYSize <= 0) { CPLError(CE_Failure, CPLE_OpenFailed, "Invalid image dimensions : %d x %d", poDS->nRasterXSize, poDS->nRasterYSize); delete poDS; return nullptr; } poDS->nBands = std::max(static_cast<GUInt16>(1), poDS->image.zsize); if (poDS->nBands > 256) { CPLError(CE_Failure, CPLE_OpenFailed, "Too many bands : %d", poDS->nBands); delete poDS; return nullptr; } const int numItems = (static_cast<int>( poDS->image.bpc ) == 1) ? 256 : 65536; if( poDS->image.xsize > INT_MAX / numItems ) { delete poDS; return nullptr; } poDS->image.tmpSize = poDS->image.xsize * numItems; poDS->image.tmp = (unsigned char*)VSI_CALLOC_VERBOSE(poDS->image.xsize,numItems); if (poDS->image.tmp == nullptr) { delete poDS; return nullptr; } /* -------------------------------------------------------------------- */ /* Read RLE Pointer tables. */ /* -------------------------------------------------------------------- */ if( static_cast<int>( poDS->image.type ) == 1 ) // RLE compressed { const size_t x = static_cast<size_t>(poDS->image.ysize) * poDS->nBands * sizeof(GUInt32); poDS->image.rowStart = reinterpret_cast<GUInt32*>( VSI_MALLOC2_VERBOSE(poDS->image.ysize, poDS->nBands * sizeof(GUInt32) ) ); poDS->image.rowSize = reinterpret_cast<GInt32 *>( VSI_MALLOC2_VERBOSE(poDS->image.ysize, poDS->nBands * sizeof(GUInt32) ) ); if (poDS->image.rowStart == nullptr || poDS->image.rowSize == nullptr) { delete poDS; return nullptr; } memset(poDS->image.rowStart, 0, x); memset(poDS->image.rowSize, 0, x); poDS->image.rleEnd = static_cast<GUInt32>(512 + (2 * x)); VSIFSeekL(poDS->fpImage, 512, SEEK_SET); if( VSIFReadL(poDS->image.rowStart, 1, x, poDS->image.file ) != x ) { delete poDS; CPLError(CE_Failure, CPLE_OpenFailed, "file read error while reading start positions in sgidataset.cpp"); return nullptr; } if( VSIFReadL(poDS->image.rowSize, 1, x, poDS->image.file) != x) { delete poDS; CPLError(CE_Failure, CPLE_OpenFailed, "file read error while reading row lengths in sgidataset.cpp"); return nullptr; } ConvertLong(poDS->image.rowStart, static_cast<int>(x / static_cast<int>( sizeof(GUInt32))) ); ConvertLong(reinterpret_cast<GUInt32 *>( poDS->image.rowSize ), static_cast<int>(x / static_cast<int>( sizeof(GInt32) )) ); } else // uncompressed. { poDS->image.rowStart = nullptr; poDS->image.rowSize = nullptr; } /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ for(int iBand = 0; iBand < poDS->nBands; iBand++) poDS->SetBand(iBand+1, new SGIRasterBand(poDS, iBand+1)); /* -------------------------------------------------------------------- */ /* Check for world file. */ /* -------------------------------------------------------------------- */ poDS->bGeoTransformValid = GDALReadWorldFile(poOpenInfo->pszFilename, ".wld", poDS->adfGeoTransform); /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription(poOpenInfo->pszFilename); poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Check for overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename ); return poDS; }
CPLErr MEMDataset::AddBand( GDALDataType eType, char **papszOptions ) { const int nBandId = GetRasterCount() + 1; const GSpacing nPixelSize = GDALGetDataTypeSizeBytes(eType); /* -------------------------------------------------------------------- */ /* Do we need to allocate the memory ourselves? This is the */ /* simple case. */ /* -------------------------------------------------------------------- */ if( CSLFetchNameValue( papszOptions, "DATAPOINTER" ) == NULL ) { const GSpacing nTmp = nPixelSize * GetRasterXSize(); GByte *pData = NULL; #if SIZEOF_VOIDP == 4 if( nTmp > INT_MAX ) pData = NULL; else #endif pData = reinterpret_cast<GByte *>( VSI_CALLOC_VERBOSE((size_t)nTmp, GetRasterYSize() ) ); if( pData == NULL ) { return CE_Failure; } SetBand( nBandId, new MEMRasterBand( this, nBandId, pData, eType, nPixelSize, nPixelSize * GetRasterXSize(), TRUE ) ); return CE_None; } /* -------------------------------------------------------------------- */ /* Get layout of memory and other flags. */ /* -------------------------------------------------------------------- */ const char *pszDataPointer = CSLFetchNameValue(papszOptions, "DATAPOINTER"); GByte *pData = reinterpret_cast<GByte *>( CPLScanPointer( pszDataPointer, static_cast<int>(strlen(pszDataPointer)) ) ); const char *pszOption = CSLFetchNameValue(papszOptions, "PIXELOFFSET"); GSpacing nPixelOffset; if( pszOption == NULL ) nPixelOffset = nPixelSize; else nPixelOffset = CPLAtoGIntBig(pszOption); pszOption = CSLFetchNameValue(papszOptions, "LINEOFFSET"); GSpacing nLineOffset; if( pszOption == NULL ) nLineOffset = GetRasterXSize() * static_cast<size_t>( nPixelOffset ); else nLineOffset = CPLAtoGIntBig(pszOption); SetBand( nBandId, new MEMRasterBand( this, nBandId, pData, eType, nPixelOffset, nLineOffset, FALSE ) ); return CE_None; }
GDALDataset *MEMDataset::Create( const char * /* pszFilename */, int nXSize, int nYSize, int nBands, GDALDataType eType, char **papszOptions ) { /* -------------------------------------------------------------------- */ /* Do we want a pixel interleaved buffer? I mostly care about */ /* this to test pixel interleaved IO in other contexts, but it */ /* could be useful to create a directly accessible buffer for */ /* some apps. */ /* -------------------------------------------------------------------- */ bool bPixelInterleaved = false; const char *pszOption = CSLFetchNameValue( papszOptions, "INTERLEAVE" ); if( pszOption && EQUAL(pszOption,"PIXEL") ) bPixelInterleaved = true; /* -------------------------------------------------------------------- */ /* First allocate band data, verifying that we can get enough */ /* memory. */ /* -------------------------------------------------------------------- */ const int nWordSize = GDALGetDataTypeSize(eType) / 8; if( nBands > 0 && nWordSize > 0 && (nBands > INT_MAX / nWordSize || (GIntBig)nXSize * nYSize > GINTBIG_MAX / (nWordSize * nBands)) ) { CPLError( CE_Failure, CPLE_OutOfMemory, "Multiplication overflow"); return NULL; } const GUIntBig nGlobalBigSize = static_cast<GUIntBig>(nWordSize) * nBands * nXSize * nYSize; const size_t nGlobalSize = static_cast<size_t>(nGlobalBigSize); #if SIZEOF_VOIDP == 4 if( static_cast<GUIntBig>(nGlobalSize) != nGlobalBigSize ) { CPLError( CE_Failure, CPLE_OutOfMemory, "Cannot allocate " CPL_FRMT_GUIB " bytes on this platform.", nGlobalBigSize ); return NULL; } #endif std::vector<GByte*> apbyBandData; bool bAllocOK = true; if( bPixelInterleaved ) { apbyBandData.push_back( reinterpret_cast<GByte *>( VSI_CALLOC_VERBOSE( 1, nGlobalSize ) ) ); if( apbyBandData[0] == NULL ) bAllocOK = FALSE; else { for( int iBand = 1; iBand < nBands; iBand++ ) apbyBandData.push_back( apbyBandData[0] + iBand * nWordSize ); } } else { for( int iBand = 0; iBand < nBands; iBand++ ) { apbyBandData.push_back( reinterpret_cast<GByte *>( VSI_CALLOC_VERBOSE( 1, static_cast<size_t>(nWordSize) * nXSize * nYSize ) ) ); if( apbyBandData[iBand] == NULL ) { bAllocOK = FALSE; break; } } } if( !bAllocOK ) { for( int iBand = 0; iBand < static_cast<int>( apbyBandData.size() ); iBand++ ) { if( apbyBandData[iBand] ) VSIFree( apbyBandData[iBand] ); } return NULL; } /* -------------------------------------------------------------------- */ /* Create the new GTiffDataset object. */ /* -------------------------------------------------------------------- */ MEMDataset *poDS = new MEMDataset(); poDS->nRasterXSize = nXSize; poDS->nRasterYSize = nYSize; poDS->eAccess = GA_Update; const char *pszPixelType = CSLFetchNameValue( papszOptions, "PIXELTYPE" ); if( pszPixelType && EQUAL(pszPixelType, "SIGNEDBYTE") ) poDS->SetMetadataItem( "PIXELTYPE", "SIGNEDBYTE", "IMAGE_STRUCTURE" ); if( bPixelInterleaved ) poDS->SetMetadataItem( "INTERLEAVE", "PIXEL", "IMAGE_STRUCTURE" ); /* -------------------------------------------------------------------- */ /* Create band information objects. */ /* -------------------------------------------------------------------- */ for( int iBand = 0; iBand < nBands; iBand++ ) { MEMRasterBand *poNewBand = NULL; if( bPixelInterleaved ) poNewBand = new MEMRasterBand( poDS, iBand+1, apbyBandData[iBand], eType, nWordSize * nBands, 0, iBand == 0 ); else poNewBand = new MEMRasterBand( poDS, iBand+1, apbyBandData[iBand], eType, 0, 0, TRUE ); poDS->SetBand( iBand+1, poNewBand ); } /* -------------------------------------------------------------------- */ /* Try to return a regular handle on the file. */ /* -------------------------------------------------------------------- */ return poDS; }
static int GeoLocGenerateBackMap( GDALGeoLocTransformInfo *psTransform ) { int nXSize = psTransform->nGeoLocXSize; int nYSize = psTransform->nGeoLocYSize; int nMaxIter = 3; /* -------------------------------------------------------------------- */ /* Scan forward map for lat/long extents. */ /* -------------------------------------------------------------------- */ double dfMinX=0, dfMaxX=0, dfMinY=0, dfMaxY=0; int i, bInit = FALSE; for( i = nXSize * nYSize - 1; i >= 0; i-- ) { if( !psTransform->bHasNoData || psTransform->padfGeoLocX[i] != psTransform->dfNoDataX ) { if( bInit ) { dfMinX = MIN(dfMinX,psTransform->padfGeoLocX[i]); dfMaxX = MAX(dfMaxX,psTransform->padfGeoLocX[i]); dfMinY = MIN(dfMinY,psTransform->padfGeoLocY[i]); dfMaxY = MAX(dfMaxY,psTransform->padfGeoLocY[i]); } else { bInit = TRUE; dfMinX = dfMaxX = psTransform->padfGeoLocX[i]; dfMinY = dfMaxY = psTransform->padfGeoLocY[i]; } } } /* -------------------------------------------------------------------- */ /* Decide on resolution for backmap. We aim for slightly */ /* higher resolution than the source but we can't easily */ /* establish how much dead space there is in the backmap, so it */ /* is approximate. */ /* -------------------------------------------------------------------- */ double dfTargetPixels = (nXSize * nYSize * 1.3); double dfPixelSize = sqrt((dfMaxX - dfMinX) * (dfMaxY - dfMinY) / dfTargetPixels); int nBMXSize, nBMYSize; nBMYSize = psTransform->nBackMapHeight = (int) ((dfMaxY - dfMinY) / dfPixelSize + 1); nBMXSize= psTransform->nBackMapWidth = (int) ((dfMaxX - dfMinX) / dfPixelSize + 1); if (nBMXSize > INT_MAX / nBMYSize) { CPLError(CE_Failure, CPLE_AppDefined, "Int overflow : %d x %d", nBMXSize, nBMYSize); return FALSE; } dfMinX -= dfPixelSize/2.0; dfMaxY += dfPixelSize/2.0; psTransform->adfBackMapGeoTransform[0] = dfMinX; psTransform->adfBackMapGeoTransform[1] = dfPixelSize; psTransform->adfBackMapGeoTransform[2] = 0.0; psTransform->adfBackMapGeoTransform[3] = dfMaxY; psTransform->adfBackMapGeoTransform[4] = 0.0; psTransform->adfBackMapGeoTransform[5] = -dfPixelSize; /* -------------------------------------------------------------------- */ /* Allocate backmap, and initialize to nodata value (-1.0). */ /* -------------------------------------------------------------------- */ GByte *pabyValidFlag; pabyValidFlag = (GByte *) VSI_CALLOC_VERBOSE(nBMXSize, nBMYSize); psTransform->pafBackMapX = (float *) VSI_MALLOC3_VERBOSE(nBMXSize, nBMYSize, sizeof(float)); psTransform->pafBackMapY = (float *) VSI_MALLOC3_VERBOSE(nBMXSize, nBMYSize, sizeof(float)); if( pabyValidFlag == NULL || psTransform->pafBackMapX == NULL || psTransform->pafBackMapY == NULL ) { CPLFree( pabyValidFlag ); return FALSE; } for( i = nBMXSize * nBMYSize - 1; i >= 0; i-- ) { psTransform->pafBackMapX[i] = -1.0; psTransform->pafBackMapY[i] = -1.0; } /* -------------------------------------------------------------------- */ /* Run through the whole geoloc array forward projecting and */ /* pushing into the backmap. */ /* Initialize to the nMaxIter+1 value so we can spot genuinely */ /* valid pixels in the hole-filling loop. */ /* -------------------------------------------------------------------- */ int iBMX, iBMY; int iX, iY; for( iY = 0; iY < nYSize; iY++ ) { for( iX = 0; iX < nXSize; iX++ ) { if( psTransform->bHasNoData && psTransform->padfGeoLocX[iX + iY * nXSize] == psTransform->dfNoDataX ) continue; i = iX + iY * nXSize; iBMX = (int) ((psTransform->padfGeoLocX[i] - dfMinX) / dfPixelSize); iBMY = (int) ((dfMaxY - psTransform->padfGeoLocY[i]) / dfPixelSize); if( iBMX < 0 || iBMY < 0 || iBMX >= nBMXSize || iBMY >= nBMYSize ) continue; psTransform->pafBackMapX[iBMX + iBMY * nBMXSize] = (float)(iX * psTransform->dfPIXEL_STEP + psTransform->dfPIXEL_OFFSET); psTransform->pafBackMapY[iBMX + iBMY * nBMXSize] = (float)(iY * psTransform->dfLINE_STEP + psTransform->dfLINE_OFFSET); pabyValidFlag[iBMX + iBMY * nBMXSize] = (GByte) (nMaxIter+1); } } /* -------------------------------------------------------------------- */ /* Now, loop over the backmap trying to fill in holes with */ /* nearby values. */ /* -------------------------------------------------------------------- */ int iIter; int nNumValid; for( iIter = 0; iIter < nMaxIter; iIter++ ) { nNumValid = 0; for( iBMY = 0; iBMY < nBMYSize; iBMY++ ) { for( iBMX = 0; iBMX < nBMXSize; iBMX++ ) { // if this point is already set, ignore it. if( pabyValidFlag[iBMX + iBMY*nBMXSize] ) { nNumValid++; continue; } int nCount = 0; double dfXSum = 0.0, dfYSum = 0.0; int nMarkedAsGood = nMaxIter - iIter; // left? if( iBMX > 0 && pabyValidFlag[iBMX-1+iBMY*nBMXSize] > nMarkedAsGood ) { dfXSum += psTransform->pafBackMapX[iBMX-1+iBMY*nBMXSize]; dfYSum += psTransform->pafBackMapY[iBMX-1+iBMY*nBMXSize]; nCount++; } // right? if( iBMX + 1 < nBMXSize && pabyValidFlag[iBMX+1+iBMY*nBMXSize] > nMarkedAsGood ) { dfXSum += psTransform->pafBackMapX[iBMX+1+iBMY*nBMXSize]; dfYSum += psTransform->pafBackMapY[iBMX+1+iBMY*nBMXSize]; nCount++; } // top? if( iBMY > 0 && pabyValidFlag[iBMX+(iBMY-1)*nBMXSize] > nMarkedAsGood ) { dfXSum += psTransform->pafBackMapX[iBMX+(iBMY-1)*nBMXSize]; dfYSum += psTransform->pafBackMapY[iBMX+(iBMY-1)*nBMXSize]; nCount++; } // bottom? if( iBMY + 1 < nBMYSize && pabyValidFlag[iBMX+(iBMY+1)*nBMXSize] > nMarkedAsGood ) { dfXSum += psTransform->pafBackMapX[iBMX+(iBMY+1)*nBMXSize]; dfYSum += psTransform->pafBackMapY[iBMX+(iBMY+1)*nBMXSize]; nCount++; } // top-left? if( iBMX > 0 && iBMY > 0 && pabyValidFlag[iBMX-1+(iBMY-1)*nBMXSize] > nMarkedAsGood ) { dfXSum += psTransform->pafBackMapX[iBMX-1+(iBMY-1)*nBMXSize]; dfYSum += psTransform->pafBackMapY[iBMX-1+(iBMY-1)*nBMXSize]; nCount++; } // top-right? if( iBMX + 1 < nBMXSize && iBMY > 0 && pabyValidFlag[iBMX+1+(iBMY-1)*nBMXSize] > nMarkedAsGood ) { dfXSum += psTransform->pafBackMapX[iBMX+1+(iBMY-1)*nBMXSize]; dfYSum += psTransform->pafBackMapY[iBMX+1+(iBMY-1)*nBMXSize]; nCount++; } // bottom-left? if( iBMX > 0 && iBMY + 1 < nBMYSize && pabyValidFlag[iBMX-1+(iBMY+1)*nBMXSize] > nMarkedAsGood ) { dfXSum += psTransform->pafBackMapX[iBMX-1+(iBMY+1)*nBMXSize]; dfYSum += psTransform->pafBackMapY[iBMX-1+(iBMY+1)*nBMXSize]; nCount++; } // bottom-right? if( iBMX + 1 < nBMXSize && iBMY + 1 < nBMYSize && pabyValidFlag[iBMX+1+(iBMY+1)*nBMXSize] > nMarkedAsGood ) { dfXSum += psTransform->pafBackMapX[iBMX+1+(iBMY+1)*nBMXSize]; dfYSum += psTransform->pafBackMapY[iBMX+1+(iBMY+1)*nBMXSize]; nCount++; } if( nCount > 0 ) { psTransform->pafBackMapX[iBMX + iBMY * nBMXSize] = (float)(dfXSum/nCount); psTransform->pafBackMapY[iBMX + iBMY * nBMXSize] = (float)(dfYSum/nCount); // genuinely valid points will have value iMaxIter+1 // On each iteration mark newly valid points with a // descending value so that it will not be used on the // current iteration only on subsequent ones. pabyValidFlag[iBMX+iBMY*nBMXSize] = (GByte) (nMaxIter - iIter); } } } if (nNumValid == nBMXSize * nBMYSize) break; } #ifdef notdef GDALDatasetH hBMDS = GDALCreate( GDALGetDriverByName( "GTiff" ), "backmap.tif", nBMXSize, nBMYSize, 2, GDT_Float32, NULL ); GDALSetGeoTransform( hBMDS, psTransform->adfBackMapGeoTransform ); GDALRasterIO( GDALGetRasterBand(hBMDS,1), GF_Write, 0, 0, nBMXSize, nBMYSize, psTransform->pafBackMapX, nBMXSize, nBMYSize, GDT_Float32, 0, 0 ); GDALRasterIO( GDALGetRasterBand(hBMDS,2), GF_Write, 0, 0, nBMXSize, nBMYSize, psTransform->pafBackMapY, nBMXSize, nBMYSize, GDT_Float32, 0, 0 ); GDALClose( hBMDS ); #endif CPLFree( pabyValidFlag ); return TRUE; }
VSIFilesystemPluginCallbacksStruct* VSIAllocFilesystemPluginCallbacksStruct( void ) { return static_cast<VSIFilesystemPluginCallbacksStruct*>(VSI_CALLOC_VERBOSE(1, sizeof(VSIFilesystemPluginCallbacksStruct))); }
template<class T> int GDALComputeMedianCutPCTInternal( GDALRasterBandH hRed, GDALRasterBandH hGreen, GDALRasterBandH hBlue, GByte* pabyRedBand, GByte* pabyGreenBand, GByte* pabyBlueBand, int (*pfnIncludePixel)(int, int, void*), int nColors, int nBits, T* panHistogram, // NULL, or >= size (1<<nBits)^3 * sizeof(T) bytes. GDALColorTableH hColorTable, GDALProgressFunc pfnProgress, void * pProgressArg ) { VALIDATE_POINTER1( hRed, "GDALComputeMedianCutPCT", CE_Failure ); VALIDATE_POINTER1( hGreen, "GDALComputeMedianCutPCT", CE_Failure ); VALIDATE_POINTER1( hBlue, "GDALComputeMedianCutPCT", CE_Failure ); CPLErr err = CE_None; /* -------------------------------------------------------------------- */ /* Validate parameters. */ /* -------------------------------------------------------------------- */ const int nXSize = GDALGetRasterBandXSize( hRed ); const int nYSize = GDALGetRasterBandYSize( hRed ); if( GDALGetRasterBandXSize( hGreen ) != nXSize || GDALGetRasterBandYSize( hGreen ) != nYSize || GDALGetRasterBandXSize( hBlue ) != nXSize || GDALGetRasterBandYSize( hBlue ) != nYSize ) { CPLError(CE_Failure, CPLE_IllegalArg, "Green or blue band doesn't match size of red band."); return CE_Failure; } if( pfnIncludePixel != NULL ) { CPLError(CE_Failure, CPLE_IllegalArg, "GDALComputeMedianCutPCT() doesn't currently support " "pfnIncludePixel function."); return CE_Failure; } if( nColors <= 0 ) { CPLError(CE_Failure, CPLE_IllegalArg, "GDALComputeMedianCutPCT(): " "nColors must be strictly greater than 1."); return CE_Failure; } if( nColors > 256 ) { CPLError(CE_Failure, CPLE_IllegalArg, "GDALComputeMedianCutPCT(): " "nColors must be lesser than or equal to 256."); return CE_Failure; } if( pfnProgress == NULL ) pfnProgress = GDALDummyProgress; /* ==================================================================== */ /* STEP 1: create empty boxes. */ /* ==================================================================== */ if( static_cast<GUInt32>(nXSize) > std::numeric_limits<T>::max() / static_cast<GUInt32>(nYSize) ) { CPLError(CE_Warning, CPLE_AppDefined, "GDALComputeMedianCutPCTInternal() not called " "with large enough type"); } T nPixels = 0; if( nBits == 8 && pabyRedBand != NULL && pabyGreenBand != NULL && pabyBlueBand != NULL && static_cast<GUInt32>(nXSize) <= std::numeric_limits<T>::max() / static_cast<GUInt32>(nYSize) ) { nPixels = static_cast<T>(nXSize) * static_cast<T>(nYSize); } const int nCLevels = 1 << nBits; T* histogram = NULL; HashHistogram* psHashHistogram = NULL; if( panHistogram ) { if( nBits == 8 && static_cast<GUIntBig>(nXSize) * nYSize <= 65536 ) { // If the image is small enough, then the number of colors // will be limited and using a hashmap, rather than a full table // will be more efficient. histogram = NULL; psHashHistogram = (HashHistogram*)panHistogram; memset(psHashHistogram, 0xFF, sizeof(HashHistogram) * PRIME_FOR_65536); } else { histogram = panHistogram; memset(histogram, 0, nCLevels*nCLevels*nCLevels * sizeof(T)); } } else { histogram = static_cast<T*>( VSI_CALLOC_VERBOSE(nCLevels * nCLevels * nCLevels, sizeof(T))); if( histogram == NULL ) { return CE_Failure; } } Colorbox *box_list = static_cast<Colorbox *>(CPLMalloc(nColors*sizeof (Colorbox))); Colorbox *freeboxes = box_list; freeboxes[0].next = &freeboxes[1]; freeboxes[0].prev = NULL; for( int i = 1; i < nColors-1; ++i ) { freeboxes[i].next = &freeboxes[i+1]; freeboxes[i].prev = &freeboxes[i-1]; } freeboxes[nColors-1].next = NULL; freeboxes[nColors-1].prev = &freeboxes[nColors-2]; /* ==================================================================== */ /* Build histogram. */ /* ==================================================================== */ /* -------------------------------------------------------------------- */ /* Initialize the box datastructures. */ /* -------------------------------------------------------------------- */ Colorbox *ptr = freeboxes; freeboxes = ptr->next; if( freeboxes ) freeboxes->prev = NULL; Colorbox *usedboxes = NULL; // TODO(schwehr): What? ptr->next = usedboxes; usedboxes = ptr; if( ptr->next ) ptr->next->prev = ptr; ptr->rmin = 999; ptr->gmin = 999; ptr->bmin = 999; ptr->rmax = -1; ptr->gmax = -1; ptr->bmax = -1; ptr->total = static_cast<GUIntBig>(nXSize) * static_cast<GUIntBig>(nYSize); /* -------------------------------------------------------------------- */ /* Collect histogram. */ /* -------------------------------------------------------------------- */ // TODO(schwehr): Move these closer to usage after removing gotos. const int nColorShift = 8 - nBits; int nColorCounter = 0; GByte anRed[256] = {}; GByte anGreen[256] = {}; GByte anBlue[256] = {}; GByte *pabyRedLine = static_cast<GByte *>(VSI_MALLOC_VERBOSE(nXSize)); GByte *pabyGreenLine = static_cast<GByte *>(VSI_MALLOC_VERBOSE(nXSize)); GByte *pabyBlueLine = static_cast<GByte *>(VSI_MALLOC_VERBOSE(nXSize)); if( pabyRedLine == NULL || pabyGreenLine == NULL || pabyBlueLine == NULL ) { err = CE_Failure; goto end_and_cleanup; } for( int iLine = 0; iLine < nYSize; iLine++ ) { if( !pfnProgress( iLine / static_cast<double>(nYSize), "Generating Histogram", pProgressArg ) ) { CPLError( CE_Failure, CPLE_UserInterrupt, "User Terminated" ); err = CE_Failure; goto end_and_cleanup; } err = GDALRasterIO( hRed, GF_Read, 0, iLine, nXSize, 1, pabyRedLine, nXSize, 1, GDT_Byte, 0, 0 ); if( err == CE_None ) err = GDALRasterIO( hGreen, GF_Read, 0, iLine, nXSize, 1, pabyGreenLine, nXSize, 1, GDT_Byte, 0, 0 ); if( err == CE_None ) err = GDALRasterIO( hBlue, GF_Read, 0, iLine, nXSize, 1, pabyBlueLine, nXSize, 1, GDT_Byte, 0, 0 ); if( err != CE_None ) goto end_and_cleanup; for( int iPixel = 0; iPixel < nXSize; iPixel++ ) { const int nRed = pabyRedLine[iPixel] >> nColorShift; const int nGreen = pabyGreenLine[iPixel] >> nColorShift; const int nBlue = pabyBlueLine[iPixel] >> nColorShift; ptr->rmin = std::min(ptr->rmin, nRed); ptr->gmin = std::min(ptr->gmin, nGreen); ptr->bmin = std::min(ptr->bmin, nBlue); ptr->rmax = std::max(ptr->rmax, nRed); ptr->gmax = std::max(ptr->gmax, nGreen); ptr->bmax = std::max(ptr->bmax, nBlue); bool bFirstOccurrence; if( psHashHistogram ) { int* pnColor = FindAndInsertColorCount(psHashHistogram, MAKE_COLOR_CODE(nRed, nGreen, nBlue)); bFirstOccurrence = ( *pnColor == 0 ); (*pnColor)++; } else { T* pnColor = HISTOGRAM(histogram, nCLevels, nRed, nGreen, nBlue); bFirstOccurrence = ( *pnColor == 0 ); (*pnColor)++; } if( bFirstOccurrence) { if( nColorShift == 0 && nColorCounter < nColors ) { anRed[nColorCounter] = static_cast<GByte>(nRed); anGreen[nColorCounter] = static_cast<GByte>(nGreen); anBlue[nColorCounter] = static_cast<GByte>(nBlue); } nColorCounter++; } } } if( !pfnProgress( 1.0, "Generating Histogram", pProgressArg ) ) { CPLError( CE_Failure, CPLE_UserInterrupt, "User Terminated" ); err = CE_Failure; goto end_and_cleanup; } if( nColorShift == 0 && nColorCounter <= nColors ) { #if DEBUG_VERBOSE CPLDebug("MEDIAN_CUT", "%d colors found <= %d", nColorCounter, nColors); #endif for( int iColor = 0; iColor < nColorCounter; iColor++ ) { const GDALColorEntry sEntry = { static_cast<GByte>(anRed[iColor]), static_cast<GByte>(anGreen[iColor]), static_cast<GByte>(anBlue[iColor]), 255 }; GDALSetColorEntry( hColorTable, iColor, &sEntry ); } goto end_and_cleanup; } /* ==================================================================== */ /* STEP 3: continually subdivide boxes until no more free */ /* boxes remain or until all colors assigned. */ /* ==================================================================== */ while( freeboxes != NULL ) { ptr = largest_box(usedboxes); if( ptr != NULL ) splitbox(ptr, histogram, psHashHistogram, nCLevels, &freeboxes, &usedboxes, pabyRedBand, pabyGreenBand, pabyBlueBand, nPixels); else freeboxes = NULL; } /* ==================================================================== */ /* STEP 4: assign colors to all boxes */ /* ==================================================================== */ ptr = usedboxes; for( int i = 0; ptr != NULL; ++i, ptr = ptr->next ) { const GDALColorEntry sEntry = { static_cast<GByte>(((ptr->rmin + ptr->rmax) << nColorShift) / 2), static_cast<GByte>(((ptr->gmin + ptr->gmax) << nColorShift) / 2), static_cast<GByte>(((ptr->bmin + ptr->bmax) << nColorShift) / 2), 255 }; GDALSetColorEntry( hColorTable, i, &sEntry ); } end_and_cleanup: CPLFree( pabyRedLine ); CPLFree( pabyGreenLine ); CPLFree( pabyBlueLine ); // We're done with the boxes now. CPLFree(box_list); freeboxes = NULL; usedboxes = NULL; if( panHistogram == NULL ) CPLFree( histogram ); return err; }