# Simple C Example: gdalinfo.c

    /******************************************************************************
     * $Id: gdalinfo.c 25582 2013-01-29 21:13:43Z rouault $
     *
     * Project:  GDAL Utilities
     * Purpose:  Commandline application to list info about a file.
     * Author:   Frank Warmerdam, warmerdam@pobox.com
     *
     * ****************************************************************************
     * Copyright (c) 1998, Frank Warmerdam
     *
     * Permission is hereby granted, free of charge, to any person obtaining a
     * copy of this software and associated documentation files (the "Software"),
     * to deal in the Software without restriction, including without limitation
     * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     * and/or sell copies of the Software, and to permit persons to whom the
     * Software is furnished to do so, subject to the following conditions:
     *
     * The above copyright notice and this permission notice shall be included
     * in all copies or substantial portions of the Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     * DEALINGS IN THE SOFTWARE.
     ****************************************************************************/

    #include "gdal.h"
    #include "gdal_alg.h"
    #include "ogr_srs_api.h"
    #include "cpl_string.h"
    #include "cpl_conv.h"
    #include "cpl_multiproc.h"
    #include "commonutils.h"

    CPL_CVSID("$Id: gdalinfo.c 25582 2013-01-29 21:13:43Z rouault $");

    static int
    GDALInfoReportCorner( GDALDatasetH hDataset,
                          OGRCoordinateTransformationH hTransform,
                          const char * corner_name,
                          double x, double y );

    /************************************************************************/
    /*                               Usage()                                */
    /************************************************************************/

    void Usage(const char* pszErrorMsg)

    {
        printf( "Usage: gdalinfo [--help-general] [-mm] [-stats] [-hist] [-nogcp] [-nomd]\n"
                "                [-norat] [-noct] [-nofl] [-checksum] [-proj4] [-mdd domain]*\n"
                "                [-sd subdataset] datasetname\n" );

        if( pszErrorMsg != NULL )
            fprintf(stderr, "\nFAILURE: %s\n", pszErrorMsg);

        exit( 1 );
    }

    /************************************************************************/
    /*                                main()                                */
    /************************************************************************/

    #define CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(nExtraArg) \
        do { if (i + nExtraArg >= argc) \
            Usage(CPLSPrintf("%s option requires %d argument(s)", argv[i], nExtraArg)); } while(0)

    int main( int argc, char ** argv )

    {
        GDALDatasetH        hDataset = NULL;
        GDALRasterBandH     hBand = NULL;
        int                 i, iBand;
        double              adfGeoTransform[6];
        GDALDriverH         hDriver;
        char                **papszMetadata;
        int                 bComputeMinMax = FALSE, bSample = FALSE;
        int                 bShowGCPs = TRUE, bShowMetadata = TRUE, bShowRAT=TRUE;
        int                 bStats = FALSE, bApproxStats = TRUE, iMDD;
        int                 bShowColorTable = TRUE, bComputeChecksum = FALSE;
        int                 bReportHistograms = FALSE;
        int                 bReportProj4 = FALSE;
        int                 nSubdataset = -1;
        const char          *pszFilename = NULL;
        char              **papszExtraMDDomains = NULL, **papszFileList;
        const char  *pszProjection = NULL;
        OGRCoordinateTransformationH hTransform = NULL;
        int             bShowFileList = TRUE;

        /* Check that we are running against at least GDAL 1.5 */
        /* Note to developers : if we use newer API, please change the requirement */
        if (atoi(GDALVersionInfo("VERSION_NUM")) < 1500)
        {
            fprintf(stderr, "At least, GDAL >= 1.5.0 is required for this version of %s, "
                    "which was compiled against GDAL %s\n", argv[0], GDAL_RELEASE_NAME);
            exit(1);
        }

        EarlySetConfigOptions(argc, argv);

        GDALAllRegister();

        argc = GDALGeneralCmdLineProcessor( argc, &argv, 0 );
        if( argc < 1 )
            exit( -argc );

    /* -------------------------------------------------------------------- */
    /*      Parse arguments.                                                */
    /* -------------------------------------------------------------------- */
        for( i = 1; i < argc; i++ )
        {
            if( EQUAL(argv[i], "--utility_version") )
            {
                printf("%s was compiled against GDAL %s and is running against GDAL %s\n",
                       argv[0], GDAL_RELEASE_NAME, GDALVersionInfo("RELEASE_NAME"));
                return 0;
            }
            else if( EQUAL(argv[i],"--help") )
                Usage(NULL);
            else if( EQUAL(argv[i], "-mm") )
                bComputeMinMax = TRUE;
            else if( EQUAL(argv[i], "-hist") )
                bReportHistograms = TRUE;
            else if( EQUAL(argv[i], "-proj4") )
                bReportProj4 = TRUE;
            else if( EQUAL(argv[i], "-stats") )
            {
                bStats = TRUE;
                bApproxStats = FALSE;
            }
            else if( EQUAL(argv[i], "-approx_stats") )
            {
                bStats = TRUE;
                bApproxStats = TRUE;
            }
            else if( EQUAL(argv[i], "-sample") )
                bSample = TRUE;
            else if( EQUAL(argv[i], "-checksum") )
                bComputeChecksum = TRUE;
            else if( EQUAL(argv[i], "-nogcp") )
                bShowGCPs = FALSE;
            else if( EQUAL(argv[i], "-nomd") )
                bShowMetadata = FALSE;
            else if( EQUAL(argv[i], "-norat") )
                bShowRAT = FALSE;
            else if( EQUAL(argv[i], "-noct") )
                bShowColorTable = FALSE;
            else if( EQUAL(argv[i], "-mdd") )
            {
                CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
                papszExtraMDDomains = CSLAddString( papszExtraMDDomains,
                                                    argv[++i] );
            }
            else if( EQUAL(argv[i], "-nofl") )
                bShowFileList = FALSE;
            else if( EQUAL(argv[i], "-sd") )
            {
                CHECK_HAS_ENOUGH_ADDITIONAL_ARGS(1);
                nSubdataset = atoi(argv[++i]);
            }
            else if( argv[i][0] == '-' )
                Usage(CPLSPrintf("Unkown option name '%s'", argv[i]));
            else if( pszFilename == NULL )
                pszFilename = argv[i];
            else
                Usage("Too many command options.");
        }

        if( pszFilename == NULL )
            Usage("No datasource specified.");

    /* -------------------------------------------------------------------- */
    /*      Open dataset.                                                   */
    /* -------------------------------------------------------------------- */
        hDataset = GDALOpen( pszFilename, GA_ReadOnly );

        if( hDataset == NULL )
        {
            fprintf( stderr,
                     "gdalinfo failed - unable to open '%s'.\n",
                     pszFilename );

    /* -------------------------------------------------------------------- */
    /*      If argument is a VSIFILE, then print its contents               */
    /* -------------------------------------------------------------------- */
            if ( strncmp( pszFilename, "/vsizip/", 8 ) == 0 ||
                 strncmp( pszFilename, "/vsitar/", 8 ) == 0 )
            {
                papszFileList = VSIReadDirRecursive( pszFilename );
                if ( papszFileList )
                {
                    int nCount = CSLCount( papszFileList );
                    fprintf( stdout,
                             "Unable to open source `%s' directly.\n"
                             "The archive contains %d files:\n",
                             pszFilename, nCount );
                    for ( i = 0; i < nCount; i++ )
                    {
                        fprintf( stdout, "       %s/%s\n", pszFilename, papszFileList[i] );
                    }
                    CSLDestroy( papszFileList );
                    papszFileList = NULL;
                }
            }

            CSLDestroy( argv );
            CSLDestroy( papszExtraMDDomains );

            GDALDumpOpenDatasets( stderr );

            GDALDestroyDriverManager();

            CPLDumpSharedList( NULL );

            exit( 1 );
        }

    /* -------------------------------------------------------------------- */
    /*      Read specified subdataset if requested.                         */
    /* -------------------------------------------------------------------- */
        if ( nSubdataset > 0 )
        {
            char **papszSubdatasets = GDALGetMetadata( hDataset, "SUBDATASETS" );
            int nSubdatasets = CSLCount( papszSubdatasets );

            if ( nSubdatasets > 0 && nSubdataset <= nSubdatasets )
            {
                char szKeyName[1024];
                char *pszSubdatasetName;

                snprintf( szKeyName, sizeof(szKeyName),
                          "SUBDATASET_%d_NAME", nSubdataset );
                szKeyName[sizeof(szKeyName) - 1] = '\0';
                pszSubdatasetName =
                    CPLStrdup( CSLFetchNameValue( papszSubdatasets, szKeyName ) );
                GDALClose( hDataset );
                hDataset = GDALOpen( pszSubdatasetName, GA_ReadOnly );
                CPLFree( pszSubdatasetName );
            }
            else
            {
                fprintf( stderr,
                         "gdalinfo warning: subdataset %d of %d requested. "
                         "Reading the main dataset.\n",
                         nSubdataset, nSubdatasets );

            }
        }

    /* -------------------------------------------------------------------- */
    /*      Report general info.                                            */
    /* -------------------------------------------------------------------- */
        hDriver = GDALGetDatasetDriver( hDataset );
        printf( "Driver: %s/%s\n",
                GDALGetDriverShortName( hDriver ),
                GDALGetDriverLongName( hDriver ) );

        papszFileList = GDALGetFileList( hDataset );
        if( CSLCount(papszFileList) == 0 )
        {
            printf( "Files: none associated\n" );
        }
        else
        {
            printf( "Files: %s\n", papszFileList[0] );
            if( bShowFileList )
            {
                for( i = 1; papszFileList[i] != NULL; i++ )
                    printf( "       %s\n", papszFileList[i] );
            }
        }
        CSLDestroy( papszFileList );

        printf( "Size is %d, %d\n",
                GDALGetRasterXSize( hDataset ),
                GDALGetRasterYSize( hDataset ) );

    /* -------------------------------------------------------------------- */
    /*      Report projection.                                              */
    /* -------------------------------------------------------------------- */
        if( GDALGetProjectionRef( hDataset ) != NULL )
        {
            OGRSpatialReferenceH  hSRS;
            char                  *pszProjection;

            pszProjection = (char *) GDALGetProjectionRef( hDataset );

            hSRS = OSRNewSpatialReference(NULL);
            if( OSRImportFromWkt( hSRS, &pszProjection ) == CE_None )
            {
                char        *pszPrettyWkt = NULL;

                OSRExportToPrettyWkt( hSRS, &pszPrettyWkt, FALSE );
                printf( "Coordinate System is:\n%s\n", pszPrettyWkt );
                CPLFree( pszPrettyWkt );
            }
            else
                printf( "Coordinate System is `%s'\n",
                        GDALGetProjectionRef( hDataset ) );

            if ( bReportProj4 )
            {
                char *pszProj4 = NULL;
                OSRExportToProj4( hSRS, &pszProj4 );
                printf("PROJ.4 string is:\n\'%s\'\n",pszProj4);
                CPLFree( pszProj4 );
            }

            OSRDestroySpatialReference( hSRS );
        }

    /* -------------------------------------------------------------------- */
    /*      Report Geotransform.                                            */
    /* -------------------------------------------------------------------- */
        if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None )
        {
            if( adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0 )
            {
                printf( "Origin = (%.15f,%.15f)\n",
                        adfGeoTransform[0], adfGeoTransform[3] );

                printf( "Pixel Size = (%.15f,%.15f)\n",
                        adfGeoTransform[1], adfGeoTransform[5] );
            }
            else
                printf( "GeoTransform =\n"
                        "  %.16g, %.16g, %.16g\n"
                        "  %.16g, %.16g, %.16g\n",
                        adfGeoTransform[0],
                        adfGeoTransform[1],
                        adfGeoTransform[2],
                        adfGeoTransform[3],
                        adfGeoTransform[4],
                        adfGeoTransform[5] );
        }

    /* -------------------------------------------------------------------- */
    /*      Report GCPs.                                                    */
    /* -------------------------------------------------------------------- */
        if( bShowGCPs && GDALGetGCPCount( hDataset ) > 0 )
        {
            if (GDALGetGCPProjection(hDataset) != NULL)
            {
                OGRSpatialReferenceH  hSRS;
                char                      *pszProjection;

                pszProjection = (char *) GDALGetGCPProjection( hDataset );

                hSRS = OSRNewSpatialReference(NULL);
                if( OSRImportFromWkt( hSRS, &pszProjection ) == CE_None )
                {
                    char    *pszPrettyWkt = NULL;

                    OSRExportToPrettyWkt( hSRS, &pszPrettyWkt, FALSE );
                    printf( "GCP Projection = \n%s\n", pszPrettyWkt );
                    CPLFree( pszPrettyWkt );
                }
                else
                    printf( "GCP Projection = %s\n",
                            GDALGetGCPProjection( hDataset ) );

                OSRDestroySpatialReference( hSRS );
            }

            for( i = 0; i < GDALGetGCPCount(hDataset); i++ )
            {
                const GDAL_GCP      *psGCP;

                psGCP = GDALGetGCPs( hDataset ) + i;

                printf( "GCP[%3d]: Id=%s, Info=%s\n"
                        "          (%.15g,%.15g) -> (%.15g,%.15g,%.15g)\n",
                        i, psGCP->pszId, psGCP->pszInfo,
                        psGCP->dfGCPPixel, psGCP->dfGCPLine,
                        psGCP->dfGCPX, psGCP->dfGCPY, psGCP->dfGCPZ );
            }
        }

    /* -------------------------------------------------------------------- */
    /*      Report metadata.                                                */
    /* -------------------------------------------------------------------- */
        papszMetadata = (bShowMetadata) ? GDALGetMetadata( hDataset, NULL ) : NULL;
        if( bShowMetadata && CSLCount(papszMetadata) > 0 )
        {
            printf( "Metadata:\n" );
            for( i = 0; papszMetadata[i] != NULL; i++ )
            {
                printf( "  %s\n", papszMetadata[i] );
            }
        }

        for( iMDD = 0; bShowMetadata && iMDD < CSLCount(papszExtraMDDomains); iMDD++ )
        {
            papszMetadata = GDALGetMetadata( hDataset, papszExtraMDDomains[iMDD] );
            if( CSLCount(papszMetadata) > 0 )
            {
                printf( "Metadata (%s):\n", papszExtraMDDomains[iMDD]);
                for( i = 0; papszMetadata[i] != NULL; i++ )
                {
                    if (EQUALN(papszExtraMDDomains[iMDD], "xml:", 4))
                        printf( "%s\n", papszMetadata[i] );
                    else
                        printf( "  %s\n", papszMetadata[i] );
                }
            }
        }

    /* -------------------------------------------------------------------- */
    /*      Report "IMAGE_STRUCTURE" metadata.                              */
    /* -------------------------------------------------------------------- */
        papszMetadata = (bShowMetadata) ? GDALGetMetadata( hDataset, "IMAGE_STRUCTURE" ) : NULL;
        if( bShowMetadata && CSLCount(papszMetadata) > 0 )
        {
            printf( "Image Structure Metadata:\n" );
            for( i = 0; papszMetadata[i] != NULL; i++ )
            {
                printf( "  %s\n", papszMetadata[i] );
            }
        }

    /* -------------------------------------------------------------------- */
    /*      Report subdatasets.                                             */
    /* -------------------------------------------------------------------- */
        papszMetadata = GDALGetMetadata( hDataset, "SUBDATASETS" );
        if( CSLCount(papszMetadata) > 0 )
        {
            printf( "Subdatasets:\n" );
            for( i = 0; papszMetadata[i] != NULL; i++ )
            {
                printf( "  %s\n", papszMetadata[i] );
            }
        }

    /* -------------------------------------------------------------------- */
    /*      Report geolocation.                                             */
    /* -------------------------------------------------------------------- */
        papszMetadata = (bShowMetadata) ? GDALGetMetadata( hDataset, "GEOLOCATION" ) : NULL;
        if( bShowMetadata && CSLCount(papszMetadata) > 0 )
        {
            printf( "Geolocation:\n" );
            for( i = 0; papszMetadata[i] != NULL; i++ )
            {
                printf( "  %s\n", papszMetadata[i] );
            }
        }

    /* -------------------------------------------------------------------- */
    /*      Report RPCs                                                     */
    /* -------------------------------------------------------------------- */
        papszMetadata = (bShowMetadata) ? GDALGetMetadata( hDataset, "RPC" ) : NULL;
        if( bShowMetadata && CSLCount(papszMetadata) > 0 )
        {
            printf( "RPC Metadata:\n" );
            for( i = 0; papszMetadata[i] != NULL; i++ )
            {
                printf( "  %s\n", papszMetadata[i] );
            }
        }

    /* -------------------------------------------------------------------- */
    /*      Setup projected to lat/long transform if appropriate.           */
    /* -------------------------------------------------------------------- */
        if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None )
            pszProjection = GDALGetProjectionRef(hDataset);

        if( pszProjection != NULL && strlen(pszProjection) > 0 )
        {
            OGRSpatialReferenceH hProj, hLatLong = NULL;

            hProj = OSRNewSpatialReference( pszProjection );
            if( hProj != NULL )
                hLatLong = OSRCloneGeogCS( hProj );

            if( hLatLong != NULL )
            {
                CPLPushErrorHandler( CPLQuietErrorHandler );
                hTransform = OCTNewCoordinateTransformation( hProj, hLatLong );
                CPLPopErrorHandler();

                OSRDestroySpatialReference( hLatLong );
            }

            if( hProj != NULL )
                OSRDestroySpatialReference( hProj );
        }

    /* -------------------------------------------------------------------- */
    /*      Report corners.                                                 */
    /* -------------------------------------------------------------------- */
        printf( "Corner Coordinates:\n" );
        GDALInfoReportCorner( hDataset, hTransform, "Upper Left",
                              0.0, 0.0 );
        GDALInfoReportCorner( hDataset, hTransform, "Lower Left",
                              0.0, GDALGetRasterYSize(hDataset));
        GDALInfoReportCorner( hDataset, hTransform, "Upper Right",
                              GDALGetRasterXSize(hDataset), 0.0 );
        GDALInfoReportCorner( hDataset, hTransform, "Lower Right",
                              GDALGetRasterXSize(hDataset),
                              GDALGetRasterYSize(hDataset) );
        GDALInfoReportCorner( hDataset, hTransform, "Center",
                              GDALGetRasterXSize(hDataset)/2.0,
                              GDALGetRasterYSize(hDataset)/2.0 );

        if( hTransform != NULL )
        {
            OCTDestroyCoordinateTransformation( hTransform );
            hTransform = NULL;
        }

    /* ==================================================================== */
    /*      Loop over bands.                                                */
    /* ==================================================================== */
        for( iBand = 0; iBand < GDALGetRasterCount( hDataset ); iBand++ )
        {
            double      dfMin, dfMax, adfCMinMax[2], dfNoData;
            int         bGotMin, bGotMax, bGotNodata, bSuccess;
            int         nBlockXSize, nBlockYSize, nMaskFlags;
            double      dfMean, dfStdDev;
            GDALColorTableH hTable;
            CPLErr      eErr;

            hBand = GDALGetRasterBand( hDataset, iBand+1 );

            if( bSample )
            {
                float afSample[10000];
                int   nCount;

                nCount = GDALGetRandomRasterSample( hBand, 10000, afSample );
                printf( "Got %d samples.\n", nCount );
            }

            GDALGetBlockSize( hBand, &nBlockXSize, &nBlockYSize );
            printf( "Band %d Block=%dx%d Type=%s, ColorInterp=%s\n", iBand+1,
                    nBlockXSize, nBlockYSize,
                    GDALGetDataTypeName(
                        GDALGetRasterDataType(hBand)),
                    GDALGetColorInterpretationName(
                        GDALGetRasterColorInterpretation(hBand)) );

            if( GDALGetDescription( hBand ) != NULL
                && strlen(GDALGetDescription( hBand )) > 0 )
                printf( "  Description = %s\n", GDALGetDescription(hBand) );

            dfMin = GDALGetRasterMinimum( hBand, &bGotMin );
            dfMax = GDALGetRasterMaximum( hBand, &bGotMax );
            if( bGotMin || bGotMax || bComputeMinMax )
            {
                printf( "  " );
                if( bGotMin )
                    printf( "Min=%.3f ", dfMin );
                if( bGotMax )
                    printf( "Max=%.3f ", dfMax );

                if( bComputeMinMax )
                {
                    CPLErrorReset();
                    GDALComputeRasterMinMax( hBand, FALSE, adfCMinMax );
                    if (CPLGetLastErrorType() == CE_None)
                    {
                      printf( "  Computed Min/Max=%.3f,%.3f",
                              adfCMinMax[0], adfCMinMax[1] );
                    }
                }

                printf( "\n" );
            }

            eErr = GDALGetRasterStatistics( hBand, bApproxStats, bStats,
                                            &dfMin, &dfMax, &dfMean, &dfStdDev );
            if( eErr == CE_None )
            {
                printf( "  Minimum=%.3f, Maximum=%.3f, Mean=%.3f, StdDev=%.3f\n",
                        dfMin, dfMax, dfMean, dfStdDev );
            }

            if( bReportHistograms )
            {
                int nBucketCount, *panHistogram = NULL;

                eErr = GDALGetDefaultHistogram( hBand, &dfMin, &dfMax,
                                                &nBucketCount, &panHistogram,
                                                TRUE, GDALTermProgress, NULL );
                if( eErr == CE_None )
                {
                    int iBucket;

                    printf( "  %d buckets from %g to %g:\n  ",
                            nBucketCount, dfMin, dfMax );
                    for( iBucket = 0; iBucket < nBucketCount; iBucket++ )
                        printf( "%d ", panHistogram[iBucket] );
                    printf( "\n" );
                    CPLFree( panHistogram );
                }
            }

            if ( bComputeChecksum)
            {
                printf( "  Checksum=%d\n",
                        GDALChecksumImage(hBand, 0, 0,
                                          GDALGetRasterXSize(hDataset),
                                          GDALGetRasterYSize(hDataset)));
            }

            dfNoData = GDALGetRasterNoDataValue( hBand, &bGotNodata );
            if( bGotNodata )
            {
                if (CPLIsNan(dfNoData))
                    printf( "  NoData Value=nan\n" );
                else
                    printf( "  NoData Value=%.18g\n", dfNoData );
            }

            if( GDALGetOverviewCount(hBand) > 0 )
            {
                int         iOverview;

                printf( "  Overviews: " );
                for( iOverview = 0;
                     iOverview < GDALGetOverviewCount(hBand);
                     iOverview++ )
                {
                    GDALRasterBandH hOverview;
                    const char *pszResampling = NULL;

                    if( iOverview != 0 )
                        printf( ", " );

                    hOverview = GDALGetOverview( hBand, iOverview );
                    if (hOverview != NULL)
                    {
                        printf( "%dx%d",
                                GDALGetRasterBandXSize( hOverview ),
                                GDALGetRasterBandYSize( hOverview ) );

                        pszResampling =
                            GDALGetMetadataItem( hOverview, "RESAMPLING", "" );

                        if( pszResampling != NULL
                            && EQUALN(pszResampling,"AVERAGE_BIT2",12) )
                            printf( "*" );
                    }
                    else
                        printf( "(null)" );
                }
                printf( "\n" );

                if ( bComputeChecksum)
                {
                    printf( "  Overviews checksum: " );
                    for( iOverview = 0;
                        iOverview < GDALGetOverviewCount(hBand);
                        iOverview++ )
                    {
                        GDALRasterBandH     hOverview;

                        if( iOverview != 0 )
                            printf( ", " );

                        hOverview = GDALGetOverview( hBand, iOverview );
                        if (hOverview)
                            printf( "%d",
                                    GDALChecksumImage(hOverview, 0, 0,
                                            GDALGetRasterBandXSize(hOverview),
                                            GDALGetRasterBandYSize(hOverview)));
                        else
                            printf( "(null)" );
                    }
                    printf( "\n" );
                }
            }

            if( GDALHasArbitraryOverviews( hBand ) )
            {
                printf( "  Overviews: arbitrary\n" );
            }

            nMaskFlags = GDALGetMaskFlags( hBand );
            if( (nMaskFlags & (GMF_NODATA|GMF_ALL_VALID)) == 0 )
            {
                GDALRasterBandH hMaskBand = GDALGetMaskBand(hBand) ;

                printf( "  Mask Flags: " );
                if( nMaskFlags & GMF_PER_DATASET )
                    printf( "PER_DATASET " );
                if( nMaskFlags & GMF_ALPHA )
                    printf( "ALPHA " );
                if( nMaskFlags & GMF_NODATA )
                    printf( "NODATA " );
                if( nMaskFlags & GMF_ALL_VALID )
                    printf( "ALL_VALID " );
                printf( "\n" );

                if( hMaskBand != NULL &&
                    GDALGetOverviewCount(hMaskBand) > 0 )
                {
                    int             iOverview;

                    printf( "  Overviews of mask band: " );
                    for( iOverview = 0;
                         iOverview < GDALGetOverviewCount(hMaskBand);
                         iOverview++ )
                    {
                        GDALRasterBandH     hOverview;

                        if( iOverview != 0 )
                            printf( ", " );

                        hOverview = GDALGetOverview( hMaskBand, iOverview );
                        printf( "%dx%d",
                                GDALGetRasterBandXSize( hOverview ),
                                GDALGetRasterBandYSize( hOverview ) );
                    }
                    printf( "\n" );
                }
            }

            if( strlen(GDALGetRasterUnitType(hBand)) > 0 )
            {
                printf( "  Unit Type: %s\n", GDALGetRasterUnitType(hBand) );
            }

            if( GDALGetRasterCategoryNames(hBand) != NULL )
            {
                char **papszCategories = GDALGetRasterCategoryNames(hBand);
                int i;

                printf( "  Categories:\n" );
                for( i = 0; papszCategories[i] != NULL; i++ )
                    printf( "    %3d: %s\n", i, papszCategories[i] );
            }

            if( GDALGetRasterScale( hBand, &bSuccess ) != 1.0
                || GDALGetRasterOffset( hBand, &bSuccess ) != 0.0 )
                printf( "  Offset: %.15g,   Scale:%.15g\n",
                        GDALGetRasterOffset( hBand, &bSuccess ),
                        GDALGetRasterScale( hBand, &bSuccess ) );

            papszMetadata = (bShowMetadata) ? GDALGetMetadata( hBand, NULL ) : NULL;
            if( bShowMetadata && CSLCount(papszMetadata) > 0 )
            {
                printf( "  Metadata:\n" );
                for( i = 0; papszMetadata[i] != NULL; i++ )
                {
                    printf( "    %s\n", papszMetadata[i] );
                }
            }

            papszMetadata = (bShowMetadata) ? GDALGetMetadata( hBand, "IMAGE_STRUCTURE" ) : NULL;
            if( bShowMetadata && CSLCount(papszMetadata) > 0 )
            {
                printf( "  Image Structure Metadata:\n" );
                for( i = 0; papszMetadata[i] != NULL; i++ )
                {
                    printf( "    %s\n", papszMetadata[i] );
                }
            }

            if( GDALGetRasterColorInterpretation(hBand) == GCI_PaletteIndex
                && (hTable = GDALGetRasterColorTable( hBand )) != NULL )
            {
                int                 i;

                printf( "  Color Table (%s with %d entries)\n",
                        GDALGetPaletteInterpretationName(
                            GDALGetPaletteInterpretation( hTable )),
                        GDALGetColorEntryCount( hTable ) );

                if (bShowColorTable)
                {
                    for( i = 0; i < GDALGetColorEntryCount( hTable ); i++ )
                    {
                        GDALColorEntry      sEntry;

                        GDALGetColorEntryAsRGB( hTable, i, &sEntry );
                        printf( "  %3d: %d,%d,%d,%d\n",
                                i,
                                sEntry.c1,
                                sEntry.c2,
                                sEntry.c3,
                                sEntry.c4 );
                    }
                }
            }

            if( bShowRAT && GDALGetDefaultRAT( hBand ) != NULL )
            {
                GDALRasterAttributeTableH hRAT = GDALGetDefaultRAT( hBand );

                GDALRATDumpReadable( hRAT, NULL );
            }
        }

        GDALClose( hDataset );

        CSLDestroy( papszExtraMDDomains );
        CSLDestroy( argv );

        GDALDumpOpenDatasets( stderr );

        GDALDestroyDriverManager();

        CPLDumpSharedList( NULL );
        CPLCleanupTLS();

        exit( 0 );
    }

    /************************************************************************/
    /*                        GDALInfoReportCorner()                        */
    /************************************************************************/

    static int
    GDALInfoReportCorner( GDALDatasetH hDataset,
                          OGRCoordinateTransformationH hTransform,
                          const char * corner_name,
                          double x, double y )

    {
        double      dfGeoX, dfGeoY;
        double      adfGeoTransform[6];

        printf( "%-11s ", corner_name );

    /* -------------------------------------------------------------------- */
    /*      Transform the point into georeferenced coordinates.             */
    /* -------------------------------------------------------------------- */
        if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None )
        {
            dfGeoX = adfGeoTransform[0] + adfGeoTransform[1] * x
                + adfGeoTransform[2] * y;
            dfGeoY = adfGeoTransform[3] + adfGeoTransform[4] * x
                + adfGeoTransform[5] * y;
        }

        else
        {
            printf( "(%7.1f,%7.1f)\n", x, y );
            return FALSE;
        }

    /* -------------------------------------------------------------------- */
    /*      Report the georeferenced coordinates.                           */
    /* -------------------------------------------------------------------- */
        if( ABS(dfGeoX) < 181 && ABS(dfGeoY) < 91 )
        {
            printf( "(%12.7f,%12.7f) ", dfGeoX, dfGeoY );
        }
        else
        {
            printf( "(%12.3f,%12.3f) ", dfGeoX, dfGeoY );
        }

    /* -------------------------------------------------------------------- */
    /*      Transform to latlong and report.                                */
    /* -------------------------------------------------------------------- */
        if( hTransform != NULL
            && OCTTransform(hTransform,1,&dfGeoX,&dfGeoY,NULL) )
        {

            printf( "(%s,", GDALDecToDMS( dfGeoX, "Long", 2 ) );
            printf( "%s)", GDALDecToDMS( dfGeoY, "Lat", 2 ) );
        }

        printf( "\n" );

        return TRUE;
    }

Generated for GDAL by 1.7.1.