Exemplo 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);
}
Exemplo n.º 2
0
OGRErr OGRCSVEditableLayerSynchronizer::EditableSyncToDisk(OGRLayer* poEditableLayer,
                                                           OGRLayer** ppoDecoratedLayer)
{
    CPLAssert( m_poCSVLayer == *ppoDecoratedLayer );

    CPLString osLayerName(m_poCSVLayer->GetName());
    CPLString osFilename(m_poCSVLayer->GetFilename());
    const bool bCreateCSVT = m_poCSVLayer->GetCreateCSVT();
    CPLString osCSVTFilename(CPLResetExtension(osFilename, "csvt"));
    VSIStatBufL sStatBuf;
    const bool bHasCSVT = VSIStatL(osCSVTFilename, &sStatBuf) == 0;
    CPLString osTmpFilename(osFilename);
    CPLString osTmpCSVTFilename(osFilename);
    if( VSIStatL(osFilename, &sStatBuf) == 0 )
    {
        osTmpFilename += "_ogr_tmp.csv";
        osTmpCSVTFilename += "_ogr_tmp.csvt";
    }
    const char chDelimiter = m_poCSVLayer->GetDelimiter();
    OGRCSVLayer* poCSVTmpLayer = new OGRCSVLayer( osLayerName, NULL,
                                                  osTmpFilename,
                                                  true, true, chDelimiter );
    poCSVTmpLayer->BuildFeatureDefn(NULL, NULL, m_papszOpenOptions);
    poCSVTmpLayer->SetCRLF( m_poCSVLayer->GetCRLF() );
    poCSVTmpLayer->SetCreateCSVT( bCreateCSVT || bHasCSVT );
    poCSVTmpLayer->SetWriteBOM( m_poCSVLayer->GetWriteBOM() );

    if( m_poCSVLayer->GetGeometryFormat() == OGR_CSV_GEOM_AS_WKT )
        poCSVTmpLayer->SetWriteGeometry( wkbNone, OGR_CSV_GEOM_AS_WKT, NULL );

    OGRErr eErr = OGRERR_NONE;
    OGRFeatureDefn* poEditableFDefn =  poEditableLayer->GetLayerDefn();
    for( int i=0; eErr == OGRERR_NONE &&
                  i < poEditableFDefn->GetFieldCount(); i++ )
    {
        OGRFieldDefn oFieldDefn(poEditableFDefn->GetFieldDefn(i));
        int iGeomFieldIdx = 0;
        if( (EQUAL(oFieldDefn.GetNameRef(), "WKT") &&
             (iGeomFieldIdx = poEditableFDefn->GetGeomFieldIndex("")) >= 0) ||
            (iGeomFieldIdx = poEditableFDefn->GetGeomFieldIndex(oFieldDefn.GetNameRef())) >= 0 )
        {
            OGRGeomFieldDefn oGeomFieldDefn(
                poEditableFDefn->GetGeomFieldDefn(iGeomFieldIdx) );
            eErr = poCSVTmpLayer->CreateGeomField( &oGeomFieldDefn );
        }
        else
        {
            eErr = poCSVTmpLayer->CreateField( &oFieldDefn );
        }
    }

    const bool bHasXY = ( !m_poCSVLayer->GetXField().empty() &&
                          !m_poCSVLayer->GetYField().empty() );
    const bool bHasZ = ( !m_poCSVLayer->GetZField().empty() );
    if( bHasXY && !CPLFetchBool(m_papszOpenOptions, "KEEP_GEOM_COLUMNS", true) )
    {
        if( poCSVTmpLayer->GetLayerDefn()->GetFieldIndex(m_poCSVLayer->GetXField()) < 0 )
        {
            OGRFieldDefn oFieldDefn(m_poCSVLayer->GetXField(), OFTReal);
            if( eErr == OGRERR_NONE )
                eErr = poCSVTmpLayer->CreateField( &oFieldDefn );
        }
        if( poCSVTmpLayer->GetLayerDefn()->GetFieldIndex(m_poCSVLayer->GetYField()) < 0 )
        {
            OGRFieldDefn oFieldDefn(m_poCSVLayer->GetYField(), OFTReal);
            if( eErr == OGRERR_NONE )
                eErr = poCSVTmpLayer->CreateField( &oFieldDefn );
        }
        if( bHasZ && poCSVTmpLayer->GetLayerDefn()->GetFieldIndex(m_poCSVLayer->GetZField()) < 0 )
        {
            OGRFieldDefn oFieldDefn(m_poCSVLayer->GetZField(), OFTReal);
            if( eErr == OGRERR_NONE )
                eErr = poCSVTmpLayer->CreateField( &oFieldDefn );
        }
    }

    int nFirstGeomColIdx = 0;
    if( m_poCSVLayer->HasHiddenWKTColumn() )
    {
        poCSVTmpLayer->SetWriteGeometry(
            poEditableFDefn->GetGeomFieldDefn(0)->GetType(),
            OGR_CSV_GEOM_AS_WKT,
            poEditableFDefn->GetGeomFieldDefn(0)->GetNameRef());
        nFirstGeomColIdx = 1;
    }

    if( !(poEditableFDefn->GetGeomFieldCount() == 1 && bHasXY) )
    {
        for( int i=nFirstGeomColIdx; eErr == OGRERR_NONE &&
                i < poEditableFDefn->GetGeomFieldCount(); i++ )
        {
            OGRGeomFieldDefn oGeomFieldDefn( poEditableFDefn->GetGeomFieldDefn(i) );
            if( poCSVTmpLayer->GetLayerDefn()->GetGeomFieldIndex(oGeomFieldDefn.GetNameRef()) >= 0 )
                continue;
            eErr = poCSVTmpLayer->CreateGeomField( &oGeomFieldDefn );
        }
    }

    OGRFeature* poFeature = NULL;
    poEditableLayer->ResetReading();
    while( eErr == OGRERR_NONE &&
           (poFeature = poEditableLayer->GetNextFeature()) != NULL )
    {
        OGRFeature* poNewFeature = new OGRFeature( poCSVTmpLayer->GetLayerDefn() );
        poNewFeature->SetFrom(poFeature);
        if( bHasXY )
        {
            OGRGeometry* poGeom = poFeature->GetGeometryRef();
            if( poGeom != NULL && wkbFlatten(poGeom->getGeometryType()) == wkbPoint )
            {
                poNewFeature->SetField( m_poCSVLayer->GetXField(),
                                        static_cast<OGRPoint*>(poGeom)->getX());
                poNewFeature->SetField( m_poCSVLayer->GetYField(),
                                        static_cast<OGRPoint*>(poGeom)->getY());
                if( bHasZ )
                {
                    poNewFeature->SetField( m_poCSVLayer->GetZField(),
                                        static_cast<OGRPoint*>(poGeom)->getZ());
                }
            }
        }
        eErr = poCSVTmpLayer->CreateFeature(poNewFeature);
        delete poFeature;
        delete poNewFeature;
    }
    delete poCSVTmpLayer;

    if( eErr != OGRERR_NONE )
    {
        CPLError(CE_Failure, CPLE_AppDefined, "Error while creating %s",
                 osTmpFilename.c_str());
        VSIUnlink( osTmpFilename );
        VSIUnlink( CPLResetExtension(osTmpFilename, "csvt") );
        return eErr;
    }

    delete m_poCSVLayer;

    if( osFilename != osTmpFilename )
    {
        CPLString osTmpOriFilename(osFilename + ".ogr_bak");
        CPLString osTmpOriCSVTFilename(osCSVTFilename + ".ogr_bak");
        if( VSIRename( osFilename, osTmpOriFilename ) != 0 ||
            (bHasCSVT && VSIRename( osCSVTFilename, osTmpOriCSVTFilename ) != 0 ) ||
            VSIRename( osTmpFilename, osFilename) != 0 ||
            (bHasCSVT && VSIRename( osTmpCSVTFilename, osCSVTFilename ) != 0) )
        {
            CPLError(CE_Failure, CPLE_AppDefined, "Cannot rename files");
            *ppoDecoratedLayer = NULL;
            m_poCSVLayer = NULL;
            return OGRERR_FAILURE;
        }
        VSIUnlink( osTmpOriFilename );
        if( bHasCSVT )
            VSIUnlink( osTmpOriCSVTFilename );
    }

    VSILFILE* fp = VSIFOpenL( osFilename, "rb+" );
    if( fp == NULL )
    {
        CPLError(CE_Failure, CPLE_AppDefined, "Cannot reopen updated %s",
                 osFilename.c_str());
        *ppoDecoratedLayer = NULL;
        m_poCSVLayer = NULL;
        return OGRERR_FAILURE;
    }

    m_poCSVLayer = new OGRCSVLayer( osLayerName, fp,
                                    osFilename,
                                    false, /* new */
                                    true, /* update */
                                    chDelimiter );
    m_poCSVLayer->BuildFeatureDefn(NULL, NULL, m_papszOpenOptions);
    *ppoDecoratedLayer = m_poCSVLayer;

    return OGRERR_NONE;
}
Exemplo n.º 3
0
static CPLXMLNode* GDALWMSDatasetGetConfigFromArcGISJSON(const char* pszURL,
                                                         const char* pszContent)
{
    /* TODO : use JSONC library to parse. But we don't really need it */
    CPLString osTmpFilename(CPLSPrintf("/vsimem/WMSArcGISJSON%p", pszURL));
    VSILFILE* fp = VSIFileFromMemBuffer( osTmpFilename,
                                         (GByte*)pszContent,
                                         strlen(pszContent),
                                         FALSE);
    const char* pszLine;
    int nTileWidth = -1, nTileHeight = -1;
    int nWKID = -1;
    double dfMinX = 0, dfMaxY = 0;
    int bHasMinX = FALSE, bHasMaxY = FALSE;
    int nExpectedLevel = 0;
    double dfBaseResolution = 0;
    while((pszLine = CPLReadLine2L(fp, 4096, NULL)) != NULL)
    {
        const char* pszPtr;
        if ((pszPtr = strstr(pszLine, "\"rows\" : ")) != NULL)
            nTileHeight = atoi(pszPtr + strlen("\"rows\" : "));
        else if ((pszPtr = strstr(pszLine, "\"cols\" : ")) != NULL)
            nTileWidth = atoi(pszPtr + strlen("\"cols\" : "));
        else if ((pszPtr = strstr(pszLine, "\"wkid\" : ")) != NULL)
        {
            int nVal = atoi(pszPtr + strlen("\"wkid\" : "));
            if (nWKID < 0)
                nWKID = nVal;
            else if (nWKID != nVal)
            {
                CPLDebug("WMS", "Inconsisant WKID values : %d, %d", nVal, nWKID);
                VSIFCloseL(fp);
                return NULL;
            }
        }
        else if ((pszPtr = strstr(pszLine, "\"x\" : ")) != NULL)
        {
            bHasMinX = TRUE;
            dfMinX = CPLAtofM(pszPtr + strlen("\"x\" : "));
        }
        else if ((pszPtr = strstr(pszLine, "\"y\" : ")) != NULL)
        {
            bHasMaxY = TRUE;
            dfMaxY = CPLAtofM(pszPtr + strlen("\"y\" : "));
        }
        else if ((pszPtr = strstr(pszLine, "\"level\" : ")) != NULL)
        {
            int nLevel = atoi(pszPtr + strlen("\"level\" : "));
            if (nLevel != nExpectedLevel)
            {
                CPLDebug("WMS", "Expected level : %d, got : %d", nExpectedLevel, nLevel);
                VSIFCloseL(fp);
                return NULL;
            }

            if ((pszPtr = strstr(pszLine, "\"resolution\" : ")) != NULL)
            {
                double dfResolution = CPLAtofM(pszPtr + strlen("\"resolution\" : "));
                if (nLevel == 0)
                    dfBaseResolution = dfResolution;
            }
            else
            {
                CPLDebug("WMS", "Did not get resolution");
                VSIFCloseL(fp);
                return NULL;
            }
            nExpectedLevel ++;
        }
    }
    VSIFCloseL(fp);

    int nLevelCount = nExpectedLevel - 1;
    if (nLevelCount < 1)
    {
        CPLDebug("WMS", "Did not get levels");
        return NULL;
    }

    if (nTileWidth <= 0)
    {
        CPLDebug("WMS", "Did not get tile width");
        return NULL;
    }
    if (nTileHeight <= 0)
    {
        CPLDebug("WMS", "Did not get tile height");
        return NULL;
    }
    if (nWKID <= 0)
    {
        CPLDebug("WMS", "Did not get WKID");
        return NULL;
    }
    if (!bHasMinX)
    {
        CPLDebug("WMS", "Did not get min x");
        return NULL;
    }
    if (!bHasMaxY)
    {
        CPLDebug("WMS", "Did not get max y");
        return NULL;
    }
    
    if (nWKID == 102100)
        nWKID = 3857;

    const char* pszEndURL = strstr(pszURL, "/MapServer?f=json");
    CPLAssert(pszEndURL);
    CPLString osURL(pszURL);
    osURL.resize(pszEndURL - pszURL);

    double dfMaxX = dfMinX + dfBaseResolution * nTileWidth;
    double dfMinY = dfMaxY - dfBaseResolution * nTileHeight;

    int nTileCountX = 1;
    if (fabs(dfMinX - -180) < 1e-4 && fabs(dfMaxY - 90) < 1e-4 &&
        fabs(dfMinY - -90) < 1e-4)
    {
        nTileCountX = 2;
        dfMaxX = 180;
    }

    CPLString osXML = CPLSPrintf(
            "<GDAL_WMS>\n"
            "  <Service name=\"TMS\">\n"
            "    <ServerUrl>%s/MapServer/tile/${z}/${y}/${x}</ServerUrl>\n"
            "  </Service>\n"
            "  <DataWindow>\n"
            "    <UpperLeftX>%.8f</UpperLeftX>\n"
            "    <UpperLeftY>%.8f</UpperLeftY>\n"
            "    <LowerRightX>%.8f</LowerRightX>\n"
            "    <LowerRightY>%.8f</LowerRightY>\n"
            "    <TileLevel>%d</TileLevel>\n"
            "    <TileCountX>%d</TileCountX>\n"
            "    <YOrigin>top</YOrigin>\n"
            "  </DataWindow>\n"
            "  <Projection>EPSG:%d</Projection>\n"
            "  <BlockSizeX>%d</BlockSizeX>\n"
            "  <BlockSizeY>%d</BlockSizeY>\n"
            "  <Cache/>\n"
            "</GDAL_WMS>\n",
            osURL.c_str(),
            dfMinX, dfMaxY, dfMaxX, dfMinY,
            nLevelCount,
            nTileCountX,
            nWKID,
            nTileWidth, nTileHeight);
    CPLDebug("WMS", "Opening TMS :\n%s", osXML.c_str());

    return CPLParseXMLString(osXML);
}