Ejemplo n.º 1
0
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);
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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;
}