|
GDAL
|
/****************************************************************************** * * Project: GDAL Utilities * Purpose: Command line application to list info about a file. * Author: Frank Warmerdam, warmerdam@pobox.com * * **************************************************************************** * Copyright (c) 1998, Frank Warmerdam * Copyright (c) 2007-2015, Even Rouault <even.rouault at spatialys.com> * Copyright (c) 2015, Faza Mahamood * * 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 "cpl_port.h" #include "gdal_utils.h" #include "gdal_utils_priv.h" #include <cmath> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <new> #include <string> #include <vector> #include "commonutils.h" #include "cpl_conv.h" #include "cpl_error.h" #include "cpl_minixml.h" #include "cpl_progress.h" #include "cpl_string.h" #include "cpl_vsi.h" #include "gdal.h" #include "gdal_alg.h" #include "gdal_priv.h" #include "gdal_rat.h" #include "ogr_api.h" #include "ogr_json_header.h" #include "ogr_srs_api.h" #include "ogrgeojsonreader.h" #include "ogrgeojsonwriter.h" using std::vector; CPL_CVSID("$Id: gdalinfo_lib.cpp 38115 2017-04-23 07:24:41Z rouault $"); typedef enum { GDALINFO_FORMAT_TEXT = 0, GDALINFO_FORMAT_JSON = 1 } GDALInfoFormat; /************************************************************************/ /* GDALInfoOptions */ /************************************************************************/ struct GDALInfoOptions { GDALInfoFormat eFormat; int bComputeMinMax; int bReportHistograms; int bReportProj4; int bStats; int bApproxStats; int bSample; int bComputeChecksum; int bShowGCPs; int bShowMetadata; int bShowRAT; int bShowColorTable; int bListMDD; int bShowFileList; char **papszExtraMDDomains; bool bStdoutOutput; }; static int GDALInfoReportCorner( const GDALInfoOptions* psOptions, GDALDatasetH hDataset, OGRCoordinateTransformationH hTransform, const char * corner_name, double x, double y, bool bJson, json_object *poCornerCoordinates, json_object *poLongLatExtentCoordinates, CPLString& osStr ); static void GDALInfoReportMetadata( const GDALInfoOptions* psOptions, GDALMajorObjectH hObject, bool bIsBand, bool bJson, json_object *poMetadata, CPLString& osStr ); static void Concat( CPLString& osRet, bool bStdoutOutput, const char* pszFormat, ... ) CPL_PRINT_FUNC_FORMAT (3, 4); static void Concat( CPLString& osRet, bool bStdoutOutput, const char* pszFormat, ... ) { va_list args; va_start( args, pszFormat ); if( bStdoutOutput ) { vfprintf(stdout, pszFormat, args ); } else { try { CPLString osTarget; osTarget.vPrintf( pszFormat, args ); osRet += osTarget; } catch( const std::bad_alloc& ) { CPLError(CE_Failure, CPLE_OutOfMemory, "Out of memory"); } } va_end( args ); } /************************************************************************/ /* GDALInfo() */ /************************************************************************/ char *GDALInfo( GDALDatasetH hDataset, const GDALInfoOptions *psOptions ) { if( hDataset == NULL ) return NULL; GDALInfoOptions* psOptionsToFree = NULL; if( psOptions == NULL ) { psOptionsToFree = GDALInfoOptionsNew(NULL, NULL); psOptions = psOptionsToFree; } CPLString osStr; json_object *poJsonObject = NULL; json_object *poBands = NULL; json_object *poMetadata = NULL; const bool bJson = psOptions->eFormat == GDALINFO_FORMAT_JSON; /* -------------------------------------------------------------------- */ /* Report general info. */ /* -------------------------------------------------------------------- */ GDALDriverH hDriver = GDALGetDatasetDriver( hDataset ); if( bJson ) { json_object *poDescription = json_object_new_string(GDALGetDescription(hDataset)); json_object *poDriverShortName = json_object_new_string(GDALGetDriverShortName(hDriver)); json_object *poDriverLongName = json_object_new_string(GDALGetDriverLongName(hDriver)); poJsonObject = json_object_new_object(); poBands = json_object_new_array(); poMetadata = json_object_new_object(); json_object_object_add(poJsonObject, "description", poDescription); json_object_object_add(poJsonObject, "driverShortName", poDriverShortName); json_object_object_add(poJsonObject, "driverLongName", poDriverLongName); } else { Concat( osStr, psOptions->bStdoutOutput, "Driver: %s/%s\n", GDALGetDriverShortName( hDriver ), GDALGetDriverLongName( hDriver ) ); } char **papszFileList = GDALGetFileList( hDataset ); if( papszFileList == NULL || *papszFileList == NULL ) { if( bJson ) { json_object *poFiles = json_object_new_array(); json_object_object_add(poJsonObject, "files", poFiles); } else { Concat( osStr, psOptions->bStdoutOutput, "Files: none associated\n" ); } } else { if( bJson ) { if( psOptions->bShowFileList ) { json_object *poFiles = json_object_new_array(); for( int i = 0; papszFileList[i] != NULL; i++ ) { json_object *poFile = json_object_new_string(papszFileList[i]); json_object_array_add(poFiles, poFile); } json_object_object_add(poJsonObject, "files", poFiles); } } else { Concat(osStr, psOptions->bStdoutOutput, "Files: %s\n", papszFileList[0] ); if( psOptions->bShowFileList ) { for( int i = 1; papszFileList[i] != NULL; i++ ) Concat(osStr, psOptions->bStdoutOutput, " %s\n", papszFileList[i] ); } } } CSLDestroy( papszFileList ); if( bJson ) { json_object *poSize = json_object_new_array(); json_object *poSizeX = json_object_new_int(GDALGetRasterXSize(hDataset)); json_object *poSizeY = json_object_new_int(GDALGetRasterYSize(hDataset)); json_object_array_add(poSize, poSizeX); json_object_array_add(poSize, poSizeY); json_object_object_add(poJsonObject, "size", poSize); } else { Concat(osStr, psOptions->bStdoutOutput, "Size is %d, %d\n", GDALGetRasterXSize( hDataset ), GDALGetRasterYSize( hDataset ) ); } /* -------------------------------------------------------------------- */ /* Report projection. */ /* -------------------------------------------------------------------- */ if( GDALGetProjectionRef( hDataset ) != NULL ) { json_object *poCoordinateSystem = NULL; if( bJson ) poCoordinateSystem = json_object_new_object(); char *pszProjection = const_cast<char *>( GDALGetProjectionRef( hDataset ) ); OGRSpatialReferenceH hSRS = OSRNewSpatialReference(NULL); if( OSRImportFromWkt( hSRS, &pszProjection ) == CE_None ) { char *pszPrettyWkt = NULL; OSRExportToPrettyWkt( hSRS, &pszPrettyWkt, FALSE ); if( bJson ) { json_object *poWkt = json_object_new_string(pszPrettyWkt); json_object_object_add(poCoordinateSystem, "wkt", poWkt); } else { Concat( osStr, psOptions->bStdoutOutput, "Coordinate System is:\n%s\n", pszPrettyWkt ); } CPLFree( pszPrettyWkt ); } else { if( bJson ) { json_object *poWkt = json_object_new_string(GDALGetProjectionRef(hDataset)); json_object_object_add(poCoordinateSystem, "wkt", poWkt); } else { Concat( osStr, psOptions->bStdoutOutput, "Coordinate System is `%s'\n", GDALGetProjectionRef( hDataset ) ); } } if ( psOptions->bReportProj4 ) { char *pszProj4 = NULL; OSRExportToProj4( hSRS, &pszProj4 ); if( bJson ) { json_object *proj4 = json_object_new_string(pszProj4); json_object_object_add(poCoordinateSystem, "proj4", proj4); } else Concat(osStr, psOptions->bStdoutOutput, "PROJ.4 string is:\n\'%s\'\n",pszProj4); CPLFree( pszProj4 ); } if( bJson ) json_object_object_add(poJsonObject, "coordinateSystem", poCoordinateSystem); OSRDestroySpatialReference( hSRS ); } /* -------------------------------------------------------------------- */ /* Report Geotransform. */ /* -------------------------------------------------------------------- */ double adfGeoTransform[6] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 }; if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None ) { if( bJson ) { json_object *poGeoTransform = json_object_new_array(); for( int i = 0; i < 6; i++ ) { json_object *poGeoTransformCoefficient = json_object_new_double_with_precision(adfGeoTransform[i], 16); json_object_array_add(poGeoTransform, poGeoTransformCoefficient); } json_object_object_add(poJsonObject, "geoTransform", poGeoTransform); } else { if( adfGeoTransform[2] == 0.0 && adfGeoTransform[4] == 0.0 ) { Concat( osStr, psOptions->bStdoutOutput, "Origin = (%.15f,%.15f)\n", adfGeoTransform[0], adfGeoTransform[3] ); Concat( osStr, psOptions->bStdoutOutput, "Pixel Size = (%.15f,%.15f)\n", adfGeoTransform[1], adfGeoTransform[5] ); } else { Concat( osStr, psOptions->bStdoutOutput, "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( psOptions->bShowGCPs && GDALGetGCPCount( hDataset ) > 0 ) { json_object * const poGCPs = bJson ? json_object_new_object() : NULL; if (GDALGetGCPProjection(hDataset) != NULL) { json_object *poGCPCoordinateSystem = NULL; char *pszProjection = const_cast<char *>( GDALGetGCPProjection( hDataset ) ); OGRSpatialReferenceH hSRS = OSRNewSpatialReference(NULL); if( OSRImportFromWkt( hSRS, &pszProjection ) == CE_None ) { char *pszPrettyWkt = NULL; OSRExportToPrettyWkt( hSRS, &pszPrettyWkt, FALSE ); if( bJson ) { json_object *poWkt = json_object_new_string(pszPrettyWkt); poGCPCoordinateSystem = json_object_new_object(); json_object_object_add(poGCPCoordinateSystem, "wkt", poWkt); } else { Concat(osStr, psOptions->bStdoutOutput, "GCP Projection = \n%s\n", pszPrettyWkt ); } CPLFree( pszPrettyWkt ); } else { if(bJson) { json_object *poWkt = json_object_new_string(GDALGetGCPProjection(hDataset)); poGCPCoordinateSystem = json_object_new_object(); json_object_object_add(poGCPCoordinateSystem, "wkt", poWkt); } else { Concat(osStr, psOptions->bStdoutOutput, "GCP Projection = %s\n", GDALGetGCPProjection( hDataset ) ); } } if(bJson) json_object_object_add(poGCPs, "coordinateSystem", poGCPCoordinateSystem); OSRDestroySpatialReference( hSRS ); } json_object * const poGCPList = bJson ? json_object_new_array() : NULL; for( int i = 0; i < GDALGetGCPCount(hDataset); i++ ) { const GDAL_GCP *psGCP = GDALGetGCPs( hDataset ) + i; if( bJson ) { json_object *poGCP = json_object_new_object(); json_object *poId = json_object_new_string(psGCP->pszId); json_object *poInfo = json_object_new_string(psGCP->pszInfo); json_object *poPixel = json_object_new_double_with_precision(psGCP->dfGCPPixel, 15); json_object *poLine = json_object_new_double_with_precision(psGCP->dfGCPLine, 15); json_object *poX = json_object_new_double_with_precision(psGCP->dfGCPX, 15); json_object *poY = json_object_new_double_with_precision(psGCP->dfGCPY, 15); json_object *poZ = json_object_new_double_with_precision(psGCP->dfGCPZ, 15); json_object_object_add(poGCP, "id", poId); json_object_object_add(poGCP, "info", poInfo); json_object_object_add(poGCP, "pixel", poPixel); json_object_object_add(poGCP, "line", poLine); json_object_object_add(poGCP, "x", poX); json_object_object_add(poGCP, "y", poY); json_object_object_add(poGCP, "z", poZ); json_object_array_add(poGCPList, poGCP); } else { Concat(osStr, psOptions->bStdoutOutput, "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 ); } } if( bJson ) { json_object_object_add(poGCPs, "gcpList", poGCPList); json_object_object_add(poJsonObject, "gcps", poGCPs); } } /* -------------------------------------------------------------------- */ /* Report metadata. */ /* -------------------------------------------------------------------- */ GDALInfoReportMetadata( psOptions, hDataset, false, bJson, poMetadata, osStr ); if( bJson ) { if( psOptions->bShowMetadata ) json_object_object_add( poJsonObject, "metadata", poMetadata ); else json_object_put(poMetadata); } /* -------------------------------------------------------------------- */ /* Setup projected to lat/long transform if appropriate. */ /* -------------------------------------------------------------------- */ const char *pszProjection = NULL; if( GDALGetGeoTransform( hDataset, adfGeoTransform ) == CE_None ) pszProjection = GDALGetProjectionRef(hDataset); OGRCoordinateTransformationH hTransform = NULL; bool bTransformToWGS84 = false; if( pszProjection != NULL && strlen(pszProjection) > 0 ) { OGRSpatialReferenceH hLatLong = NULL; OGRSpatialReferenceH hProj = OSRNewSpatialReference( pszProjection ); if( hProj != NULL ) { OGRErr eErr = OGRERR_NONE; // Check that it looks like Earth before trying to reproject to wgs84... if(bJson && fabs( OSRGetSemiMajor(hProj, &eErr) - 6378137.0) < 10000.0 && eErr == OGRERR_NONE ) { bTransformToWGS84 = true; hLatLong = OSRNewSpatialReference( NULL ); OSRSetWellKnownGeogCS( hLatLong, "WGS84" ); } else { hLatLong = OSRCloneGeogCS( hProj ); } } if( hLatLong != NULL ) { CPLPushErrorHandler( CPLQuietErrorHandler ); hTransform = OCTNewCoordinateTransformation( hProj, hLatLong ); CPLPopErrorHandler(); OSRDestroySpatialReference( hLatLong ); } if( hProj != NULL ) OSRDestroySpatialReference( hProj ); } /* -------------------------------------------------------------------- */ /* Report corners. */ /* -------------------------------------------------------------------- */ if( bJson ) { json_object *poLinearRing = json_object_new_array(); json_object *poCornerCoordinates = json_object_new_object(); json_object *poLongLatExtent = json_object_new_object(); json_object *poLongLatExtentType = json_object_new_string("Polygon"); json_object *poLongLatExtentCoordinates = json_object_new_array(); GDALInfoReportCorner( psOptions, hDataset, hTransform, "upperLeft", 0.0, 0.0, bJson, poCornerCoordinates, poLongLatExtentCoordinates, osStr ); GDALInfoReportCorner( psOptions, hDataset, hTransform, "lowerLeft", 0.0, GDALGetRasterYSize(hDataset), bJson, poCornerCoordinates, poLongLatExtentCoordinates, osStr ); GDALInfoReportCorner( psOptions, hDataset, hTransform, "lowerRight", GDALGetRasterXSize(hDataset), GDALGetRasterYSize(hDataset), bJson, poCornerCoordinates, poLongLatExtentCoordinates, osStr ); GDALInfoReportCorner( psOptions, hDataset, hTransform, "upperRight", GDALGetRasterXSize(hDataset), 0.0, bJson, poCornerCoordinates, poLongLatExtentCoordinates, osStr ); GDALInfoReportCorner( psOptions, hDataset, hTransform, "center", GDALGetRasterXSize(hDataset) / 2.0, GDALGetRasterYSize(hDataset) / 2.0, bJson, poCornerCoordinates, poLongLatExtentCoordinates, osStr ); GDALInfoReportCorner( psOptions, hDataset, hTransform, "upperLeft", 0.0, 0.0, bJson, poCornerCoordinates, poLongLatExtentCoordinates, osStr ); json_object_object_add( poJsonObject, "cornerCoordinates", poCornerCoordinates ); json_object_object_add( poLongLatExtent, "type", poLongLatExtentType ); json_object_array_add( poLinearRing, poLongLatExtentCoordinates ); json_object_object_add( poLongLatExtent, "coordinates", poLinearRing ); json_object_object_add( poJsonObject, bTransformToWGS84 ? "wgs84Extent": "extent", poLongLatExtent ); } else { Concat(osStr, psOptions->bStdoutOutput, "Corner Coordinates:\n" ); GDALInfoReportCorner( psOptions, hDataset, hTransform, "Upper Left", 0.0, 0.0, bJson, NULL, NULL, osStr ); GDALInfoReportCorner( psOptions, hDataset, hTransform, "Lower Left", 0.0, GDALGetRasterYSize(hDataset), bJson, NULL, NULL, osStr ); GDALInfoReportCorner( psOptions, hDataset, hTransform, "Upper Right", GDALGetRasterXSize(hDataset), 0.0, bJson, NULL, NULL, osStr ); GDALInfoReportCorner( psOptions, hDataset, hTransform, "Lower Right", GDALGetRasterXSize(hDataset), GDALGetRasterYSize(hDataset), bJson, NULL, NULL, osStr ); GDALInfoReportCorner( psOptions, hDataset, hTransform, "Center", GDALGetRasterXSize(hDataset)/2.0, GDALGetRasterYSize(hDataset)/2.0, bJson, NULL, NULL, osStr ); } if( hTransform != NULL ) { OCTDestroyCoordinateTransformation( hTransform ); hTransform = NULL; } /* ==================================================================== */ /* Loop over bands. */ /* ==================================================================== */ for( int iBand = 0; iBand < GDALGetRasterCount( hDataset ); iBand++ ) { json_object *poBand = NULL; json_object *poBandMetadata = NULL; if( bJson ) { poBand = json_object_new_object(); poBandMetadata = json_object_new_object(); } GDALRasterBandH const hBand = GDALGetRasterBand( hDataset, iBand+1 ); if( psOptions->bSample ) { vector<float> ofSample(10000, 0); float * const pafSample = &ofSample[0]; const int nCount = GDALGetRandomRasterSample( hBand, 10000, pafSample ); if( !bJson ) Concat( osStr, psOptions->bStdoutOutput, "Got %d samples.\n", nCount ); } int nBlockXSize = 0; int nBlockYSize = 0; GDALGetBlockSize( hBand, &nBlockXSize, &nBlockYSize ); if( bJson ) { json_object *poBandNumber = json_object_new_int(iBand+1); json_object *poBlock = json_object_new_array(); json_object *poType = json_object_new_string( GDALGetDataTypeName(GDALGetRasterDataType(hBand))); json_object *poColorInterp = json_object_new_string( GDALGetColorInterpretationName( GDALGetRasterColorInterpretation(hBand))); json_object_array_add(poBlock, json_object_new_int(nBlockXSize)); json_object_array_add(poBlock, json_object_new_int(nBlockYSize)); json_object_object_add(poBand, "band", poBandNumber); json_object_object_add(poBand, "block", poBlock); json_object_object_add(poBand, "type", poType); json_object_object_add(poBand, "colorInterpretation", poColorInterp); } else { Concat( osStr, psOptions->bStdoutOutput, "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 ) { if(bJson) { json_object *poBandDescription = json_object_new_string(GDALGetDescription(hBand)); json_object_object_add(poBand, "description", poBandDescription); } else { Concat( osStr, psOptions->bStdoutOutput, " Description = %s\n", GDALGetDescription(hBand) ); } } { int bGotMin = FALSE; int bGotMax = FALSE; const double dfMin = GDALGetRasterMinimum( hBand, &bGotMin ); const double dfMax = GDALGetRasterMaximum( hBand, &bGotMax ); if( bGotMin || bGotMax || psOptions->bComputeMinMax ) { if( !bJson ) Concat(osStr, psOptions->bStdoutOutput, " " ); if( bGotMin ) { if( bJson ) { json_object *poMin = json_object_new_double_with_precision(dfMin, 3); json_object_object_add(poBand, "min", poMin); } else { Concat(osStr, psOptions->bStdoutOutput, "Min=%.3f ", dfMin ); } } if( bGotMax ) { if( bJson ) { json_object *poMax = json_object_new_double_with_precision(dfMax, 3); json_object_object_add(poBand, "max", poMax); } else { Concat(osStr, psOptions->bStdoutOutput, "Max=%.3f ", dfMax ); } } if( psOptions->bComputeMinMax ) { CPLErrorReset(); double adfCMinMax[2] = {0.0, 0.0}; GDALComputeRasterMinMax( hBand, FALSE, adfCMinMax ); if( CPLGetLastErrorType() == CE_None ) { if( bJson ) { json_object *poComputedMin = json_object_new_double_with_precision( adfCMinMax[0], 3); json_object *poComputedMax = json_object_new_double_with_precision( adfCMinMax[1], 3); json_object_object_add(poBand, "computedMin", poComputedMin); json_object_object_add(poBand, "computedMax", poComputedMax); } else { Concat(osStr, psOptions->bStdoutOutput, " Computed Min/Max=%.3f,%.3f", adfCMinMax[0], adfCMinMax[1] ); } } } if(!bJson) Concat(osStr, psOptions->bStdoutOutput, "\n" ); } } double dfMinStat = 0.0; double dfMaxStat = 0.0; double dfMean = 0.0; double dfStdDev = 0.0; CPLErr eErr = GDALGetRasterStatistics( hBand, psOptions->bApproxStats, psOptions->bStats, &dfMinStat, &dfMaxStat, &dfMean, &dfStdDev ); if( eErr == CE_None ) { if( bJson ) { json_object *poMinimum = json_object_new_double_with_precision(dfMinStat, 3); json_object *poMaximum = json_object_new_double_with_precision(dfMaxStat, 3); json_object *poMean = json_object_new_double_with_precision(dfMean, 3); json_object *poStdDev = json_object_new_double_with_precision(dfStdDev, 3); json_object_object_add(poBand, "minimum", poMinimum); json_object_object_add(poBand, "maximum", poMaximum); json_object_object_add(poBand, "mean", poMean); json_object_object_add(poBand, "stdDev", poStdDev); } else { Concat(osStr, psOptions->bStdoutOutput, " Minimum=%.3f, Maximum=%.3f, Mean=%.3f, StdDev=%.3f\n", dfMinStat, dfMaxStat, dfMean, dfStdDev ); } } if( psOptions->bReportHistograms ) { int nBucketCount = 0; GUIntBig *panHistogram = NULL; if( bJson ) eErr = GDALGetDefaultHistogramEx( hBand, &dfMinStat, &dfMaxStat, &nBucketCount, &panHistogram, TRUE, GDALDummyProgress, NULL ); else eErr = GDALGetDefaultHistogramEx( hBand, &dfMinStat, &dfMaxStat, &nBucketCount, &panHistogram, TRUE, GDALTermProgress, NULL ); if( eErr == CE_None ) { json_object *poHistogram = NULL; json_object *poBuckets = NULL; if( bJson ) { json_object *poCount = json_object_new_int(nBucketCount); json_object *poMin = json_object_new_double(dfMinStat); json_object *poMax = json_object_new_double(dfMaxStat); poBuckets = json_object_new_array(); poHistogram = json_object_new_object(); json_object_object_add(poHistogram, "count", poCount); json_object_object_add(poHistogram, "min", poMin); json_object_object_add(poHistogram, "max", poMax); } else { Concat(osStr, psOptions->bStdoutOutput, " %d buckets from %g to %g:\n ", nBucketCount, dfMinStat, dfMaxStat ); } for( int iBucket = 0; iBucket < nBucketCount; iBucket++ ) { if(bJson) { json_object *poBucket = json_object_new_int64(panHistogram[iBucket]); json_object_array_add(poBuckets, poBucket); } else Concat(osStr, psOptions->bStdoutOutput, CPL_FRMT_GUIB " ", panHistogram[iBucket] ); } if( bJson ) { json_object_object_add(poHistogram, "buckets", poBuckets); json_object_object_add(poBand, "histogram", poHistogram); } else { Concat(osStr, psOptions->bStdoutOutput, "\n" ); } CPLFree( panHistogram ); } } if ( psOptions->bComputeChecksum) { const int nBandChecksum = GDALChecksumImage(hBand, 0, 0, GDALGetRasterXSize(hDataset), GDALGetRasterYSize(hDataset)); if( bJson ) { json_object *poChecksum = json_object_new_int(nBandChecksum); json_object_object_add(poBand, "checksum", poChecksum); } else { Concat(osStr, psOptions->bStdoutOutput, " Checksum=%d\n", nBandChecksum ); } } int bGotNodata = FALSE; const double dfNoData = GDALGetRasterNoDataValue( hBand, &bGotNodata ); if( bGotNodata ) { if( CPLIsNan(dfNoData) ) { if( bJson ) { json_object *poNoDataValue = json_object_new_string("nan"); json_object_object_add(poBand, "noDataValue", poNoDataValue); } else { Concat(osStr, psOptions->bStdoutOutput, " NoData Value=nan\n" ); } } else { if(bJson) { json_object *poNoDataValue = json_object_new_double_with_precision(dfNoData, 18); json_object_object_add(poBand, "noDataValue", poNoDataValue); } else { Concat(osStr, psOptions->bStdoutOutput, " NoData Value=%.18g\n", dfNoData ); } } } if( GDALGetOverviewCount(hBand) > 0 ) { json_object *poOverviews = NULL; if( bJson ) poOverviews = json_object_new_array(); else Concat(osStr, psOptions->bStdoutOutput, " Overviews: " ); for( int iOverview = 0; iOverview < GDALGetOverviewCount(hBand); iOverview++ ) { if( !bJson ) if( iOverview != 0 ) Concat(osStr, psOptions->bStdoutOutput, ", " ); GDALRasterBandH hOverview = GDALGetOverview( hBand, iOverview ); if (hOverview != NULL) { if(bJson) { json_object *poOverviewSize = json_object_new_array(); json_object *poOverviewSizeX = json_object_new_int( GDALGetRasterBandXSize( hOverview) ); json_object *poOverviewSizeY = json_object_new_int( GDALGetRasterBandYSize( hOverview) ); json_object *poOverview = json_object_new_object(); json_object_array_add( poOverviewSize, poOverviewSizeX ); json_object_array_add( poOverviewSize, poOverviewSizeY ); json_object_object_add( poOverview, "size", poOverviewSize ); if(psOptions->bComputeChecksum) { const int nOverviewChecksum = GDALChecksumImage( hOverview, 0, 0, GDALGetRasterBandXSize(hOverview), GDALGetRasterBandYSize(hOverview)); json_object *poOverviewChecksum = json_object_new_int(nOverviewChecksum); json_object_object_add(poOverview, "checksum", poOverviewChecksum); } json_object_array_add(poOverviews, poOverview); } else { Concat(osStr, psOptions->bStdoutOutput, "%dx%d", GDALGetRasterBandXSize( hOverview ), GDALGetRasterBandYSize( hOverview ) ); } const char *pszResampling = GDALGetMetadataItem( hOverview, "RESAMPLING", "" ); if( pszResampling != NULL && !bJson && STARTS_WITH_CI(pszResampling, "AVERAGE_BIT2") ) Concat(osStr, psOptions->bStdoutOutput, "*" ); } else { if(!bJson) Concat(osStr, psOptions->bStdoutOutput, "(null)" ); } } if(bJson) json_object_object_add(poBand, "overviews", poOverviews); else Concat(osStr, psOptions->bStdoutOutput, "\n" ); if ( psOptions->bComputeChecksum && !bJson ) { Concat(osStr, psOptions->bStdoutOutput, " Overviews checksum: " ); for( int iOverview = 0; iOverview < GDALGetOverviewCount(hBand); iOverview++ ) { GDALRasterBandH hOverview; if( iOverview != 0 ) Concat(osStr, psOptions->bStdoutOutput, ", " ); hOverview = GDALGetOverview( hBand, iOverview ); if (hOverview) { Concat(osStr, psOptions->bStdoutOutput, "%d", GDALChecksumImage(hOverview, 0, 0, GDALGetRasterBandXSize(hOverview), GDALGetRasterBandYSize(hOverview))); } else { Concat(osStr, psOptions->bStdoutOutput, "(null)" ); } } Concat(osStr, psOptions->bStdoutOutput, "\n" ); } } if( GDALHasArbitraryOverviews( hBand ) && !bJson ) { Concat(osStr, psOptions->bStdoutOutput, " Overviews: arbitrary\n" ); } const int nMaskFlags = GDALGetMaskFlags( hBand ); if( (nMaskFlags & (GMF_NODATA|GMF_ALL_VALID)) == 0 ) { GDALRasterBandH hMaskBand = GDALGetMaskBand(hBand) ; json_object *poMask = NULL; json_object *poFlags = NULL; json_object *poMaskOverviews = NULL; if(bJson) { poMask = json_object_new_object(); poFlags = json_object_new_array(); } else Concat(osStr, psOptions->bStdoutOutput, " Mask Flags: " ); if( nMaskFlags & GMF_PER_DATASET ) { if(bJson) { json_object *poFlag = json_object_new_string( "PER_DATASET" ); json_object_array_add( poFlags, poFlag ); } else Concat(osStr, psOptions->bStdoutOutput, "PER_DATASET " ); } if( nMaskFlags & GMF_ALPHA ) { if(bJson) { json_object *poFlag = json_object_new_string( "ALPHA" ); json_object_array_add( poFlags, poFlag ); } else Concat(osStr, psOptions->bStdoutOutput, "ALPHA " ); } if( nMaskFlags & GMF_NODATA ) { if(bJson) { json_object *poFlag = json_object_new_string( "NODATA" ); json_object_array_add( poFlags, poFlag ); } else { Concat(osStr, psOptions->bStdoutOutput, "NODATA " ); } } if( nMaskFlags & GMF_ALL_VALID ) { if(bJson) { json_object *poFlag = json_object_new_string( "ALL_VALID" ); json_object_array_add( poFlags, poFlag ); } else Concat(osStr, psOptions->bStdoutOutput, "ALL_VALID " ); } if(bJson) json_object_object_add( poMask, "flags", poFlags ); else Concat(osStr, psOptions->bStdoutOutput, "\n" ); if(bJson) poMaskOverviews = json_object_new_array(); if( hMaskBand != NULL && GDALGetOverviewCount(hMaskBand) > 0 ) { if(!bJson) Concat(osStr, psOptions->bStdoutOutput, " Overviews of mask band: " ); for( int iOverview = 0; iOverview < GDALGetOverviewCount(hMaskBand); iOverview++ ) { GDALRasterBandH hOverview; json_object *poMaskOverview = NULL; json_object *poMaskOverviewSize = NULL; if(bJson) { poMaskOverview = json_object_new_object(); poMaskOverviewSize = json_object_new_array(); } else { if( iOverview != 0 ) Concat(osStr, psOptions->bStdoutOutput, ", " ); } hOverview = GDALGetOverview( hMaskBand, iOverview ); if(bJson) { json_object *poMaskOverviewSizeX = json_object_new_int( GDALGetRasterBandXSize(hOverview)); json_object *poMaskOverviewSizeY = json_object_new_int( GDALGetRasterBandYSize(hOverview)); json_object_array_add(poMaskOverviewSize, poMaskOverviewSizeX); json_object_array_add(poMaskOverviewSize, poMaskOverviewSizeY); json_object_object_add(poMaskOverview, "size", poMaskOverviewSize); json_object_array_add(poMaskOverviews, poMaskOverview); } else { Concat( osStr, psOptions->bStdoutOutput, "%dx%d", GDALGetRasterBandXSize( hOverview ), GDALGetRasterBandYSize( hOverview ) ); } } if( !bJson ) Concat(osStr, psOptions->bStdoutOutput, "\n" ); } if(bJson) { json_object_object_add(poMask, "overviews", poMaskOverviews); json_object_object_add(poBand, "mask", poMask); } } if( strlen(GDALGetRasterUnitType(hBand)) > 0 ) { if( bJson ) { json_object *poUnit = json_object_new_string(GDALGetRasterUnitType(hBand)); json_object_object_add(poBand, "unit", poUnit); } else { Concat(osStr, psOptions->bStdoutOutput, " Unit Type: %s\n", GDALGetRasterUnitType(hBand) ); } } if( GDALGetRasterCategoryNames(hBand) != NULL ) { char **papszCategories = GDALGetRasterCategoryNames(hBand); json_object *poCategories = NULL; if( bJson ) poCategories = json_object_new_array(); else Concat(osStr, psOptions->bStdoutOutput, " Categories:\n" ); for( int i = 0; papszCategories[i] != NULL; i++ ) { if(bJson) { json_object *poCategoryName = json_object_new_string(papszCategories[i]); json_object_array_add(poCategories, poCategoryName); } else Concat(osStr, psOptions->bStdoutOutput, " %3d: %s\n", i, papszCategories[i] ); } if(bJson) json_object_object_add(poBand, "categories", poCategories); } int bSuccess = FALSE; if( GDALGetRasterScale( hBand, &bSuccess ) != 1.0 || GDALGetRasterOffset( hBand, &bSuccess ) != 0.0 ) { if( bJson ) { json_object *poOffset = json_object_new_double_with_precision( GDALGetRasterOffset(hBand, &bSuccess), 15); json_object *poScale = json_object_new_double_with_precision( GDALGetRasterScale(hBand, &bSuccess), 15); json_object_object_add(poBand, "offset", poOffset); json_object_object_add(poBand, "scale", poScale); } else { Concat(osStr, psOptions->bStdoutOutput, " Offset: %.15g, Scale:%.15g\n", GDALGetRasterOffset( hBand, &bSuccess ), GDALGetRasterScale( hBand, &bSuccess ) ); } } GDALInfoReportMetadata( psOptions, hBand, true, bJson, poBandMetadata, osStr ); if( bJson ) { if (psOptions->bShowMetadata) json_object_object_add( poBand, "metadata", poBandMetadata ); else json_object_put(poBandMetadata); } GDALColorTableH hTable; if( GDALGetRasterColorInterpretation(hBand) == GCI_PaletteIndex && (hTable = GDALGetRasterColorTable( hBand )) != NULL ) { if( !bJson ) Concat( osStr, psOptions->bStdoutOutput, " Color Table (%s with %d entries)\n", GDALGetPaletteInterpretationName( GDALGetPaletteInterpretation( hTable )), GDALGetColorEntryCount( hTable ) ); if (psOptions->bShowColorTable) { json_object *poEntries = NULL; if( bJson ) { json_object *poPalette = json_object_new_string(GDALGetPaletteInterpretationName( GDALGetPaletteInterpretation(hTable))); json_object *poCount = json_object_new_int(GDALGetColorEntryCount(hTable)); json_object *poColorTable = json_object_new_object(); json_object_object_add(poColorTable, "palette", poPalette); json_object_object_add(poColorTable, "count", poCount); poEntries = json_object_new_array(); json_object_object_add(poColorTable, "entries", poEntries); json_object_object_add(poBand, "colorTable", poColorTable); } for( int i = 0; i < GDALGetColorEntryCount( hTable ); i++ ) { GDALColorEntry sEntry; GDALGetColorEntryAsRGB( hTable, i, &sEntry ); if(bJson) { json_object *poEntry = json_object_new_array(); json_object *poC1 = json_object_new_int(sEntry.c1); json_object *poC2 = json_object_new_int(sEntry.c2); json_object *poC3 = json_object_new_int(sEntry.c3); json_object *poC4 = json_object_new_int(sEntry.c4); json_object_array_add(poEntry, poC1); json_object_array_add(poEntry, poC2); json_object_array_add(poEntry, poC3); json_object_array_add(poEntry, poC4); json_object_array_add(poEntries, poEntry); } else { Concat(osStr, psOptions->bStdoutOutput, " %3d: %d,%d,%d,%d\n", i, sEntry.c1, sEntry.c2, sEntry.c3, sEntry.c4 ); } } } } if( psOptions->bShowRAT && GDALGetDefaultRAT( hBand ) != NULL ) { GDALRasterAttributeTableH hRAT = GDALGetDefaultRAT( hBand ); if( bJson ) { json_object *poRAT = (json_object*) GDALRATSerializeJSON( hRAT ); json_object_object_add( poJsonObject, "rat", poRAT ); } else { CPLXMLNode *psTree = ((GDALRasterAttributeTable *) hRAT)->Serialize(); char *pszXMLText = CPLSerializeXMLTree( psTree ); CPLDestroyXMLNode( psTree ); Concat(osStr, psOptions->bStdoutOutput, "%s\n", pszXMLText ); CPLFree( pszXMLText ); } } if(bJson) json_object_array_add(poBands, poBand); } if(bJson) { json_object_object_add(poJsonObject, "bands", poBands); Concat(osStr, psOptions->bStdoutOutput, "%s", json_object_to_json_string_ext(poJsonObject, JSON_C_TO_STRING_PRETTY)); json_object_put(poJsonObject); } if( psOptionsToFree != NULL ) GDALInfoOptionsFree(psOptionsToFree); return VSI_STRDUP_VERBOSE(osStr); } /************************************************************************/ /* GDALInfoReportCorner() */ /************************************************************************/ static int GDALInfoReportCorner( const GDALInfoOptions* psOptions, GDALDatasetH hDataset, OGRCoordinateTransformationH hTransform, const char * corner_name, double x, double y, bool bJson, json_object *poCornerCoordinates, json_object *poLongLatExtentCoordinates, CPLString& osStr ) { if(!bJson) Concat(osStr, psOptions->bStdoutOutput, "%-11s ", corner_name ); /* -------------------------------------------------------------------- */ /* Transform the point into georeferenced coordinates. */ /* -------------------------------------------------------------------- */ double adfGeoTransform[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; double dfGeoX = 0.0; double dfGeoY = 0.0; 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 { if( bJson ) { json_object * const poCorner = json_object_new_array(); json_object * const poX = json_object_new_double_with_precision( x, 1 ); json_object * const poY = json_object_new_double_with_precision( y, 1 ); json_object_array_add( poCorner, poX ); json_object_array_add( poCorner, poY ); json_object_object_add( poCornerCoordinates, corner_name, poCorner ); } else { Concat(osStr, psOptions->bStdoutOutput, "(%7.1f,%7.1f)\n", x, y ); } return FALSE; } /* -------------------------------------------------------------------- */ /* Report the georeferenced coordinates. */ /* -------------------------------------------------------------------- */ if( std::abs(dfGeoX) < 181 && std::abs(dfGeoY) < 91 ) { if(bJson) { json_object * const poCorner = json_object_new_array(); json_object * const poX = json_object_new_double_with_precision( dfGeoX, 7 ); json_object * const poY = json_object_new_double_with_precision( dfGeoY, 7 ); json_object_array_add( poCorner, poX ); json_object_array_add( poCorner, poY ); json_object_object_add( poCornerCoordinates, corner_name, poCorner ); } else { Concat(osStr, psOptions->bStdoutOutput, "(%12.7f,%12.7f) ", dfGeoX, dfGeoY ); } } else { if(bJson) { json_object * const poCorner = json_object_new_array(); json_object * const poX = json_object_new_double_with_precision( dfGeoX, 3 ); json_object * const poY = json_object_new_double_with_precision( dfGeoY, 3 ); json_object_array_add( poCorner, poX ); json_object_array_add( poCorner, poY ); json_object_object_add( poCornerCoordinates, corner_name, poCorner ); } else { Concat(osStr, psOptions->bStdoutOutput, "(%12.3f,%12.3f) ", dfGeoX, dfGeoY ); } } /* -------------------------------------------------------------------- */ /* Transform to latlong and report. */ /* -------------------------------------------------------------------- */ if(bJson) { double dfZ = 0.0; if( hTransform != NULL && !EQUAL( corner_name, "center" ) && OCTTransform(hTransform,1,&dfGeoX,&dfGeoY,&dfZ) ) { json_object * const poCorner = json_object_new_array(); json_object * const poX = json_object_new_double_with_precision( dfGeoX, 7 ); json_object * const poY = json_object_new_double_with_precision( dfGeoY, 7 ); json_object_array_add( poCorner, poX ); json_object_array_add( poCorner, poY ); json_object_array_add( poLongLatExtentCoordinates , poCorner ); } } else { double dfZ = 0.0; if( hTransform != NULL && OCTTransform(hTransform,1,&dfGeoX,&dfGeoY,&dfZ) ) { Concat(osStr, psOptions->bStdoutOutput, "(%s,", GDALDecToDMS( dfGeoX, "Long", 2 ) ); Concat(osStr, psOptions->bStdoutOutput, "%s)", GDALDecToDMS( dfGeoY, "Lat", 2 ) ); } Concat(osStr, psOptions->bStdoutOutput, "\n" ); } return TRUE; } /************************************************************************/ /* GDALInfoPrintMetadata() */ /************************************************************************/ static void GDALInfoPrintMetadata( const GDALInfoOptions* psOptions, GDALMajorObjectH hObject, const char *pszDomain, const char *pszDisplayedname, const char *pszIndent, int bJsonOutput, json_object *poMetadata, CPLString& osStr ) { const bool bIsxml = pszDomain != NULL && STARTS_WITH_CI(pszDomain, "xml:"); const bool bMDIsJson = pszDomain != NULL && STARTS_WITH_CI(pszDomain, "json:"); char **papszMetadata = GDALGetMetadata( hObject, pszDomain ); if( papszMetadata != NULL && *papszMetadata != NULL ) { json_object *poDomain = (bJsonOutput && !bIsxml && !bMDIsJson) ? json_object_new_object() : NULL; if( !bJsonOutput ) Concat( osStr, psOptions->bStdoutOutput, "%s%s:\n", pszIndent, pszDisplayedname ); json_object *poValue = NULL; for( int i = 0; papszMetadata[i] != NULL; i++ ) { if( bJsonOutput ) { if( bIsxml ) { poValue = json_object_new_string( papszMetadata[i] ); break; } else if( bMDIsJson ) { OGRJSonParse(papszMetadata[i], &poValue, true); break; } else { char *pszKey = NULL; const char *pszValue = CPLParseNameValue( papszMetadata[i], &pszKey ); if( pszKey ) { poValue = json_object_new_string( pszValue ); json_object_object_add( poDomain, pszKey, poValue ); CPLFree( pszKey ); } } } else { if (bIsxml || bMDIsJson) Concat(osStr, psOptions->bStdoutOutput, "%s%s\n", pszIndent, papszMetadata[i] ); else Concat(osStr, psOptions->bStdoutOutput, "%s %s\n", pszIndent, papszMetadata[i] ); } } if(bJsonOutput) { if(bIsxml || bMDIsJson) { json_object_object_add( poMetadata, pszDomain, poValue ); } else { if(pszDomain == NULL) json_object_object_add( poMetadata, "", poDomain ); else json_object_object_add( poMetadata, pszDomain, poDomain ); } } } } /************************************************************************/ /* GDALInfoReportMetadata() */ /************************************************************************/ static void GDALInfoReportMetadata( const GDALInfoOptions* psOptions, GDALMajorObjectH hObject, bool bIsBand, bool bJson, json_object *poMetadata, CPLString& osStr ) { const char* const pszIndent = bIsBand ? " " : ""; /* -------------------------------------------------------------------- */ /* Report list of Metadata domains */ /* -------------------------------------------------------------------- */ if( psOptions->bListMDD ) { char** papszMDDList = GDALGetMetadataDomainList( hObject ); char** papszIter = papszMDDList; json_object *poMDD = NULL; json_object * const poListMDD = bJson ? json_object_new_array() : NULL; if( papszMDDList != NULL ) { if( !bJson ) Concat(osStr, psOptions->bStdoutOutput, "%sMetadata domains:\n", pszIndent ); } while( papszIter != NULL && *papszIter != NULL ) { if( EQUAL(*papszIter, "") ) { if( bJson ) poMDD = json_object_new_string( *papszIter ); else Concat(osStr, psOptions->bStdoutOutput, "%s (default)\n", pszIndent); } else { if( bJson ) poMDD = json_object_new_string( *papszIter ); else Concat(osStr, psOptions->bStdoutOutput, "%s %s\n", pszIndent, *papszIter ); } if( bJson ) json_object_array_add( poListMDD, poMDD ); papszIter ++; } if( bJson ) json_object_object_add( poMetadata, "metadataDomains", poListMDD ); CSLDestroy(papszMDDList); } if (!psOptions->bShowMetadata) return; /* -------------------------------------------------------------------- */ /* Report default Metadata domain. */ /* -------------------------------------------------------------------- */ GDALInfoPrintMetadata( psOptions, hObject, NULL, "Metadata", pszIndent, bJson, poMetadata, osStr ); /* -------------------------------------------------------------------- */ /* Report extra Metadata domains */ /* -------------------------------------------------------------------- */ if( psOptions->papszExtraMDDomains != NULL ) { char **papszExtraMDDomainsExpanded = NULL; if( EQUAL(psOptions->papszExtraMDDomains[0], "all") && psOptions->papszExtraMDDomains[1] == NULL ) { char ** papszMDDList = GDALGetMetadataDomainList( hObject ); char * const * papszIter = papszMDDList; while( papszIter != NULL && *papszIter != NULL ) { if( !EQUAL(*papszIter, "") && !EQUAL(*papszIter, "IMAGE_STRUCTURE") && !EQUAL(*papszIter, "SUBDATASETS") && !EQUAL(*papszIter, "GEOLOCATION") && !EQUAL(*papszIter, "RPC") ) { papszExtraMDDomainsExpanded = CSLAddString(papszExtraMDDomainsExpanded, *papszIter); } papszIter ++; } CSLDestroy(papszMDDList); } else { papszExtraMDDomainsExpanded = CSLDuplicate(psOptions->papszExtraMDDomains); } for( int iMDD = 0; papszExtraMDDomainsExpanded != NULL && papszExtraMDDomainsExpanded[iMDD] != NULL; iMDD++ ) { if(bJson) { GDALInfoPrintMetadata( psOptions, hObject, papszExtraMDDomainsExpanded[iMDD], papszExtraMDDomainsExpanded[iMDD], pszIndent, bJson, poMetadata, osStr ); } else { CPLString osDisplayedname = "Metadata (" + CPLString(papszExtraMDDomainsExpanded[iMDD]) + ")"; GDALInfoPrintMetadata( psOptions, hObject, papszExtraMDDomainsExpanded[iMDD], osDisplayedname.c_str(), pszIndent, bJson, poMetadata, osStr ); } } CSLDestroy(papszExtraMDDomainsExpanded); } /* -------------------------------------------------------------------- */ /* Report various named metadata domains. */ /* -------------------------------------------------------------------- */ GDALInfoPrintMetadata( psOptions, hObject, "IMAGE_STRUCTURE", "Image Structure Metadata", pszIndent, bJson, poMetadata, osStr ); if (!bIsBand) { GDALInfoPrintMetadata( psOptions, hObject, "SUBDATASETS", "Subdatasets", pszIndent, bJson, poMetadata, osStr ); GDALInfoPrintMetadata( psOptions, hObject, "GEOLOCATION", "Geolocation", pszIndent, bJson, poMetadata, osStr ); GDALInfoPrintMetadata( psOptions, hObject, "RPC", "RPC Metadata", pszIndent, bJson, poMetadata, osStr ); } } /************************************************************************/ /* GDALInfoOptionsNew() */ /************************************************************************/ GDALInfoOptions *GDALInfoOptionsNew( char** papszArgv, GDALInfoOptionsForBinary* psOptionsForBinary ) { bool bGotFilename = false; GDALInfoOptions *psOptions = static_cast<GDALInfoOptions *>( CPLCalloc( 1, sizeof(GDALInfoOptions) ) ); psOptions->eFormat = GDALINFO_FORMAT_TEXT; psOptions->bComputeMinMax = FALSE; psOptions->bReportHistograms = FALSE; psOptions->bReportProj4 = FALSE; psOptions->bStats = FALSE; psOptions->bApproxStats = TRUE; psOptions->bSample = FALSE; psOptions->bComputeChecksum = FALSE; psOptions->bShowGCPs = TRUE; psOptions->bShowMetadata = TRUE; psOptions->bShowRAT = TRUE; psOptions->bShowColorTable = TRUE; psOptions->bListMDD = FALSE; psOptions->bShowFileList = TRUE; /* -------------------------------------------------------------------- */ /* Parse arguments. */ /* -------------------------------------------------------------------- */ for( int i = 0; papszArgv != NULL && papszArgv[i] != NULL; i++ ) { if( EQUAL(papszArgv[i],"-json") ) psOptions->eFormat = GDALINFO_FORMAT_JSON; else if( EQUAL(papszArgv[i], "-mm") ) psOptions->bComputeMinMax = TRUE; else if( EQUAL(papszArgv[i], "-hist") ) psOptions->bReportHistograms = TRUE; else if( EQUAL(papszArgv[i], "-proj4") ) psOptions->bReportProj4 = TRUE; else if( EQUAL(papszArgv[i], "-stats") ) { psOptions->bStats = TRUE; psOptions->bApproxStats = FALSE; } else if( EQUAL(papszArgv[i], "-approx_stats") ) { psOptions->bStats = TRUE; psOptions->bApproxStats = TRUE; } else if( EQUAL(papszArgv[i], "-sample") ) psOptions->bSample = TRUE; else if( EQUAL(papszArgv[i], "-checksum") ) psOptions->bComputeChecksum = TRUE; else if( EQUAL(papszArgv[i], "-nogcp") ) psOptions->bShowGCPs = FALSE; else if( EQUAL(papszArgv[i], "-nomd") ) psOptions->bShowMetadata = FALSE; else if( EQUAL(papszArgv[i], "-norat") ) psOptions->bShowRAT = FALSE; else if( EQUAL(papszArgv[i], "-noct") ) psOptions->bShowColorTable = FALSE; else if( EQUAL(papszArgv[i], "-listmdd") ) psOptions->bListMDD = TRUE; /* Not documented: used by gdalinfo_bin.cpp only */ else if( EQUAL(papszArgv[i], "-stdout") ) psOptions->bStdoutOutput = true; else if( EQUAL(papszArgv[i], "-mdd") && papszArgv[i+1] != NULL ) { psOptions->papszExtraMDDomains = CSLAddString( psOptions->papszExtraMDDomains, papszArgv[++i] ); } else if( EQUAL(papszArgv[i], "-oo") && papszArgv[i+1] != NULL ) { i++; if( psOptionsForBinary ) { psOptionsForBinary->papszOpenOptions = CSLAddString( psOptionsForBinary->papszOpenOptions, papszArgv[i] ); } } else if( EQUAL(papszArgv[i], "-nofl") ) psOptions->bShowFileList = FALSE; else if( EQUAL(papszArgv[i], "-sd") && papszArgv[i+1] != NULL ) { i++; if( psOptionsForBinary ) { psOptionsForBinary->nSubdataset = atoi(papszArgv[i]); } } else if( papszArgv[i][0] == '-' ) { CPLError(CE_Failure, CPLE_NotSupported, "Unknown option name '%s'", papszArgv[i]); GDALInfoOptionsFree(psOptions); return NULL; } else if( !bGotFilename ) { bGotFilename = true; if( psOptionsForBinary ) psOptionsForBinary->pszFilename = CPLStrdup(papszArgv[i]); } else { CPLError(CE_Failure, CPLE_NotSupported, "Too many command options '%s'", papszArgv[i]); GDALInfoOptionsFree(psOptions); return NULL; } } return psOptions; } /************************************************************************/ /* GDALInfoOptionsFree() */ /************************************************************************/ void GDALInfoOptionsFree( GDALInfoOptions *psOptions ) { if( psOptions != NULL ) { CSLDestroy( psOptions->papszExtraMDDomains ); CPLFree(psOptions); } }
1.7.6.1.