static GDALDataset *
XPMCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
               int bStrict, char ** papszOptions, 
               GDALProgressFunc pfnProgress, 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 );
        
        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 auxilary pam information.         */
/* -------------------------------------------------------------------- */
    GDALPamDataset *poDS = (GDALPamDataset *) 
        GDALOpen( pszFilename, GA_ReadOnly );

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

    return poDS;
}
Esempio n. 2
0
GDALDataset *GS7BGDataset::CreateCopy( const char *pszFilename,
                                       GDALDataset *poSrcDS,
                                       int bStrict,
                                       CPL_UNUSED char **papszOptions,
                                       GDALProgressFunc pfnProgress,
                                       void *pProgressData )
{
    if( pfnProgress == NULL )
        pfnProgress = GDALDummyProgress;

    int nBands = poSrcDS->GetRasterCount();
    if (nBands == 0)
    {
        CPLError( CE_Failure, CPLE_NotSupported, 
                  "Driver does not support source dataset with zero band.\n");
        return NULL;
    }
    else if (nBands > 1)
    {
        if( bStrict )
        {
            CPLError( CE_Failure, CPLE_NotSupported,
                "Unable to create copy, "
                "format only supports one raster band.\n" );
            return NULL;
        }
        else
            CPLError( CE_Warning, CPLE_NotSupported,
                "Format only supports one "
                "raster band, first band will be copied.\n" );
    }

    GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( 1 );
    
    if( !pfnProgress( 0.0, NULL, pProgressData ) )
    {
        CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated\n" );
        return NULL;
    }

    VSILFILE    *fp = VSIFOpenL( pszFilename, "w+b" );

    if( fp == NULL )
    {
        CPLError( CE_Failure, CPLE_OpenFailed,
                  "Attempt to create file '%s' failed.\n",
                  pszFilename );
        return NULL;
    }

    GInt32  nXSize = poSrcBand->GetXSize();
    GInt32  nYSize = poSrcBand->GetYSize();
    double  adfGeoTransform[6];

    poSrcDS->GetGeoTransform( adfGeoTransform );

    double dfMinX = adfGeoTransform[0] + adfGeoTransform[1] / 2;
    double dfMaxX = adfGeoTransform[1] * (nXSize - 0.5) + adfGeoTransform[0];
    double dfMinY = adfGeoTransform[5] * (nYSize - 0.5) + adfGeoTransform[3];
    double dfMaxY = adfGeoTransform[3] + adfGeoTransform[5] / 2;
    CPLErr eErr = WriteHeader( fp, nXSize, nYSize,
                   dfMinX, dfMaxX, dfMinY, dfMaxY, 0.0, 0.0 );

    if( eErr != CE_None )
    {
        VSIFCloseL( fp );
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Copy band data.                                                 */
/* -------------------------------------------------------------------- */
    double *pfData = (double *)VSIMalloc2( nXSize, sizeof( double ) );
    if( pfData == NULL )
    {
        VSIFCloseL( fp );
        CPLError( CE_Failure, CPLE_OutOfMemory,
              "Unable to create copy, unable to allocate line buffer.\n" );
        return NULL;
    }

    int     bSrcHasNDValue;
    double   dfSrcNoDataValue = poSrcBand->GetNoDataValue( &bSrcHasNDValue );
    double  dfMinZ = DBL_MAX;
    double  dfMaxZ = -DBL_MAX;
    for( GInt32 iRow = nYSize - 1; iRow >= 0; iRow-- )
    {
        eErr = poSrcBand->RasterIO( GF_Read, 0, iRow,
                    nXSize, 1, pfData,
                    nXSize, 1, GDT_Float64, 0, 0, NULL );

        if( eErr != CE_None )
        {
            VSIFCloseL( fp );
            VSIFree( pfData );
            return NULL;
        }

        for( int iCol=0; iCol<nXSize; iCol++ )
        {
            if( bSrcHasNDValue && pfData[iCol] == dfSrcNoDataValue )
            {
                pfData[iCol] = dfNoData_Value;
            }
            else
            {
                if( pfData[iCol] > dfMaxZ )
                    dfMaxZ = pfData[iCol];

                if( pfData[iCol] < dfMinZ )
                    dfMinZ = pfData[iCol];
            }

            CPL_LSBPTR32( pfData+iCol );
        }

        if( VSIFWriteL( (void *)pfData, sizeof( double ), nXSize,
                fp ) != static_cast<unsigned>(nXSize) )
        {
            VSIFCloseL( fp );
            VSIFree( pfData );
            CPLError( CE_Failure, CPLE_FileIO,
                "Unable to write grid row. Disk full?\n" );
            return NULL;
        }

        if( !pfnProgress( static_cast<double>(nYSize - iRow)/nYSize,
                NULL, pProgressData ) )
        {
            VSIFCloseL( fp );
            VSIFree( pfData );
            CPLError( CE_Failure, CPLE_UserInterrupt, "User terminated" );
            return NULL;
        }
    }

    VSIFree( pfData );

    /* write out the min and max values */
    eErr = WriteHeader( fp, nXSize, nYSize,
            dfMinX, dfMaxX, dfMinY, dfMaxY, dfMinZ, dfMaxZ );

    if( eErr != CE_None )
    {
        VSIFCloseL( fp );
        return NULL;
    }

    VSIFCloseL( fp );

    GDALPamDataset *poDS = (GDALPamDataset *)GDALOpen( pszFilename,
                                                GA_Update );
    if (poDS)
    {
        poDS->CloneInfo( poSrcDS, GCIF_PAM_DEFAULT );
    }

    return poDS;
}
Esempio n. 3
0
GDALDataset * SRTMHGTDataset::CreateCopy( const char * pszFilename,
                                          GDALDataset *poSrcDS,
                                          int bStrict,
                                          CPL_UNUSED char ** papszOptions,
                                          GDALProgressFunc pfnProgress,
                                          void * pProgressData )
{
    if( pfnProgress && !pfnProgress( 0.0, NULL, pProgressData ) )
        return NULL;

/* -------------------------------------------------------------------- */
/*      Some some rudimentary checks                                    */
/* -------------------------------------------------------------------- */
    const int nBands = poSrcDS->GetRasterCount();
    if (nBands == 0)
    {
        CPLError( CE_Failure, CPLE_NotSupported,
                  "SRTMHGT driver does not support source dataset with zero band.\n");
        return NULL;
    }
    else if (nBands != 1)
    {
        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
                  "SRTMHGT driver only uses the first band of the dataset.\n");
        if (bStrict)
            return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Checks the input SRS                                            */
/* -------------------------------------------------------------------- */
    OGRSpatialReference ogrsr_input;
    char* c = const_cast<char *>( poSrcDS->GetProjectionRef() );
    ogrsr_input.importFromWkt(&c);

    OGRSpatialReference ogrsr_wgs84;
    ogrsr_wgs84.SetWellKnownGeogCS( "WGS84" );

    if ( ogrsr_input.IsSameGeogCS(&ogrsr_wgs84) == FALSE)
    {
        CPLError( CE_Warning, CPLE_AppDefined,
                  "The source projection coordinate system is %s. Only WGS 84 "
                  "is supported.\nThe SRTMHGT driver will generate a file as "
                  "if the source was WGS 84 projection coordinate system.",
                  poSrcDS->GetProjectionRef() );
    }

/* -------------------------------------------------------------------- */
/*      Work out the LL origin.                                         */
/* -------------------------------------------------------------------- */
    double adfGeoTransform[6];
    if (poSrcDS->GetGeoTransform( adfGeoTransform ) != CE_None)
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                  "Source image must have a geo transform matrix.");
        return NULL;
    }

    const int nLLOriginLat = static_cast<int>(
        std::floor(adfGeoTransform[3]
              + poSrcDS->GetRasterYSize() * adfGeoTransform[5] + 0.5) );

    int nLLOriginLong = static_cast<int>(
        std::floor(adfGeoTransform[0] + 0.5) );

    if (std::abs(nLLOriginLat - (
            adfGeoTransform[3] + (poSrcDS->GetRasterYSize() - 0.5 )
            * adfGeoTransform[5] ) ) > 1e-10 ||
        std::abs(nLLOriginLong - (
            adfGeoTransform[0] + 0.5 * adfGeoTransform[1])) > 1e-10 )
    {
        CPLError( CE_Warning, CPLE_AppDefined,
               "The corner coordinates of the source are not properly "
               "aligned on plain latitude/longitude boundaries.");
    }

/* -------------------------------------------------------------------- */
/*      Check image dimensions.                                         */
/* -------------------------------------------------------------------- */
    const int nXSize = poSrcDS->GetRasterXSize();
    const int nYSize = poSrcDS->GetRasterYSize();

    if (!((nXSize == 1201 && nYSize == 1201) || (nXSize == 3601 && nYSize == 3601)))
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                  "Image dimensions should be 1201x1201 or 3601x3601.");
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Check filename.                                                 */
/* -------------------------------------------------------------------- */
    char expectedFileName[12];
    snprintf(expectedFileName, sizeof(expectedFileName), "%c%02d%c%03d.HGT",
             (nLLOriginLat >= 0) ? 'N' : 'S',
             (nLLOriginLat >= 0) ? nLLOriginLat : -nLLOriginLat,
             (nLLOriginLong >= 0) ? 'E' : 'W',
             (nLLOriginLong >= 0) ? nLLOriginLong : -nLLOriginLong);
    if (!EQUAL(expectedFileName, CPLGetFilename(pszFilename)))
    {
        CPLError( CE_Warning, CPLE_AppDefined,
                  "Expected output filename is %s.", expectedFileName);
    }

/* -------------------------------------------------------------------- */
/*      Write output file.                                              */
/* -------------------------------------------------------------------- */
    VSILFILE* fp = VSIFOpenL(pszFilename, "wb");
    if (fp == NULL)
    {
        CPLError( CE_Failure, CPLE_FileIO,
                  "Cannot create file %s", pszFilename );
        return NULL;
    }

    GInt16* panData
        = reinterpret_cast<GInt16 *>( CPLMalloc(sizeof(GInt16) * nXSize) );
    GDALRasterBand* poSrcBand = poSrcDS->GetRasterBand(1);

    int bSrcBandHasNoData;
    double srcBandNoData = poSrcBand->GetNoDataValue(&bSrcBandHasNoData);

    for( int iY = 0; iY < nYSize; iY++ )
    {
        if( poSrcBand->RasterIO( GF_Read, 0, iY, nXSize, 1,
                                 reinterpret_cast<void *>( panData ), nXSize, 1,
                                 GDT_Int16, 0, 0, NULL ) != CE_None )
        {
            VSIFCloseL(fp);
            CPLFree( panData );
            return NULL;
        }

        /* Translate nodata values */
        if (bSrcBandHasNoData && srcBandNoData != SRTMHG_NODATA_VALUE)
        {
            for( int iX = 0; iX < nXSize; iX++ )
            {
                if (panData[iX] == srcBandNoData)
                    panData[iX] = SRTMHG_NODATA_VALUE;
            }
        }

#ifdef CPL_LSB
        GDALSwapWords(panData, 2, nXSize, 2);
#endif

        if( VSIFWriteL( panData,sizeof(GInt16) * nXSize,1,fp ) != 1)
        {
            CPLError( CE_Failure, CPLE_FileIO,
                      "Failed to write line %d in SRTMHGT dataset.\n",
                      iY );
            VSIFCloseL(fp);
            CPLFree( panData );
            return NULL;
        }

        if( pfnProgress && !pfnProgress( (iY+1) / static_cast<double>( nYSize ),
                                         NULL, pProgressData ) )
        {
            CPLError( CE_Failure, CPLE_UserInterrupt,
                        "User terminated CreateCopy()" );
            VSIFCloseL(fp);
            CPLFree( panData );
            return NULL;
        }
    }

    CPLFree( panData );
    VSIFCloseL(fp);

/* -------------------------------------------------------------------- */
/*      Reopen and copy missing information into a PAM file.            */
/* -------------------------------------------------------------------- */
    GDALPamDataset *poDS = reinterpret_cast<GDALPamDataset *>(
        GDALOpen( pszFilename, GA_ReadOnly ) );

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

    return poDS;
}
Esempio n. 4
0
GDALDataset *
RCreateCopy( const char * pszFilename, GDALDataset *poSrcDS, 
             int bStrict, char ** papszOptions, 
             GDALProgressFunc pfnProgress, void * pProgressData )

{
    int  nBands = poSrcDS->GetRasterCount();
    int  nXSize = poSrcDS->GetRasterXSize();
    int  nYSize = poSrcDS->GetRasterYSize();
    int  bASCII = CSLFetchBoolean( papszOptions, "ASCII", FALSE );
    int  bCompressed = CSLFetchBoolean( papszOptions, "COMPRESS", !bASCII );

/* -------------------------------------------------------------------- */
/*      Some some rudimentary checks                                    */
/* -------------------------------------------------------------------- */

/* -------------------------------------------------------------------- */
/*      Setup the filename to actually use.  We prefix with             */
/*      /vsigzip/ if we want compressed output.                         */
/* -------------------------------------------------------------------- */
    CPLString osAdjustedFilename;

    if( bCompressed )
        osAdjustedFilename = "/vsigzip/";

    osAdjustedFilename += pszFilename;

/* -------------------------------------------------------------------- */
/*      Create the file.                                                */
/* -------------------------------------------------------------------- */
    FILE	*fp;

    fp = VSIFOpenL( osAdjustedFilename, "wb" );
    if( fp == NULL )
    {
        CPLError( CE_Failure, CPLE_OpenFailed, 
                  "Unable to create file %s.\n", 
                  pszFilename );
        return NULL;
    }

/* -------------------------------------------------------------------- */
/*      Write header with version, etc.                                 */
/* -------------------------------------------------------------------- */
    if( bASCII )
    {
        const char *pszHeader = "RDA2\nA\n";
        VSIFWriteL( pszHeader, 1, strlen(pszHeader), fp );
    }
    else
    {
        const char *pszHeader = "RDX2\nX\n";
        VSIFWriteL( pszHeader, 1, strlen(pszHeader), fp );
    }

    RWriteInteger( fp, bASCII, 2 );
    RWriteInteger( fp, bASCII, 133377 );
    RWriteInteger( fp, bASCII, 131840 );

/* -------------------------------------------------------------------- */
/*      Establish the primary pairlist with one component object.       */
/* -------------------------------------------------------------------- */
    RWriteInteger( fp, bASCII, 1026 );
    RWriteInteger( fp, bASCII, 1 );  

/* -------------------------------------------------------------------- */
/*      Write the object name.  Eventually we should derive this        */
/*      from the filename, possible with override by a creation         */
/*      option.                                                         */
/* -------------------------------------------------------------------- */
    RWriteString( fp, bASCII, "gg" );

/* -------------------------------------------------------------------- */
/*      For now we write the raster as a numeric array with             */
/*      attributes (526).                                               */
/* -------------------------------------------------------------------- */
    RWriteInteger( fp, bASCII, 526 );
    RWriteInteger( fp, bASCII, nXSize * nYSize * nBands );

/* -------------------------------------------------------------------- */
/*      Write the raster data.                                          */
/* -------------------------------------------------------------------- */
    double 	*padfScanline;
    CPLErr      eErr = CE_None;
    int         iLine;

    padfScanline = (double *) CPLMalloc( nXSize * sizeof(double) );

    for( int iBand = 0; iBand < nBands; iBand++ )
    {
        GDALRasterBand * poBand = poSrcDS->GetRasterBand( iBand+1 );

        for( iLine = 0; iLine < nYSize && eErr == CE_None; iLine++ )
        {
            int iValue;

            eErr = poBand->RasterIO( GF_Read, 0, iLine, nXSize, 1, 
                                     padfScanline, nXSize, 1, GDT_Float64,
                                     sizeof(double), 0 );

            if( bASCII )
            {
                for( iValue = 0; iValue < nXSize; iValue++ )
                {
                    char szValue[128];
                    sprintf(szValue,"%.16g\n", padfScanline[iValue] );
                    VSIFWriteL( szValue, 1, strlen(szValue), fp );
                }
            }
            else
            {
                for( iValue = 0; iValue < nXSize; iValue++ )
                    CPL_MSBPTR64( padfScanline + iValue );

                VSIFWriteL( padfScanline, 8, nXSize, fp );
            }
            
            if( eErr == CE_None
                && !pfnProgress( (iLine+1) / (double) nYSize,
                                 NULL, pProgressData ) )
            {
                eErr = CE_Failure;
                CPLError( CE_Failure, CPLE_UserInterrupt,
                          "User terminated CreateCopy()" );
            }
        }
    }

    CPLFree( padfScanline );

/* -------------------------------------------------------------------- */
/*      Write out the dims attribute.                                   */
/* -------------------------------------------------------------------- */
    RWriteInteger( fp, bASCII, 1026 );
    RWriteInteger( fp, bASCII, 1 );  
    
    RWriteString( fp, bASCII, "dim" );

    RWriteInteger( fp, bASCII, 13 );
    RWriteInteger( fp, bASCII, 3 );
    RWriteInteger( fp, bASCII, nXSize );
    RWriteInteger( fp, bASCII, nYSize );
    RWriteInteger( fp, bASCII, nBands );

    RWriteInteger( fp, bASCII, 254 );

/* -------------------------------------------------------------------- */
/*      Terminate overall pairlist.                                     */
/* -------------------------------------------------------------------- */
    RWriteInteger( fp, bASCII, 254 );

/* -------------------------------------------------------------------- */
/*      Cleanup.                                                        */
/* -------------------------------------------------------------------- */
    VSIFCloseL( fp );

    if( eErr != CE_None )
        return NULL;

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

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

    return poDS;
}
Esempio n. 5
0
static GDALDataset *
DTEDCreateCopy( const char * pszFilename, GDALDataset *poSrcDS,
                int bStrict, char ** /* papszOptions */,
                GDALProgressFunc pfnProgress, void *pProgressData)

{
/* -------------------------------------------------------------------- */
/*      Some some rudimentary checks                                    */
/* -------------------------------------------------------------------- */
    const int nBands = poSrcDS->GetRasterCount();
    if (nBands == 0)
    {
        CPLError( CE_Failure, CPLE_NotSupported,
                  "DTED driver does not support source dataset with zero band.\n");
        return nullptr;
    }

    if (nBands != 1)
    {
        CPLError( (bStrict) ? CE_Failure : CE_Warning, CPLE_NotSupported,
                  "DTED driver only uses the first band of the dataset.\n");
        if (bStrict)
            return nullptr;
    }

    if( pfnProgress && !pfnProgress( 0.0, nullptr, pProgressData ) )
        return nullptr;

/* -------------------------------------------------------------------- */
/*      Work out the level.                                             */
/* -------------------------------------------------------------------- */
    int nLevel;

    if( poSrcDS->GetRasterYSize() == 121 )
        nLevel = 0;
    else if( poSrcDS->GetRasterYSize() == 1201 )
        nLevel = 1;
    else if( poSrcDS->GetRasterYSize() == 3601 )
        nLevel = 2;
    else
    {
        CPLError( CE_Warning, CPLE_AppDefined,
               "The source does not appear to be a properly formatted cell." );
        nLevel = 1;
    }

/* -------------------------------------------------------------------- */
/*      Checks the input SRS                                            */
/* -------------------------------------------------------------------- */
    OGRSpatialReference ogrsr_input;
    ogrsr_input.importFromWkt(poSrcDS->GetProjectionRef());
    OGRSpatialReference ogrsr_wgs84;
    ogrsr_wgs84.SetWellKnownGeogCS( "WGS84" );
    if ( ogrsr_input.IsSameGeogCS(&ogrsr_wgs84) == FALSE)
    {
        CPLError( CE_Warning, CPLE_AppDefined,
                  "The source projection coordinate system is %s. Only WGS 84 is supported.\n"
                  "The DTED driver will generate a file as if the source was WGS 84 projection coordinate system.",
                  poSrcDS->GetProjectionRef() );
    }

/* -------------------------------------------------------------------- */
/*      Work out the LL origin.                                         */
/* -------------------------------------------------------------------- */
    double adfGeoTransform[6];

    poSrcDS->GetGeoTransform( adfGeoTransform );

    int nLLOriginLat = (int)
        floor(adfGeoTransform[3]
              + poSrcDS->GetRasterYSize() * adfGeoTransform[5] + 0.5);

    int nLLOriginLong = (int) floor(adfGeoTransform[0] + 0.5);

    if (fabs(nLLOriginLat - (adfGeoTransform[3]
              + (poSrcDS->GetRasterYSize() - 0.5) * adfGeoTransform[5])) > 1e-10 ||
        fabs(nLLOriginLong - (adfGeoTransform[0] + 0.5 * adfGeoTransform[1])) > 1e-10)
    {
        CPLError( CE_Warning, CPLE_AppDefined,
               "The corner coordinates of the source are not properly "
               "aligned on plain latitude/longitude boundaries.");
    }

/* -------------------------------------------------------------------- */
/*     Check horizontal source size.                                    */
/* -------------------------------------------------------------------- */
    int expectedXSize;
    int nReferenceLat = nLLOriginLat < 0 ? - (nLLOriginLat + 1) : nLLOriginLat;
    if( nReferenceLat >= 80 )
        expectedXSize = (poSrcDS->GetRasterYSize() - 1) / 6 + 1;
    else if( nReferenceLat >= 75 )
        expectedXSize = (poSrcDS->GetRasterYSize() - 1) / 4 + 1;
    else if( nReferenceLat >= 70 )
        expectedXSize = (poSrcDS->GetRasterYSize() - 1) / 3 + 1;
    else if( nReferenceLat >= 50 )
        expectedXSize = (poSrcDS->GetRasterYSize() - 1) / 2 + 1;
    else
        expectedXSize = poSrcDS->GetRasterYSize();

    if (poSrcDS->GetRasterXSize() != expectedXSize)
    {
        CPLError( CE_Warning, CPLE_AppDefined,
               "The horizontal source size is not conformant with the one "
               "expected by DTED Level %d at this latitude (%d pixels found instead of %d).", nLevel,
                poSrcDS->GetRasterXSize(), expectedXSize);
    }

/* -------------------------------------------------------------------- */
/*      Create the output dted file.                                    */
/* -------------------------------------------------------------------- */
    const char *pszError
        = DTEDCreate( pszFilename, nLevel, nLLOriginLat, nLLOriginLong );

    if( pszError != nullptr )
    {
        CPLError( CE_Failure, CPLE_AppDefined,
                  "%s", pszError );
        return nullptr;
    }

/* -------------------------------------------------------------------- */
/*      Open the DTED file so we can output the data to it.             */
/* -------------------------------------------------------------------- */
    DTEDInfo *psDTED
        = DTEDOpen( pszFilename, "rb+", FALSE );
    if( psDTED == nullptr )
        return nullptr;

/* -------------------------------------------------------------------- */
/*      Read all the data in a single buffer.                           */
/* -------------------------------------------------------------------- */
    GDALRasterBand *poSrcBand = poSrcDS->GetRasterBand( 1 );
    GInt16 *panData = (GInt16 *)
        VSI_MALLOC_VERBOSE(sizeof(GInt16) * psDTED->nXSize * psDTED->nYSize);
    if (panData == nullptr)
    {
        DTEDClose(psDTED);
        return nullptr;
    }

    for( int iY = 0; iY < psDTED->nYSize; iY++ )
    {
        if( poSrcBand->RasterIO( GF_Read, 0, iY, psDTED->nXSize, 1,
                            (void *) (panData + iY * psDTED->nXSize), psDTED->nXSize, 1,
                            GDT_Int16, 0, 0, nullptr ) != CE_None )
        {
            DTEDClose( psDTED );
            CPLFree( panData );
            return nullptr;
        }

        if( pfnProgress && !pfnProgress(0.5 * (iY+1) / (double) psDTED->nYSize, nullptr, pProgressData ) )
        {
            CPLError( CE_Failure, CPLE_UserInterrupt,
                        "User terminated CreateCopy()" );
            DTEDClose( psDTED );
            CPLFree( panData );
            return nullptr;
        }
    }

    int bSrcBandHasNoData;
    double srcBandNoData = poSrcBand->GetNoDataValue(&bSrcBandHasNoData);

/* -------------------------------------------------------------------- */
/*      Write all the profiles.                                         */
/* -------------------------------------------------------------------- */
    GInt16      anProfData[3601];
    int         dfNodataCount=0;
    GByte       iPartialCell;

    for( int iProfile = 0; iProfile < psDTED->nXSize; iProfile++ )
    {
        for( int iY = 0; iY < psDTED->nYSize; iY++ )
        {
            anProfData[iY] = panData[iProfile + iY * psDTED->nXSize];
            if ( bSrcBandHasNoData && anProfData[iY] == srcBandNoData)
            {
                anProfData[iY] = DTED_NODATA_VALUE;
                dfNodataCount++;
            }
            else if ( anProfData[iY] == DTED_NODATA_VALUE )
                dfNodataCount++;
        }
        DTEDWriteProfile( psDTED, iProfile, anProfData );

        if( pfnProgress
            && !pfnProgress( 0.5 + 0.5 * (iProfile+1) / (double) psDTED->nXSize,
                             nullptr, pProgressData ) )
        {
            CPLError( CE_Failure, CPLE_UserInterrupt,
                      "User terminated CreateCopy()" );
            DTEDClose( psDTED );
            CPLFree( panData );
            return nullptr;
        }
    }
    CPLFree( panData );

/* -------------------------------------------------------------------- */
/* Partial cell indicator: 0 for complete coverage; 1-99 for incomplete */
/* -------------------------------------------------------------------- */
    char szPartialCell[3];

    if ( dfNodataCount == 0 )
        iPartialCell = 0;
    else
    {
      iPartialCell = (GByte)int(floor(100.0 -
           (dfNodataCount*100.0/(psDTED->nXSize * psDTED->nYSize))));
        if (iPartialCell < 1)
           iPartialCell=1;
    }

    CPLsnprintf( szPartialCell, sizeof(szPartialCell), "%02d",iPartialCell);
    DTEDSetMetadata(psDTED, DTEDMD_PARTIALCELL_DSI, szPartialCell);

/* -------------------------------------------------------------------- */
/*      Try to copy any matching available metadata.                    */
/* -------------------------------------------------------------------- */
    if( poSrcDS->GetMetadataItem( "DTED_VerticalAccuracy_UHL" ) != nullptr )
        DTEDSetMetadata( psDTED, DTEDMD_VERTACCURACY_UHL,
                     poSrcDS->GetMetadataItem( "DTED_VerticalAccuracy_UHL" ) );

    if( poSrcDS->GetMetadataItem( "DTED_VerticalAccuracy_ACC" ) != nullptr )
        DTEDSetMetadata( psDTED, DTEDMD_VERTACCURACY_ACC,
                    poSrcDS->GetMetadataItem( "DTED_VerticalAccuracy_ACC" ) );

    if( poSrcDS->GetMetadataItem( "DTED_SecurityCode_UHL" ) != nullptr )
        DTEDSetMetadata( psDTED, DTEDMD_SECURITYCODE_UHL,
                    poSrcDS->GetMetadataItem( "DTED_SecurityCode_UHL" ) );

    if( poSrcDS->GetMetadataItem( "DTED_SecurityCode_DSI" ) != nullptr )
        DTEDSetMetadata( psDTED, DTEDMD_SECURITYCODE_DSI,
                    poSrcDS->GetMetadataItem( "DTED_SecurityCode_DSI" ) );

    if( poSrcDS->GetMetadataItem( "DTED_UniqueRef_UHL" ) != nullptr )
        DTEDSetMetadata( psDTED, DTEDMD_UNIQUEREF_UHL,
                         poSrcDS->GetMetadataItem( "DTED_UniqueRef_UHL" ) );

    if( poSrcDS->GetMetadataItem( "DTED_UniqueRef_DSI" ) != nullptr )
        DTEDSetMetadata( psDTED, DTEDMD_UNIQUEREF_DSI,
                         poSrcDS->GetMetadataItem( "DTED_UniqueRef_DSI" ) );

    if( poSrcDS->GetMetadataItem( "DTED_DataEdition" ) != nullptr )
        DTEDSetMetadata( psDTED, DTEDMD_DATA_EDITION,
                         poSrcDS->GetMetadataItem( "DTED_DataEdition" ) );

    if( poSrcDS->GetMetadataItem( "DTED_MatchMergeVersion" ) != nullptr )
        DTEDSetMetadata( psDTED, DTEDMD_MATCHMERGE_VERSION,
                     poSrcDS->GetMetadataItem( "DTED_MatchMergeVersion" ) );

    if( poSrcDS->GetMetadataItem( "DTED_MaintenanceDate" ) != nullptr )
        DTEDSetMetadata( psDTED, DTEDMD_MAINT_DATE,
                         poSrcDS->GetMetadataItem( "DTED_MaintenanceDate" ) );

    if( poSrcDS->GetMetadataItem( "DTED_MatchMergeDate" ) != nullptr )
        DTEDSetMetadata( psDTED, DTEDMD_MATCHMERGE_DATE,
                         poSrcDS->GetMetadataItem( "DTED_MatchMergeDate" ) );

    if( poSrcDS->GetMetadataItem( "DTED_MaintenanceDescription" ) != nullptr )
        DTEDSetMetadata( psDTED, DTEDMD_MAINT_DESCRIPTION,
                 poSrcDS->GetMetadataItem( "DTED_MaintenanceDescription" ) );

    if( poSrcDS->GetMetadataItem( "DTED_Producer" ) != nullptr )
        DTEDSetMetadata( psDTED, DTEDMD_PRODUCER,
                         poSrcDS->GetMetadataItem( "DTED_Producer" ) );

    if( poSrcDS->GetMetadataItem( "DTED_VerticalDatum" ) != nullptr )
        DTEDSetMetadata( psDTED, DTEDMD_VERTDATUM,
                         poSrcDS->GetMetadataItem( "DTED_VerticalDatum" ) );

    if( poSrcDS->GetMetadataItem( "DTED_HorizontalDatum" ) != nullptr )
        DTEDSetMetadata( psDTED, DTEDMD_HORIZDATUM,
                         poSrcDS->GetMetadataItem( "DTED_HorizontalDatum" ) );

    if( poSrcDS->GetMetadataItem( "DTED_DigitizingSystem" ) != nullptr )
        DTEDSetMetadata( psDTED, DTEDMD_DIGITIZING_SYS,
                         poSrcDS->GetMetadataItem( "DTED_DigitizingSystem" ) );

    if( poSrcDS->GetMetadataItem( "DTED_CompilationDate" ) != nullptr )
        DTEDSetMetadata( psDTED, DTEDMD_COMPILATION_DATE,
                         poSrcDS->GetMetadataItem( "DTED_CompilationDate" ) );

    if( poSrcDS->GetMetadataItem( "DTED_HorizontalAccuracy" ) != nullptr )
        DTEDSetMetadata( psDTED, DTEDMD_HORIZACCURACY,
                     poSrcDS->GetMetadataItem( "DTED_HorizontalAccuracy" ) );

    if( poSrcDS->GetMetadataItem( "DTED_RelHorizontalAccuracy" ) != nullptr )
        DTEDSetMetadata( psDTED, DTEDMD_REL_HORIZACCURACY,
                   poSrcDS->GetMetadataItem( "DTED_RelHorizontalAccuracy" ) );

    if( poSrcDS->GetMetadataItem( "DTED_RelVerticalAccuracy" ) != nullptr )
        DTEDSetMetadata( psDTED, DTEDMD_REL_VERTACCURACY,
                     poSrcDS->GetMetadataItem( "DTED_RelVerticalAccuracy" ) );

/* -------------------------------------------------------------------- */
/*      Try to open the resulting DTED file.                            */
/* -------------------------------------------------------------------- */
    DTEDClose( psDTED );

/* -------------------------------------------------------------------- */
/*      Reopen and copy missing information into a PAM file.            */
/* -------------------------------------------------------------------- */
    GDALPamDataset *poDS = (GDALPamDataset *)
        GDALOpen( pszFilename, GA_ReadOnly );

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

    return poDS;
}
Esempio n. 6
0
/*!
  \warning   The source raster must have only 1 band. Currently, the values in
             the source raster must be stored in one of the supported cell
             representations (CR_UINT1, CR_INT4, CR_REAL4, CR_REAL8).

  The meta data item PCRASTER_VALUESCALE will be checked to see what value
  scale to use. Otherwise a value scale is determined using
  GDALType2ValueScale(GDALDataType).

  This function always writes rasters using CR_UINT1, CR_INT4 or CR_REAL4
  cell representations.
*/
GDALDataset* PCRasterDataset::createCopy(
    char const* filename,
    GDALDataset* source,
    CPL_UNUSED int strict,
    CPL_UNUSED char** options,
    GDALProgressFunc progress,
    void* progressData)
{
  // Checks.
  const int nrBands = source->GetRasterCount();
  if(nrBands != 1) {
    CPLError(CE_Failure, CPLE_NotSupported,
         "PCRaster driver: Too many bands ('%d'): must be 1 band", nrBands);
    return NULL;
  }

  GDALRasterBand* raster = source->GetRasterBand(1);

  // Create PCRaster raster. Determine properties of raster to create.

  // The in-file type of the cells.
  CSF_CR fileCellRepresentation = GDALType2CellRepresentation(
         raster->GetRasterDataType(), false);

  if(fileCellRepresentation == CR_UNDEFINED) {
    CPLError(CE_Failure, CPLE_NotSupported,
         "PCRaster driver: Cannot determine a valid cell representation");
    return NULL;
  }

  // The value scale of the values.
  CSF_VS valueScale = VS_UNDEFINED;
  std::string osString;
  if(source->GetMetadataItem("PCRASTER_VALUESCALE")) {
    osString = source->GetMetadataItem("PCRASTER_VALUESCALE");
  }

  valueScale = !osString.empty()
         ? string2ValueScale(osString)
         : GDALType2ValueScale(raster->GetRasterDataType());

  if(valueScale == VS_UNDEFINED) {
    CPLError(CE_Failure, CPLE_NotSupported,
         "PCRaster driver: Cannot determine a valid value scale");
    return NULL;
  }

  CSF_PT const projection = PT_YDECT2B;
  const REAL8 angle = 0.0;
  REAL8 west = 0.0;
  REAL8 north = 0.0;
  REAL8 cellSize = 1.0;

  double transform[6];
  if(source->GetGeoTransform(transform) == CE_None) {
    if(transform[2] == 0.0 && transform[4] == 0.0) {
      west = static_cast<REAL8>(transform[0]);
      north = static_cast<REAL8>(transform[3]);
      cellSize = static_cast<REAL8>(transform[1]);
    }
  }

  // The in-memory type of the cells.
  CSF_CR appCellRepresentation = CR_UNDEFINED;
  appCellRepresentation = GDALType2CellRepresentation(
         raster->GetRasterDataType(), true);

  if(appCellRepresentation == CR_UNDEFINED) {
    CPLError(CE_Failure, CPLE_NotSupported,
         "PCRaster driver: Cannot determine a valid cell representation");
    return NULL;
  }

  // Check whether value scale fits the cell representation. Adjust when
  // needed.
  valueScale = fitValueScale(valueScale, appCellRepresentation);

  // Create a raster with the in file cell representation.
  const size_t nrRows = raster->GetYSize();
  const size_t nrCols = raster->GetXSize();
  MAP* map = Rcreate(filename, nrRows, nrCols, fileCellRepresentation,
         valueScale, projection, west, north, angle, cellSize);

  if(!map) {
    CPLError(CE_Failure, CPLE_OpenFailed,
         "PCRaster driver: Unable to create raster %s", filename);
    return NULL;
  }

  // Try to convert in app cell representation to the cell representation
  // of the file.
  if(RuseAs(map, appCellRepresentation)) {
    CPLError(CE_Failure, CPLE_NotSupported,
         "PCRaster driver: Cannot convert cells: %s", MstrError());
    Mclose(map);
    return NULL;
  }

  int hasMissingValue;
  double missingValue = raster->GetNoDataValue(&hasMissingValue);

  // This is needed to get my (KDJ) unit tests running.
  // I am still uncertain why this is needed. If the input raster has float32
  // values and the output int32, than the missing value in the dataset object
  // is not updated like the values are.
  if(missingValue == ::missingValue(CR_REAL4) &&
         fileCellRepresentation == CR_INT4) {
    missingValue = ::missingValue(fileCellRepresentation);
  }

  // TODO: Proper translation of TODO.
  // TODO: Support conversion to INT2 (?) INT4. ruseas.c see line 503.
  // Conversion r 159.

  // Create buffer for one row of values.
  void* buffer = Rmalloc(map, nrCols);

  // Copy values from source to target.
  CPLErr errorCode = CE_None;
  for(size_t row = 0; errorCode == CE_None && row < nrRows; ++row) {

    // Get row from source.
    if(raster->RasterIO(GF_Read, 0, static_cast<int>(row),
        static_cast<int>(nrCols), 1, buffer,
        static_cast<int>(nrCols), 1,
         raster->GetRasterDataType(), 0, 0, NULL) != CE_None) {
      CPLError(CE_Failure, CPLE_FileIO,
         "PCRaster driver: Error reading from source raster");
      errorCode = CE_Failure;
      break;
    }

    // Upon reading values are converted to the
    // right data type. This includes the missing value. If the source
    // value cannot be represented in the target data type it is set to a
    // missing value.

    if(hasMissingValue) {
      alterToStdMV(buffer, nrCols, appCellRepresentation, missingValue);
    }

    if(valueScale == VS_BOOLEAN) {
      castValuesToBooleanRange(buffer, nrCols, appCellRepresentation);
    }

    // Write row in target.
    RputRow(map, row, buffer);

    if(!progress((row + 1) / (static_cast<double>(nrRows)), NULL, progressData)) {
      CPLError(CE_Failure, CPLE_UserInterrupt,
         "PCRaster driver: User terminated CreateCopy()");
      errorCode = CE_Failure;
      break;
    }
  }

  Mclose(map);
  map = NULL;

  free(buffer);
  buffer = NULL;

  if( errorCode != CE_None )
      return NULL;

/* -------------------------------------------------------------------- */
/*      Re-open dataset, and copy any auxiliary pam information.        */
/* -------------------------------------------------------------------- */
  GDALPamDataset *poDS = reinterpret_cast<GDALPamDataset *>(
      GDALOpen( filename, GA_Update ) );

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

  return poDS;
}