GDALDataset *CALSDataset::CreateCopy( const char *pszFilename, GDALDataset *poSrcDS, int bStrict, char ** /* papszOptionsUnused */, GDALProgressFunc pfnProgress, void *pProgressData ) { if( poSrcDS->GetRasterCount() == 0 || (bStrict && poSrcDS->GetRasterCount() != 1) ) { CPLError( CE_Failure, CPLE_NotSupported, "CALS driver only supports single band raster."); return NULL; } if( poSrcDS->GetRasterBand(1)-> GetMetadataItem("NBITS", "IMAGE_STRUCTURE") == NULL || !EQUAL(poSrcDS->GetRasterBand(1)-> GetMetadataItem("NBITS", "IMAGE_STRUCTURE"), "1") ) { CPLError( bStrict ? CE_Failure : CE_Warning, CPLE_NotSupported, "CALS driver only supports 1-bit."); if( bStrict ) return NULL; } if( poSrcDS->GetRasterXSize() > 999999 || poSrcDS->GetRasterYSize() > 999999 ) { CPLError( CE_Failure, CPLE_NotSupported, "CALS driver only supports datasets with dimension <= 999999."); return NULL; } GDALDriver* poGTiffDrv = static_cast<GDALDriver *>(GDALGetDriverByName("GTiff")); if( poGTiffDrv == NULL ) { CPLError( CE_Failure, CPLE_NotSupported, "CALS driver needs GTiff driver." ); return NULL; } // Write a in-memory TIFF with just the TIFF header to figure out // how large it will be. CPLString osTmpFilename(CPLSPrintf("/vsimem/cals/tmp_%p", poSrcDS)); char** papszOptions = NULL; papszOptions = CSLSetNameValue(papszOptions, "COMPRESS", "CCITTFAX4"); papszOptions = CSLSetNameValue(papszOptions, "NBITS", "1"); papszOptions = CSLSetNameValue(papszOptions, "BLOCKYSIZE", CPLSPrintf("%d", poSrcDS->GetRasterYSize())); papszOptions = CSLSetNameValue(papszOptions, "SPARSE_OK", "YES"); GDALDataset* poDS = poGTiffDrv->Create(osTmpFilename, poSrcDS->GetRasterXSize(), poSrcDS->GetRasterYSize(), 1, GDT_Byte, papszOptions); if( poDS == NULL ) { // Should not happen normally (except if CCITTFAX4 not available). CSLDestroy(papszOptions); return NULL; } const char INITIAL_PADDING[] = "12345"; // To adjust padding. poDS->SetMetadataItem("TIFFTAG_DOCUMENTNAME", INITIAL_PADDING); GDALClose(poDS); VSIStatBufL sStat; if( VSIStatL(osTmpFilename, &sStat) != 0 ) { // Shoudln't happen really. Just to make Coverity happy. CSLDestroy(papszOptions); return NULL; } int nTIFFHeaderSize = static_cast<int>(sStat.st_size); VSIUnlink(osTmpFilename); // Redo the same thing, but this time write it to the output file // and use a variable TIFF tag (TIFFTAG_DOCUMENTNAME) to enlarge the // header + the variable TIFF tag so that they are 2048 bytes large. char szBuffer[2048+1] = {}; memset(szBuffer, 'X', 2048 - nTIFFHeaderSize + strlen(INITIAL_PADDING)); szBuffer[2048 - nTIFFHeaderSize + strlen(INITIAL_PADDING)] = 0; GDALDataset* poTmpDS = new CALSWrapperSrcDataset(poSrcDS, szBuffer); poDS = poGTiffDrv->CreateCopy(pszFilename, poTmpDS, FALSE, papszOptions, pfnProgress, pProgressData ); delete poTmpDS; CSLDestroy(papszOptions); if( poDS == NULL ) return NULL; delete poDS; // Now replace the TIFF header by the CALS header. VSILFILE* fp = VSIFOpenL(pszFilename, "rb+"); if( fp == NULL ) return NULL; // Shoudln't happen normally. memset(szBuffer, ' ', 2048); CPLString osField; osField = "srcdocid: NONE"; memcpy(szBuffer, osField, osField.size()); osField = "dstdocid: NONE"; memcpy(szBuffer + 128, osField, osField.size()); osField = "txtfilid: NONE"; memcpy(szBuffer + 128*2, osField, osField.size()); osField = "figid: NONE"; memcpy(szBuffer + 128*3, osField, osField.size()); osField = "srcgph: NONE"; memcpy(szBuffer + 128*4, osField, osField.size()); osField = "doccls: NONE"; memcpy(szBuffer + 128*5, osField, osField.size()); osField = "rtype: 1"; memcpy(szBuffer + 128*6, osField, osField.size()); int nAngle1 = 0; int nAngle2 = 270; const char* pszPixelPath = poSrcDS->GetMetadataItem("PIXEL_PATH"); const char* pszLineProgression = poSrcDS->GetMetadataItem("LINE_PROGRESSION"); if( pszPixelPath && pszLineProgression ) { nAngle1 = atoi(pszPixelPath); nAngle2 = atoi(pszLineProgression); } osField = CPLSPrintf("rorient: %03d,%03d", nAngle1, nAngle2); memcpy(szBuffer + 128*7, osField, osField.size()); osField = CPLSPrintf("rpelcnt: %06d,%06d", poSrcDS->GetRasterXSize(), poSrcDS->GetRasterYSize()); memcpy(szBuffer + 128*8, osField, osField.size()); int nDensity = 200; const char* pszXRes = poSrcDS->GetMetadataItem("TIFFTAG_XRESOLUTION"); const char* pszYRes = poSrcDS->GetMetadataItem("TIFFTAG_YRESOLUTION"); const char* pszResUnit = poSrcDS->GetMetadataItem("TIFFTAG_RESOLUTIONUNIT"); if( pszXRes && pszYRes && pszResUnit && EQUAL(pszXRes, pszYRes) && atoi(pszResUnit) == 2 ) { nDensity = atoi(pszXRes); if( nDensity < 1 || nDensity > 9999 ) nDensity = 200; } osField = CPLSPrintf("rdensty: %04d", nDensity); memcpy(szBuffer + 128*9, osField, osField.size()); osField = "notes: NONE"; memcpy(szBuffer + 128*10, osField, osField.size()); VSIFWriteL(szBuffer, 1, 2048, fp); VSIFCloseL(fp); GDALOpenInfo oOpenInfo(pszFilename, GA_ReadOnly, NULL); return Open(&oOpenInfo); }
GDALDataset* SRTMHGTDataset::Open(GDALOpenInfo* poOpenInfo) { if (!Identify(poOpenInfo)) return nullptr; const char* fileName = CPLGetFilename(poOpenInfo->pszFilename); CPLString osLCFilename(CPLString(fileName).tolower()); if( !STARTS_WITH(fileName, "/vsizip/") && osLCFilename.endsWith(".hgt.zip") ) { CPLString osFilename ("/vsizip/"); osFilename += poOpenInfo->pszFilename; osFilename += "/"; osFilename += CPLString(fileName).substr(0, 7); osFilename += ".hgt"; GDALOpenInfo oOpenInfo(osFilename, poOpenInfo->eAccess); GDALDataset* poDS = Open(&oOpenInfo); if( poDS != nullptr ) { // override description with the main one poDS->SetDescription(poOpenInfo->pszFilename); } return poDS; } if( !STARTS_WITH(fileName, "/vsizip/") && osLCFilename.endsWith(".srtmswbd.raw.zip") ) { CPLString osFilename("/vsizip/"); osFilename += poOpenInfo->pszFilename; osFilename += "/"; osFilename += CPLString(fileName).substr(0, 7); osFilename += ".raw"; GDALOpenInfo oOpenInfo(osFilename, poOpenInfo->eAccess); GDALDataset* poDS = Open(&oOpenInfo); if( poDS != nullptr ) { // override description with the main one poDS->SetDescription(poOpenInfo->pszFilename); } return poDS; } char latLonValueString[4]; memset(latLonValueString, 0, 4); strncpy(latLonValueString, &fileName[1], 2); int southWestLat = atoi(latLonValueString); memset(latLonValueString, 0, 4); // cppcheck-suppress redundantCopy strncpy(latLonValueString, &fileName[4], 3); int southWestLon = atoi(latLonValueString); if(fileName[0] == 'N' || fileName[0] == 'n') /*southWestLat = southWestLat */; else if(fileName[0] == 'S' || fileName[0] == 's') southWestLat = southWestLat * -1; else return nullptr; if(fileName[3] == 'E' || fileName[3] == 'e') /*southWestLon = southWestLon */; else if(fileName[3] == 'W' || fileName[3] == 'w') southWestLon = southWestLon * -1; else return nullptr; /* -------------------------------------------------------------------- */ /* Create a corresponding GDALDataset. */ /* -------------------------------------------------------------------- */ SRTMHGTDataset* poDS = new SRTMHGTDataset(); poDS->fpImage = poOpenInfo->fpL; poOpenInfo->fpL = nullptr; VSIStatBufL fileStat; if(VSIStatL(poOpenInfo->pszFilename, &fileStat) != 0) { delete poDS; return nullptr; } int numPixels_x, numPixels_y; GDALDataType eDT = GDT_Int16; switch (fileStat.st_size) { case 3601 * 3601: numPixels_x = numPixels_y = 3601; eDT = GDT_Byte; break; case 3601 * 3601 * 2: numPixels_x = numPixels_y = 3601; break; case 1801 * 3601 * 2: numPixels_x = 1801; numPixels_y = 3601; break; case 1201 * 1201 * 2: numPixels_x = numPixels_y = 1201; break; default: numPixels_x = numPixels_y = 0; break; } poDS->eAccess = poOpenInfo->eAccess; #ifdef CPL_LSB if(poDS->eAccess == GA_Update && eDT == GDT_Int16) { poDS->panBuffer = reinterpret_cast<GInt16 *>( CPLMalloc(numPixels_x * sizeof(GInt16)) ); } #endif /* -------------------------------------------------------------------- */ /* Capture some information from the file that is of interest. */ /* -------------------------------------------------------------------- */ poDS->nRasterXSize = numPixels_x; poDS->nRasterYSize = numPixels_y; poDS->nBands = 1; poDS->adfGeoTransform[0] = southWestLon - 0.5 / (numPixels_x - 1); poDS->adfGeoTransform[1] = 1.0 / (numPixels_x-1); poDS->adfGeoTransform[2] = 0.0; poDS->adfGeoTransform[3] = southWestLat + 1 + 0.5 / (numPixels_y - 1); poDS->adfGeoTransform[4] = 0.0; poDS->adfGeoTransform[5] = -1.0 / (numPixels_y-1); poDS->SetMetadataItem( GDALMD_AREA_OR_POINT, GDALMD_AOP_POINT ); /* -------------------------------------------------------------------- */ /* Create band information object. */ /* -------------------------------------------------------------------- */ SRTMHGTRasterBand* tmpBand = new SRTMHGTRasterBand(poDS, 1, eDT); poDS->SetBand(1, tmpBand); /* -------------------------------------------------------------------- */ /* Initialize any PAM information. */ /* -------------------------------------------------------------------- */ poDS->SetDescription(poOpenInfo->pszFilename); poDS->TryLoadXML(); /* -------------------------------------------------------------------- */ /* Support overviews. */ /* -------------------------------------------------------------------- */ poDS->oOvManager.Initialize( poDS, poOpenInfo->pszFilename ); return poDS; }
GDALDataset* OGRPLScenesDataset::OpenRasterScene(GDALOpenInfo* poOpenInfo, CPLString osScene, char** papszOptions) { if( !(poOpenInfo->nOpenFlags & GDAL_OF_RASTER) ) { return NULL; } for( char** papszIter = papszOptions; papszIter && *papszIter; papszIter ++ ) { char* pszKey; const char* pszValue = CPLParseNameValue(*papszIter, &pszKey); if( pszValue != NULL ) { if( !EQUAL(pszKey, "api_key") && !EQUAL(pszKey, "scene") && !EQUAL(pszKey, "product_type") ) { CPLError(CE_Failure, CPLE_NotSupported, "Unsupported option %s", pszKey); CPLFree(pszKey); return NULL; } CPLFree(pszKey); } } const char* pszProductType = CSLFetchNameValueDef(papszOptions, "product_type", CSLFetchNameValueDef(poOpenInfo->papszOpenOptions, "PRODUCT_TYPE", "visual")); CPLString osRasterURL; osRasterURL = osBaseURL; osRasterURL += "ortho/"; osRasterURL += osScene; json_object* poObj = RunRequest( osRasterURL ); if( poObj == NULL ) return NULL; json_object* poProperties = json_object_object_get(poObj, "properties"); if( poProperties == NULL || json_object_get_type(poProperties) != json_type_object ) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot find properties object"); json_object_put(poObj); return NULL; } const char* pszLink = NULL; if( EQUAL(pszProductType, "thumb") ) { json_object* poLinks = json_object_object_get(poProperties, "links"); if( poLinks != NULL && json_object_get_type(poLinks) == json_type_object ) { json_object* poThumbnail = json_object_object_get(poLinks, "thumbnail"); if( poThumbnail && json_object_get_type(poThumbnail) == json_type_string ) pszLink = json_object_get_string(poThumbnail); } } else { json_object* poData = json_object_object_get(poProperties, "data"); if( poData != NULL && json_object_get_type(poData) == json_type_object ) { json_object* poProducts = json_object_object_get(poData, "products"); if( poProducts != NULL && json_object_get_type(poProducts) == json_type_object ) { json_object* poProduct = json_object_object_get(poProducts, pszProductType); if( poProduct != NULL && json_object_get_type(poProduct) == json_type_object ) { json_object* poFull = json_object_object_get(poProduct, "full"); if( poFull && json_object_get_type(poFull) == json_type_string ) pszLink = json_object_get_string(poFull); } } } } osRasterURL = pszLink ? pszLink : ""; json_object_put(poObj); if( osRasterURL.size() == 0 ) { CPLError(CE_Failure, CPLE_AppDefined, "Cannot find link to scene %s", osScene.c_str()); return NULL; } if( strncmp(osRasterURL, "http://", strlen("http://")) == 0 ) { osRasterURL = "http://" + osAPIKey + ":@" + osRasterURL.substr(strlen("http://")); } else if( strncmp(osRasterURL, "https://", strlen("https://")) == 0 ) { osRasterURL = "https://" + osAPIKey + ":@" + osRasterURL.substr(strlen("https://")); } CPLString osOldHead(CPLGetConfigOption("CPL_VSIL_CURL_USE_HEAD", "")); CPLString osOldExt(CPLGetConfigOption("CPL_VSIL_CURL_ALLOWED_EXTENSIONS", "")); int bUseVSICURL = CSLFetchBoolean(poOpenInfo->papszOpenOptions, "RANDOM_ACCESS", TRUE); if( bUseVSICURL && !(strncmp(osBaseURL, "/vsimem/", strlen("/vsimem/")) == 0) ) { CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_USE_HEAD", "NO"); CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_ALLOWED_EXTENSIONS", "{noext}"); VSIStatBufL sStat; if( VSIStatL(("/vsicurl/" + osRasterURL).c_str(), &sStat) == 0 && sStat.st_size > 0 ) { osRasterURL = "/vsicurl/" + osRasterURL; } else { CPLDebug("PLSCENES", "Cannot use random access for that file"); } } GDALDataset* poOutDS = (GDALDataset*) GDALOpen(osRasterURL, GA_ReadOnly); if( poOutDS ) { poOutDS->SetDescription(poOpenInfo->pszFilename); poOutDS->GetFileList(); /* so as to probe all auxiliary files before reseting the allowed extensions */ if( !EQUAL(pszProductType, "thumb") ) { OGRPLScenesLayer* poLayer = new OGRPLScenesLayer(this, "ortho", (osBaseURL + "ortho/").c_str()); papoLayers = (OGRPLScenesLayer**) CPLRealloc(papoLayers, sizeof(OGRPLScenesLayer*) * (nLayers + 1)); papoLayers[nLayers ++] = poLayer; /* Attach scene matadata */ poLayer->SetAttributeFilter(CPLSPrintf("id = '%s'", osScene.c_str())); OGRFeature* poFeat = poLayer->GetNextFeature(); if( poFeat ) { for(int i=0;i<poFeat->GetFieldCount();i++) { if( poFeat->IsFieldSet(i) ) { const char* pszKey = poFeat->GetFieldDefnRef(i)->GetNameRef(); const char* pszVal = poFeat->GetFieldAsString(i); if( strstr(pszKey, "file_size") == NULL && strstr(pszVal, "https://") == NULL ) { poOutDS->SetMetadataItem(pszKey, pszVal); } } } } delete poFeat; } } if( bUseVSICURL ) { CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_USE_HEAD", osOldHead.size() ? osOldHead.c_str(): NULL); CPLSetThreadLocalConfigOption("CPL_VSIL_CURL_ALLOWED_EXTENSIONS", osOldExt.size() ? osOldExt.c_str(): NULL); } return poOutDS; }