Example #1
0
OGRErr OGRCSVLayer::WriteHeader()
{
    if( !bNew )
        return OGRERR_NONE;

/* -------------------------------------------------------------------- */
/*      Write field names if we haven't written them yet.               */
/*      Write .csvt file if needed                                      */
/* -------------------------------------------------------------------- */
    bNew = FALSE;
    bHasFieldNames = TRUE;

    for(int iFile=0;iFile<((bCreateCSVT) ? 2 : 1);iFile++)
    {
        VSILFILE* fpCSVT = NULL;
        if (bCreateCSVT && iFile == 0)
        {
            char* pszDirName = CPLStrdup(CPLGetDirname(pszFilename));
            char* pszBaseName = CPLStrdup(CPLGetBasename(pszFilename));
            fpCSVT = VSIFOpenL(CPLFormFilename(pszDirName, pszBaseName, ".csvt"), "wb");
            CPLFree(pszDirName);
            CPLFree(pszBaseName);
        }
        else
        {
            if( strncmp(pszFilename, "/vsistdout/", 11) == 0 ||
                strncmp(pszFilename, "/vsizip/", 8) == 0 )
                fpCSV = VSIFOpenL( pszFilename, "wb" );
            else
                fpCSV = VSIFOpenL( pszFilename, "w+b" );

            if( fpCSV == NULL )
            {
                CPLError( CE_Failure, CPLE_OpenFailed,
                          "Failed to create %s:\n%s",
                          pszFilename, VSIStrerror( errno ) );
                return OGRERR_FAILURE;
            }
        }

        if (bWriteBOM && fpCSV)
        {
            VSIFWriteL("\xEF\xBB\xBF", 1, 3, fpCSV);
        }

        if (eGeometryFormat == OGR_CSV_GEOM_AS_WKT)
        {
            if (fpCSV) VSIFPrintfL( fpCSV, "%s", "WKT");
            if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", "String");
            if (poFeatureDefn->GetFieldCount() > 0)
            {
                if (fpCSV) VSIFPrintfL( fpCSV, "%c", chDelimiter );
                if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", ",");
            }
        }
        else if (eGeometryFormat == OGR_CSV_GEOM_AS_XYZ)
        {
            if (fpCSV) VSIFPrintfL( fpCSV, "X%cY%cZ", chDelimiter, chDelimiter);
            if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", "Real,Real,Real");
            if (poFeatureDefn->GetFieldCount() > 0)
            {
                if (fpCSV) VSIFPrintfL( fpCSV, "%c", chDelimiter );
                if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", ",");
            }
        }
        else if (eGeometryFormat == OGR_CSV_GEOM_AS_XY)
        {
            if (fpCSV) VSIFPrintfL( fpCSV, "X%cY", chDelimiter);
            if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", "Real,Real");
            if (poFeatureDefn->GetFieldCount() > 0)
            {
                if (fpCSV) VSIFPrintfL( fpCSV, "%c", chDelimiter );
                if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", ",");
            }
        }
        else if (eGeometryFormat == OGR_CSV_GEOM_AS_YX)
        {
            if (fpCSV) VSIFPrintfL( fpCSV, "Y%cX", chDelimiter);
            if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", "Real,Real");
            if (poFeatureDefn->GetFieldCount() > 0)
            {
                if (fpCSV) VSIFPrintfL( fpCSV, "%c", chDelimiter );
                if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", ",");
            }
        }

        for( int iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
        {
            char *pszEscaped;

            if( iField > 0 )
            {
                if (fpCSV) VSIFPrintfL( fpCSV, "%c", chDelimiter );
                if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", ",");
            }

            pszEscaped = 
                CPLEscapeString( poFeatureDefn->GetFieldDefn(iField)->GetNameRef(), 
                                 -1, CPLES_CSV );

            if (fpCSV) VSIFPrintfL( fpCSV, "%s", pszEscaped );
            CPLFree( pszEscaped );

            if (fpCSVT)
            {
                switch( poFeatureDefn->GetFieldDefn(iField)->GetType() )
                {
                  case OFTInteger:  VSIFPrintfL( fpCSVT, "%s", "Integer"); break;
                  case OFTReal:     VSIFPrintfL( fpCSVT, "%s", "Real"); break;
                  case OFTDate:     VSIFPrintfL( fpCSVT, "%s", "Date"); break;
                  case OFTTime:     VSIFPrintfL( fpCSVT, "%s", "Time"); break;
                  case OFTDateTime: VSIFPrintfL( fpCSVT, "%s", "DateTime"); break;
                  default:          VSIFPrintfL( fpCSVT, "%s", "String"); break;
                }

                int nWidth = poFeatureDefn->GetFieldDefn(iField)->GetWidth();
                int nPrecision = poFeatureDefn->GetFieldDefn(iField)->GetPrecision();
                if (nWidth != 0)
                {
                    if (nPrecision != 0)
                        VSIFPrintfL( fpCSVT, "(%d.%d)", nWidth, nPrecision);
                    else
                        VSIFPrintfL( fpCSVT, "(%d)", nWidth);
                }
            }
        }

        /* The CSV driver will not recognize single column tables, so add */
        /* a fake second blank field */
        if( poFeatureDefn->GetFieldCount() == 1 )
        {
            if (fpCSV) VSIFPrintfL( fpCSV, "%c", chDelimiter );
        }

        if( bUseCRLF )
        {
            if (fpCSV) VSIFPutcL( 13, fpCSV );
            if (fpCSVT) VSIFPutcL( 13, fpCSVT );
        }
        if (fpCSV) VSIFPutcL( '\n', fpCSV );
        if (fpCSVT) VSIFPutcL( '\n', fpCSVT );
        if (fpCSVT) VSIFCloseL(fpCSVT);
    }

    if (fpCSV == NULL) 
        return OGRERR_FAILURE;
    else
        return OGRERR_NONE;
}
Example #2
0
static GDALDataset *
XPMCreateCopy( const char * pszFilename,
               CPL_UNUSED GDALDataset *poSrcDS,
               int bStrict,
               CPL_UNUSED char ** papszOptions,
               CPL_UNUSED GDALProgressFunc pfnProgress,
               CPL_UNUSED void * pProgressData )
{
    int  nBands = poSrcDS->GetRasterCount();
    int  nXSize = poSrcDS->GetRasterXSize();
    int  nYSize = poSrcDS->GetRasterYSize();
    GDALColorTable *poCT;

    /* -------------------------------------------------------------------- */
    /*      Some some rudimentary checks                                    */
    /* -------------------------------------------------------------------- */
    if( nBands != 1 )
    {
        CPLError( CE_Failure, CPLE_NotSupported,
                  "XPM driver only supports one band images.\n" );

        return NULL;
    }

    if( poSrcDS->GetRasterBand(1)->GetRasterDataType() != GDT_Byte
            && bStrict )
    {
        CPLError( CE_Failure, CPLE_NotSupported,
                  "XPM driver doesn't support data type %s. "
                  "Only eight bit bands supported.\n",
                  GDALGetDataTypeName(
                      poSrcDS->GetRasterBand(1)->GetRasterDataType()) );

        return NULL;
    }

    /* -------------------------------------------------------------------- */
    /*      If there is no colortable on the source image, create a         */
    /*      greyscale one with 64 levels of grey.                           */
    /* -------------------------------------------------------------------- */
    GDALRasterBand	*poBand = poSrcDS->GetRasterBand(1);
    int                 i;
    GDALColorTable      oGreyTable;

    poCT = poBand->GetColorTable();
    if( poCT == NULL )
    {
        poCT = &oGreyTable;

        for( i = 0; i < 256; i++ )
        {
            GDALColorEntry sColor;

            sColor.c1 = (short) i;
            sColor.c2 = (short) i;
            sColor.c3 = (short) i;
            sColor.c4 = 255;

            poCT->SetColorEntry( i, &sColor );
        }
    }

    /* -------------------------------------------------------------------- */
    /*      Build list of active colors, and the mapping from pixels to     */
    /*      our active colormap.                                            */
    /* -------------------------------------------------------------------- */
    const char *pszColorCodes = " abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-+=[]|:;,.<>?/";

    int  anPixelMapping[256];
    GDALColorEntry asPixelColor[256];
    int  nActiveColors = MIN(poCT->GetColorEntryCount(),256);

    // Setup initial colortable and pixel value mapping.
    memset( anPixelMapping+0, 0, sizeof(int) * 256 );
    for( i = 0; i < nActiveColors; i++ )
    {
        poCT->GetColorEntryAsRGB( i, asPixelColor + i );
        anPixelMapping[i] = i;
    }

    /* ==================================================================== */
    /*      Iterate merging colors until we are under our limit (about 85). */
    /* ==================================================================== */
    while( nActiveColors > (int) strlen(pszColorCodes) )
    {
        int nClosestDistance = 768;
        int iClose1 = -1, iClose2 = -1;
        int iColor1, iColor2;

        // Find the closest pair of colors.
        for( iColor1 = 0; iColor1 < nActiveColors; iColor1++ )
        {
            for( iColor2 = iColor1+1; iColor2 < nActiveColors; iColor2++ )
            {
                int	nDistance;

                if( asPixelColor[iColor1].c4 < 128
                        && asPixelColor[iColor2].c4 < 128 )
                    nDistance = 0;
                else
                    nDistance =
                        ABS(asPixelColor[iColor1].c1-asPixelColor[iColor2].c1)
                        + ABS(asPixelColor[iColor1].c2-asPixelColor[iColor2].c2)
                        + ABS(asPixelColor[iColor1].c3-asPixelColor[iColor2].c3);

                if( nDistance < nClosestDistance )
                {
                    nClosestDistance = nDistance;
                    iClose1 = iColor1;
                    iClose2 = iColor2;
                }
            }

            if( nClosestDistance < 8 )
                break;
        }

        // This should never happen!
        if( iClose1 == -1 )
            break;

        // Merge two selected colors - shift icolor2 into icolor1 and
        // move the last active color into icolor2's slot.
        for( i = 0; i < 256; i++ )
        {
            if( anPixelMapping[i] == iClose2 )
                anPixelMapping[i] = iClose1;
            else if( anPixelMapping[i] == nActiveColors-1 )
                anPixelMapping[i] = iClose2;
        }

        asPixelColor[iClose2] = asPixelColor[nActiveColors-1];
        nActiveColors--;
    }

    /* ==================================================================== */
    /*      Write the output image.                                         */
    /* ==================================================================== */
    VSILFILE	*fpPBM;

    fpPBM = VSIFOpenL( pszFilename, "wb+" );
    if( fpPBM == NULL )
    {
        CPLError( CE_Failure, CPLE_OpenFailed,
                  "Unable to create file `%s'.",
                  pszFilename );

        return NULL;
    }

    /* -------------------------------------------------------------------- */
    /*      Write the header lines.                                         */
    /* -------------------------------------------------------------------- */
    VSIFPrintfL( fpPBM, "/* XPM */\n" );
    VSIFPrintfL( fpPBM, "static char *%s[] = {\n",
                 CPLGetBasename( pszFilename ) );
    VSIFPrintfL( fpPBM, "/* width height num_colors chars_per_pixel */\n" );
    VSIFPrintfL( fpPBM, "\"  %3d   %3d     %3d             1\",\n",
                 nXSize, nYSize, nActiveColors );
    VSIFPrintfL( fpPBM, "/* colors */\n" );

    /* -------------------------------------------------------------------- */
    /*      Write the color table.                                          */
    /* -------------------------------------------------------------------- */
    for( i = 0; i < nActiveColors; i++ )
    {
        if( asPixelColor[i].c4 < 128 )
            VSIFPrintfL( fpPBM, "\"%c c None\",\n", pszColorCodes[i] );
        else
            VSIFPrintfL( fpPBM,
                         "\"%c c #%02x%02x%02x\",\n",
                         pszColorCodes[i],
                         asPixelColor[i].c1,
                         asPixelColor[i].c2,
                         asPixelColor[i].c3 );
    }

    /* -------------------------------------------------------------------- */
    /*	Dump image.							*/
    /* -------------------------------------------------------------------- */
    int iLine;
    GByte 	*pabyScanline;

    pabyScanline = (GByte *) CPLMalloc( nXSize );
    for( iLine = 0; iLine < nYSize; iLine++ )
    {
        poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1,
                          (void *) pabyScanline, nXSize, 1, GDT_Byte, 0, 0, NULL );

        VSIFPutcL( '"', fpPBM );
        for( int iPixel = 0; iPixel < nXSize; iPixel++ )
            VSIFPutcL( pszColorCodes[anPixelMapping[pabyScanline[iPixel]]],
                       fpPBM);
        VSIFPrintfL( fpPBM, "\",\n" );
    }

    CPLFree( pabyScanline );

    /* -------------------------------------------------------------------- */
    /*      cleanup                                                         */
    /* -------------------------------------------------------------------- */
    VSIFPrintfL( fpPBM, "};\n" );
    VSIFCloseL( fpPBM );

    /* -------------------------------------------------------------------- */
    /*      Re-open dataset, and copy any auxiliary pam information.         */
    /* -------------------------------------------------------------------- */
    GDALPamDataset *poDS = (GDALPamDataset *)
                           GDALOpen( pszFilename, GA_ReadOnly );

    if( poDS )
        poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );

    return poDS;
}
Example #3
0
OGRErr OGRCSVLayer::CreateFeature( OGRFeature *poNewFeature )

{
    int iField;

    if( !bInWriteMode )
    {
        CPLError( CE_Failure, CPLE_AppDefined, 
            "The CreateFeature() operation is not permitted on a read-only CSV." );
        return OGRERR_FAILURE;
    }

    /* If we need rewind, it means that we have just written a feature before */
    /* so there's no point seeking to the end of the file, as we're already */
    /* at the end */
    int bNeedSeekEnd = !bNeedRewindBeforeRead;

    bNeedRewindBeforeRead = TRUE;

/* -------------------------------------------------------------------- */
/*      Write field names if we haven't written them yet.               */
/*      Write .csvt file if needed                                      */
/* -------------------------------------------------------------------- */
    if( bNew )
    {
        OGRErr eErr = WriteHeader();
        if (eErr != OGRERR_NONE)
            return eErr;
        bNeedSeekEnd = FALSE;
    }

    if (fpCSV == NULL)
        return OGRERR_FAILURE;

/* -------------------------------------------------------------------- */
/*      Make sure we are at the end of the file.                        */
/* -------------------------------------------------------------------- */
    if (bNeedSeekEnd)
    {
        if (bFirstFeatureAppendedDuringSession)
        {
            /* Add a newline character to the end of the file if necessary */
            bFirstFeatureAppendedDuringSession = FALSE;
            VSIFSeekL( fpCSV, 0, SEEK_END );
            VSIFSeekL( fpCSV, VSIFTellL(fpCSV) - 1, SEEK_SET);
            char chLast;
            VSIFReadL( &chLast, 1, 1, fpCSV );
            VSIFSeekL( fpCSV, 0, SEEK_END );
            if (chLast != '\n')
            {
                if( bUseCRLF )
                    VSIFPutcL( 13, fpCSV );
                VSIFPutcL( '\n', fpCSV );
            }
        }
        else
        {
            VSIFSeekL( fpCSV, 0, SEEK_END );
        }
    }

/* -------------------------------------------------------------------- */
/*      Write out the geometry                                          */
/* -------------------------------------------------------------------- */
    if (eGeometryFormat == OGR_CSV_GEOM_AS_WKT)
    {
        OGRGeometry     *poGeom = poNewFeature->GetGeometryRef();
        char* pszWKT = NULL;
        if (poGeom && poGeom->exportToWkt(&pszWKT) == OGRERR_NONE)
        {
            VSIFPrintfL( fpCSV, "\"%s\"", pszWKT);
        }
        else
        {
            VSIFPrintfL( fpCSV, "\"\"");
        }
        CPLFree(pszWKT);
        if (poFeatureDefn->GetFieldCount() > 0)
            VSIFPrintfL( fpCSV, "%c", chDelimiter);
    }
    else if (eGeometryFormat == OGR_CSV_GEOM_AS_XYZ ||
             eGeometryFormat == OGR_CSV_GEOM_AS_XY ||
             eGeometryFormat == OGR_CSV_GEOM_AS_YX)
    {
        OGRGeometry     *poGeom = poNewFeature->GetGeometryRef();
        if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint)
        {
            OGRPoint* poPoint = (OGRPoint*) poGeom;
            char szBuffer[75];
            if (eGeometryFormat == OGR_CSV_GEOM_AS_XYZ )
                OGRMakeWktCoordinate(szBuffer, poPoint->getX(), poPoint->getY(), poPoint->getZ(), 3);
            else if (eGeometryFormat == OGR_CSV_GEOM_AS_XY )
                OGRMakeWktCoordinate(szBuffer, poPoint->getX(), poPoint->getY(), 0, 2);
            else
                OGRMakeWktCoordinate(szBuffer, poPoint->getY(), poPoint->getX(), 0, 2);
            char* pc = szBuffer;
            while(*pc != '\0')
            {
                if (*pc == ' ')
                    *pc = chDelimiter;
                pc ++;
            }
            VSIFPrintfL( fpCSV, "%s", szBuffer );
        }
        else
        {
            VSIFPrintfL( fpCSV, "%c", chDelimiter );
            if (eGeometryFormat == OGR_CSV_GEOM_AS_XYZ)
                VSIFPrintfL( fpCSV, "%c", chDelimiter );
        }
        if (poFeatureDefn->GetFieldCount() > 0)
            VSIFPrintfL( fpCSV, "%c", chDelimiter );
    }

/* -------------------------------------------------------------------- */
/*      Write out all the field values.                                 */
/* -------------------------------------------------------------------- */
    int bNonEmptyLine = FALSE;
    for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
    {
        char *pszEscaped;
        
        if( iField > 0 )
            VSIFPrintfL( fpCSV, "%c", chDelimiter );
        
        if (poFeatureDefn->GetFieldDefn(iField)->GetType() == OFTReal)
        {
            pszEscaped = CPLStrdup(poNewFeature->GetFieldAsString(iField));
            /* Use point as decimal separator */
            char* pszComma = strchr(pszEscaped, ',');
            if (pszComma)
                *pszComma = '.';
        }
        else
        {
            pszEscaped =
                CPLEscapeString( poNewFeature->GetFieldAsString(iField),
                                -1, CPLES_CSV );
        }

        int nLen = (int)strlen(pszEscaped);
        bNonEmptyLine |= (nLen != 0);
        VSIFWriteL( pszEscaped, 1, nLen, fpCSV );
        CPLFree( pszEscaped );
    }

    if(  poFeatureDefn->GetFieldCount() == 1 && !bNonEmptyLine )
        VSIFPrintfL( fpCSV, "%c", chDelimiter );

    if( bUseCRLF )
        VSIFPutcL( 13, fpCSV );
    VSIFPutcL( '\n', fpCSV );

    return OGRERR_NONE;
}
Example #4
0
OGRErr OGRCSVLayer::CreateFeature( OGRFeature *poNewFeature )

{
    int iField;

    if( !bInWriteMode )
    {
        CPLError( CE_Failure, CPLE_AppDefined, 
            "The CreateFeature() operation is not permitted on a read-only CSV." );
        return OGRERR_FAILURE;
    }

    /* If we need rewind, it means that we have just written a feature before */
    /* so there's no point seeking to the end of the file, as we're already */
    /* at the end */
    int bNeedSeekEnd = !bNeedRewindBeforeRead;

    bNeedRewindBeforeRead = TRUE;

/* -------------------------------------------------------------------- */
/*      Write field names if we haven't written them yet.               */
/*      Write .csvt file if needed                                      */
/* -------------------------------------------------------------------- */
    if( !bHasFieldNames )
    {
      bHasFieldNames = TRUE;
      bNeedSeekEnd = FALSE;

      for(int iFile=0;iFile<((bCreateCSVT) ? 2 : 1);iFile++)
      {
        VSILFILE* fpCSVT = NULL;
        if (bCreateCSVT && iFile == 0)
        {
            char* pszDirName = CPLStrdup(CPLGetDirname(pszFilename));
            char* pszBaseName = CPLStrdup(CPLGetBasename(pszFilename));
            fpCSVT = VSIFOpenL(CPLFormFilename(pszDirName, pszBaseName, ".csvt"), "wb");
            CPLFree(pszDirName);
            CPLFree(pszBaseName);
        }
        else
        {
            if( strncmp(pszFilename, "/vsistdout/", 11) == 0 ||
                strncmp(pszFilename, "/vsizip/", 8) == 0 )
                fpCSV = VSIFOpenL( pszFilename, "wb" );
            else
                fpCSV = VSIFOpenL( pszFilename, "w+b" );

            if( fpCSV == NULL )
            {
                CPLError( CE_Failure, CPLE_OpenFailed,
                        "Failed to create %s:\n%s",
                        pszFilename, VSIStrerror( errno ) );

                return NULL;
            }
        }

        if (eGeometryFormat == OGR_CSV_GEOM_AS_WKT)
        {
            if (fpCSV) VSIFPrintfL( fpCSV, "%s", "WKT");
            if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", "String");
            if (poFeatureDefn->GetFieldCount() > 0)
            {
                if (fpCSV) VSIFPrintfL( fpCSV, "%c", chDelimiter );
                if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", ",");
            }
        }
        else if (eGeometryFormat == OGR_CSV_GEOM_AS_XYZ)
        {
            if (fpCSV) VSIFPrintfL( fpCSV, "X%cY%cZ", chDelimiter, chDelimiter);
            if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", "Real,Real,Real");
            if (poFeatureDefn->GetFieldCount() > 0)
            {
                if (fpCSV) VSIFPrintfL( fpCSV, "%c", chDelimiter );
                if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", ",");
            }
        }
        else if (eGeometryFormat == OGR_CSV_GEOM_AS_XY)
        {
            if (fpCSV) VSIFPrintfL( fpCSV, "X%cY", chDelimiter);
            if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", "Real,Real");
            if (poFeatureDefn->GetFieldCount() > 0)
            {
                if (fpCSV) VSIFPrintfL( fpCSV, "%c", chDelimiter );
                if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", ",");
            }
        }
        else if (eGeometryFormat == OGR_CSV_GEOM_AS_YX)
        {
            if (fpCSV) VSIFPrintfL( fpCSV, "Y%cX", chDelimiter);
            if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", "Real,Real");
            if (poFeatureDefn->GetFieldCount() > 0)
            {
                if (fpCSV) VSIFPrintfL( fpCSV, "%c", chDelimiter );
                if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", ",");
            }
        }

        for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
        {
            char *pszEscaped;

            if( iField > 0 )
            {
                if (fpCSV) VSIFPrintfL( fpCSV, "%c", chDelimiter );
                if (fpCSVT) VSIFPrintfL( fpCSVT, "%s", ",");
            }

            pszEscaped = 
                CPLEscapeString( poFeatureDefn->GetFieldDefn(iField)->GetNameRef(), 
                                 -1, CPLES_CSV );

            if (fpCSV) VSIFPrintfL( fpCSV, "%s", pszEscaped );
            CPLFree( pszEscaped );

            if (fpCSVT)
            {
                switch( poFeatureDefn->GetFieldDefn(iField)->GetType() )
                {
                    case OFTInteger:  VSIFPrintfL( fpCSVT, "%s", "Integer"); break;
                    case OFTReal:     VSIFPrintfL( fpCSVT, "%s", "Real"); break;
                    case OFTDate:     VSIFPrintfL( fpCSVT, "%s", "Date"); break;
                    case OFTTime:     VSIFPrintfL( fpCSVT, "%s", "Time"); break;
                    case OFTDateTime: VSIFPrintfL( fpCSVT, "%s", "DateTime"); break;
                    default:          VSIFPrintfL( fpCSVT, "%s", "String"); break;
                }

                int nWidth = poFeatureDefn->GetFieldDefn(iField)->GetWidth();
                int nPrecision = poFeatureDefn->GetFieldDefn(iField)->GetPrecision();
                if (nWidth != 0)
                {
                    if (nPrecision != 0)
                        VSIFPrintfL( fpCSVT, "(%d.%d)", nWidth, nPrecision);
                    else
                        VSIFPrintfL( fpCSVT, "(%d)", nWidth);
                }
            }
        }
        if( bUseCRLF )
        {
            if (fpCSV) VSIFPutcL( 13, fpCSV );
            if (fpCSVT) VSIFPutcL( 13, fpCSVT );
        }
        if (fpCSV) VSIFPutcL( '\n', fpCSV );
        if (fpCSVT) VSIFPutcL( '\n', fpCSVT );
        if (fpCSVT) VSIFCloseL(fpCSVT);
      }
    }

    if (fpCSV == NULL)
        return OGRERR_FAILURE;

/* -------------------------------------------------------------------- */
/*      Make sure we are at the end of the file.                        */
/* -------------------------------------------------------------------- */
    if (bNeedSeekEnd)
    {
        if (bFirstFeatureAppendedDuringSession)
        {
            /* Add a newline character to the end of the file if necessary */
            bFirstFeatureAppendedDuringSession = FALSE;
            VSIFSeekL( fpCSV, 0, SEEK_END );
            VSIFSeekL( fpCSV, VSIFTellL(fpCSV) - 1, SEEK_SET);
            char chLast;
            VSIFReadL( &chLast, 1, 1, fpCSV );
            VSIFSeekL( fpCSV, 0, SEEK_END );
            if (chLast != '\n')
            {
                if( bUseCRLF )
                    VSIFPutcL( 13, fpCSV );
                VSIFPutcL( '\n', fpCSV );
            }
        }
        else
        {
            VSIFSeekL( fpCSV, 0, SEEK_END );
        }
    }

/* -------------------------------------------------------------------- */
/*      Write out the geometry                                          */
/* -------------------------------------------------------------------- */
    if (eGeometryFormat == OGR_CSV_GEOM_AS_WKT)
    {
        OGRGeometry     *poGeom = poNewFeature->GetGeometryRef();
        char* pszWKT = NULL;
        if (poGeom && poGeom->exportToWkt(&pszWKT) == OGRERR_NONE)
        {
            VSIFPrintfL( fpCSV, "\"%s\"", pszWKT);
        }
        else
        {
            VSIFPrintfL( fpCSV, "\"\"");
        }
        CPLFree(pszWKT);
        if (poFeatureDefn->GetFieldCount() > 0)
            VSIFPrintfL( fpCSV, "%c", chDelimiter);
    }
    else if (eGeometryFormat == OGR_CSV_GEOM_AS_XYZ ||
             eGeometryFormat == OGR_CSV_GEOM_AS_XY ||
             eGeometryFormat == OGR_CSV_GEOM_AS_YX)
    {
        OGRGeometry     *poGeom = poNewFeature->GetGeometryRef();
        if (poGeom && wkbFlatten(poGeom->getGeometryType()) == wkbPoint)
        {
            OGRPoint* poPoint = (OGRPoint*) poGeom;
            char szBuffer[75];
            if (eGeometryFormat == OGR_CSV_GEOM_AS_XYZ )
                OGRMakeWktCoordinate(szBuffer, poPoint->getX(), poPoint->getY(), poPoint->getZ(), 3);
            else if (eGeometryFormat == OGR_CSV_GEOM_AS_XY )
                OGRMakeWktCoordinate(szBuffer, poPoint->getX(), poPoint->getY(), 0, 2);
            else
                OGRMakeWktCoordinate(szBuffer, poPoint->getY(), poPoint->getX(), 0, 2);
            char* pc = szBuffer;
            while(*pc != '\0')
            {
                if (*pc == ' ')
                    *pc = chDelimiter;
                pc ++;
            }
            VSIFPrintfL( fpCSV, "%s", szBuffer );
        }
        else
        {
            VSIFPrintfL( fpCSV, "%c", chDelimiter );
            if (eGeometryFormat == OGR_CSV_GEOM_AS_XYZ)
                VSIFPrintfL( fpCSV, "%c", chDelimiter );
        }
        if (poFeatureDefn->GetFieldCount() > 0)
            VSIFPrintfL( fpCSV, "%c", chDelimiter );
    }

/* -------------------------------------------------------------------- */
/*      Write out all the field values.                                 */
/* -------------------------------------------------------------------- */
    for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
    {
        char *pszEscaped;
        
        if( iField > 0 )
            VSIFPrintfL( fpCSV, "%c", chDelimiter );
        
        pszEscaped = 
            CPLEscapeString( poNewFeature->GetFieldAsString(iField),
                            -1, CPLES_CSV );

        if (poFeatureDefn->GetFieldDefn(iField)->GetType() == OFTReal)
        {
            /* Use point as decimal separator */
            char* pszComma = strchr(pszEscaped, ',');
            if (pszComma)
                *pszComma = '.';
        }

        VSIFWriteL( pszEscaped, 1, strlen(pszEscaped), fpCSV );
        CPLFree( pszEscaped );
    }
    
    if( bUseCRLF )
        VSIFPutcL( 13, fpCSV );
    VSIFPutcL( '\n', fpCSV );

    return OGRERR_NONE;
}