#include "gdal_priv.h" #include #include #include #define suicide() _suicide(__FILE__, __LINE__) #define DUMP(expr) std::cout << dump::indent() << expr << std::endl #define DUMP_PUSH(expr) do { std::cout << dump::indent() << expr; dump::push(); } while (false) #define DUMP_POP() dump::pop() namespace dump { static int level = 0; static std::string indentation; static const char *indent() { return indentation.c_str(); } static void increase(bool positive) { level += positive ? 1 : -1; indentation = ""; for (int i = 0; i < level; ++i) indentation += " "; } static void push() { std::cout << " {{{" << std::endl; increase(true); } static void pop() { increase(false); DUMP("}}}"); } } static void _suicide(const char *fname, int line) { std::cerr << "suicide at " << fname << ":" << line << std::endl; _exit(1); } // print all metadata in the given domain static void print_metadata(GDALDataset *poDataset, const char *domain) { char **metadata = poDataset->GetMetadata(domain); if (metadata) { DUMP_PUSH("Metadata " << domain); for (char **meta = metadata; *meta; ++meta) DUMP(*meta); DUMP_POP(); } } // recursively dump elements, attributes and child datasets static void doit(const char *filename) { GDALDataset *poDataset; poDataset = (GDALDataset *)GDALOpen(filename, GA_ReadOnly); if (!poDataset) suicide(); DUMP_PUSH(filename); // global description { DUMP("Driver " << poDataset->GetDriver()->GetDescription()); } // x, y int xsize = poDataset->GetRasterXSize(); int ysize = poDataset->GetRasterYSize(); DUMP("(X, Y) " << xsize << ", " << ysize); // projection { const char *proj = poDataset->GetProjectionRef(); if (proj) { DUMP("Projection " << proj); } const char *gcpproj = poDataset->GetGCPProjection(); if (gcpproj) { DUMP("GCPProjection " << proj); } int gcpcount = poDataset->GetGCPCount(); for (int i = 0; i < gcpcount; ++i) { const GDAL_GCP *gcp = poDataset->GetGCPs() + i; DUMP("GCP[" << i << "] " << gcp->pszId << ", " << gcp->pszInfo); } } { double geotransform[6]; if (poDataset->GetGeoTransform(geotransform) == CE_None) { DUMP("GeoTransform " << geotransform[0] << ", " << geotransform[1] << ", " << geotransform[2]); DUMP("GeoTransform " << geotransform[3] << ", " << geotransform[4] << ", " << geotransform[5]); } } // elements { int count = poDataset->GetRasterCount(); for (int i = 0; i < count; ++i) { GDALRasterBand *rb = poDataset->GetRasterBand(i + 1); int blockx, blocky; rb->GetBlockSize(&blockx, &blocky); GDALDataType dtype = rb->GetRasterDataType(); const char *desc = rb->GetDescription(); DUMP_PUSH("RasterBand[" << i << "] (" << blockx << ", " << blocky << ") " << GDALGetDataTypeName(dtype) << " : " << desc); int hasfill = false; double fill = rb->GetNoDataValue(&hasfill); if (hasfill) DUMP("Fill " << fill); float *buffer = new float[xsize * ysize]; rb->RasterIO(GF_Read, 0, 0, xsize, ysize, buffer, xsize, ysize, GDT_Float32, 0, 0); for (int j = 0; j < ysize; ++j) { for (int k = 0; k < xsize; ++k) { std::cout << buffer[j * xsize + k] << " "; } std::cout << std::endl; } delete [] buffer; DUMP_POP(); } } // metadata print_metadata(poDataset, ""); print_metadata(poDataset, "GEOLOCATION"); print_metadata(poDataset, "IMAGE_STRUCTURE"); print_metadata(poDataset, "SUBDATASETS"); // recursively dump all child objects { char **metadata = poDataset->GetMetadata("SUBDATASETS"); if (metadata) { // need to skip SUBDATASET_?_DESC; // we only need SUBDATASET_?_NAME here for (char **meta = metadata; *meta; meta += 2) { const char *name = strstr(*meta, "="); if (!name) suicide(); doit(name + 1); } } } GDALClose(poDataset); DUMP_POP(); } int main(int argc, char **argv) { if (argc != 2) return 1; GDALAllRegister(); doit(argv[1]); return 0; } // vim:ts=8:sw=2:sts=2