CREATE FOOTPRINT OF RASTERS IN GEOJSON FORMAT

Most of the spatial queries like filtering all images covering a given point are inevitably solved if footprints of all images are created. The below code can create footprint of all raster files having any GDAL supported format inside a folder. The footprint in GeoJSON format is saved in the same folder. Just ensure a few things as mentioned below:

  • The folder having the raster files has the read-write permission.
  • The rasters having geo-information in GCPs are ignored.

In this blog, I will share java codes for creating footprints of rasters files in a folder in GeoJSON format using GDAL. Set the GDAL environment variables and java gdal settings as explained earlier.

We already know that any raster footprint can have only four corner coordinates. So we need to retrieve these coordinates from raster files. We will also save some extra information like projection, datum, number of bands, number of pyramid layers etc.

We will create a java project name RasterFootprint with java package name as rasterfootprint. We need to add gdal.jar and json-simple-1.1.1.jar in project class path. We will first create a Coordinate.java class with latitude, longitude and height as class variables. The code is as follows:

package rasterfootprint;

public class Coordinate {
	
    private double lat;
    private double lon;
    private double height = 0;
	//default constructor
    public Coordinate(){
        
    }
	//All setters and getters
    public Coordinate(double height){
        this.height = height;
    }
    public Coordinate(int height){
        this.height = height;
    }
    public Coordinate(double lat, double lon){
        this.lat = lat;
        this.lon = lon;
    }
    public Coordinate(double lat, double lon, double height){
        this.lat = lat;
        this.lon = lon;
        this.height = height;
    }
    public double getLat() {
        return lat;
    }

    public void setLat(double lat) {
        this.lat = lat;
    }

    public double getLon() {
        return lon;
    }

    public void setLon(double lon) {
        this.lon = lon;
    }

    public double getHeight() {
        return height;
    }

    public void setHeight(double height) {
        this.height = height;
    }
	//Apply significant figures in all variables like 4 place decimals only
    public static Coordinate setSigFeagures(Coordinate x, int sf){
        Coordinate y;
        if(sf<=0){
            y = new Coordinate((double)((int)(x.getLat())), (double)((int)(x.getLon())), (double)((int)(x.getHeight())));
        }else{
            double z = Math.pow(10, sf);
            y = new Coordinate(((int)(x.getLat()*z))/(z), ((int)(x.getLon()*z))/(z), ((int)(x.getHeight()*z))/(z));
        }
        return y;
    }
}

Now we will create raster information class to store all raster properties like file name, file location, corner coordinates, projection, datum, number of bands, EPSG, file dimensions, projection in proj4 format, coverage and pyramid layers. Following is the code for it. Let us call it Geoinfo.java


package rasterfootprint;

public class Geoinfo {
    //raster file name
    private String name;
    //raster file location
    private String location;
    //raster corner coordinates for polygon
    private Coordinate[] coord = new Coordinate[5];
    //raster projection
    private String proj= null;
	//raster datum
    private String dat = null;
	//number of bands in raster
    private int band = 0;
	//raster EPSG number
    private int epsg = 0;
	//raster number of pixels along X axis
    private int Xpixel = 0;
	//raster number of pixels along X axis
    private int Ypixel = 0;
	//raster project in proj4
    private String proj4 = "";
	//raster coverage as Xmin Ymin Xmax Ymax
    private String coverage = "";
	//number of pyramid layers in raster
    private int pyramid = 0;

	//All setters and getters
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getLocation() {
        return location;
    }

    public void setLocation(String location) {
        this.location = location;
    }
    
    public int getPyramid() {
        return pyramid;
    }

    public void setPyramid(int pyramid) {
        this.pyramid = pyramid;
    }

    public String getCoverage() {
        return coverage;
    }

    public void setCoverage(String coverage) {
        this.coverage = coverage;
    }

    public String getProj4() {
        return proj4;
    }

    public void setProj4(String proj4) {
        this.proj4 = proj4;
    }

    public Coordinate[] getCoord() {
        return coord;
    }

    public void setCoord(Coordinate[] coord) {
        this.coord = coord;
    }

    public String getProj() {
        return proj;
    }

    public void setProj(String proj) {
        this.proj = proj;
    }

    public String getDat() {
        return dat;
    }

    public void setDat(String dat) {
        this.dat = dat;
    }

    public int getBand() {
        return band;
    }

    public void setBand(int band) {
        this.band = band;
    }

    public int getEpsg() {
        return epsg;
    }

    public void setEpsg(int epsg) {
        this.epsg = epsg;
    }

    public int getXpixel() {
        return Xpixel;
    }

    public void setXpixel(int Xpixel) {
        this.Xpixel = Xpixel;
    }

    public int getYpixel() {
        return Ypixel;
    }

    public void setYpixel(int Ypixel) {
        this.Ypixel = Ypixel;
    }    
}
            

Now the main file RasterFootprint.java.

package rasterfootprint;

import java.io.*;
import java.util.ArrayList;
import org.gdal.gdal.*;
import org.gdal.gdalconst.gdalconstConstants;
import org.gdal.osr.*;
import org.json.simple.*;

public class RasterFootprint {
	//list of all files are saved in this arraylist
	private static ArrayList<String> vecfiles = new ArrayList<>();
	//Main method which accepts folder/raster file  location as only argument
	public static void main(String[] args) {
		//Validate argument
        if(args.length>0){
            String loc = validateFolder(args[0]);
            ArrayList<String> allfiles = listFiles(loc);
			//Check if files are available
            if(allfiles.size()>0){
			//register gdal
            gdal.AllRegister();
			//This arraylist saves Geoinfo objects of all supported rasters
            ArrayList <Geoinfo> ginfo = new ArrayList<>();
			//loop over all files to extract and save the Geoinfo object in ginfo arraylist
            for (int i = 0; i<allfiles.size(); i++){
                try{
                ginfo.add(imagegis(allfiles.get(i)));
                }catch(Exception e){
                    System.out.println(e.toString());
                }
            }
			//print geojson in console for verification
            System.out.println(getGeoJSON(ginfo));
            //Create geojson file in the same folder
            createJSON(saveLocation(loc), getGeoJSON(ginfo));
        }else{
            System.out.println("No GDAL supported files available to create footprint. Try again!");
        }
        }else{
            System.out.println("No arguments received.\n Please write the folder location or file as first argument.\n Ensure file is not in UNC path.\n Try again!");
        }
    }
    
	//Method to list files recursively and save in class variable vecfiles
    private static ArrayList<String> listFiles(String path) {
        File[] fList = null;
        try{
            File directory = new File(path);
            fList = directory.listFiles();

            for (File file : fList) {
                if (file.isFile()) {
                        vecfiles.add(file.getAbsolutePath());
                } else if (file.isDirectory()) {
                    listFiles(file.getAbsolutePath());
                }
            }
        }catch (Exception e){
            System.err.println("Error in File Listing: "+e.toString());
        }    
        return vecfiles;
    }  
    //Method to create geojson for all supported rasters with all properties
    private static String getGeoJSON(ArrayList<Geoinfo> info){
        JSONObject featureCollection = new JSONObject();
        JSONArray featureList = new JSONArray();
        JSONObject crs = new JSONObject();
        JSONObject name = new JSONObject();
        int i = 0;
        for(int p = 0; p<info.size(); p++){
            Coordinate[] polygon =  info.get(p).getCoord();
            try {
                JSONObject poly = new JSONObject();
                JSONObject properties = new JSONObject();
                JSONArray coord = new JSONArray();
                JSONArray coordp = new JSONArray();
                JSONObject feature = new JSONObject();
                crs.put("type", "name");
                name.put("name", "urn:ogc:def:crs:OGC:1.3:CRS84");
                crs.put("properties", name);
                poly.put("type", "Polygon");

                // iterate through your list
                for(int x = 0; x<polygon.length; x++){
                   Coordinate c = Coordinate.setSigFeagures((polygon[x]),5);
                    // construct a JSONArray from a string; can also use an array or list
                    JSONArray coordy = new JSONArray();
                    coordy.add(c.getLon());
                    coordy.add(c.getLat());
                    coord.add(coordy);
                }
                coordp.add(coord);
                poly.put("coordinates", coordp);
                properties.put("id", ++i);
                properties.put("proj", info.get(p).getProj());
                properties.put("datum", info.get(p).getDat());
                properties.put("epsg", info.get(p).getEpsg());
                properties.put("Xpixel", info.get(p).getXpixel());
                properties.put("Ypixel", info.get(p).getYpixel());
                properties.put("proj4", info.get(p).getProj4());
                properties.put("coverage", info.get(p).getCoverage());
                properties.put("pyramid", info.get(p).getPyramid());
                feature.put("geometry", poly);
                feature.put("type", "Feature");
                feature.put("properties", properties);
                featureList.add(feature);
            }catch (Exception e) {
                System.err.println("Error in JSON creation: "+e.toString());
            }
        }
        featureCollection.put("features", featureList);
        featureCollection.put("crs", crs);
        featureCollection.put("type", "FeatureCollection");
        return featureCollection.toString();
    }
	//Method to retrieve all gis and non-gis info from raster and save as Geoinfo object
    private static Geoinfo imagegis(String img_loc){
        Geoinfo imgDetails = new Geoinfo();
        Dataset hDataset = gdal.Open(img_loc, gdalconstConstants.GA_ReadOnly);
        Coordinate[] coord = new Coordinate[5];
        imgDetails.setName(new File(img_loc).getName());
        imgDetails.setLocation(img_loc);
        coord[0]= GDALInfoReportCorner(hDataset, "Upper Left ", 0.0, 0.0);
        coord[1]= GDALInfoReportCorner(hDataset, "Lower Left ", 0.0, hDataset.getRasterYSize());
        coord[2]= GDALInfoReportCorner(hDataset, "Lower Right", hDataset.getRasterXSize(), hDataset.getRasterYSize());
        coord[3]= GDALInfoReportCorner(hDataset, "Upper Right", hDataset.getRasterXSize(), 0.0);
        coord[4]= GDALInfoReportCorner(hDataset, "Upper Left ", 0.0, 0.0);
        imgDetails.setCoord(coord);
        imgDetails.setPyramid(hDataset.GetRasterBand(1).GetOverviewCount());
        imgDetails.setBand( hDataset.getRasterCount());
        imgDetails.setXpixel(hDataset.getRasterXSize());
        imgDetails.setYpixel(hDataset.getRasterYSize());
        imgDetails.setCoverage(Math.min(coord[0].getLon(), coord[2].getLon())+" "+Math.min(coord[0].getLat(), coord[2].getLat()) +" "+Math.max(coord[0].getLon(), coord[2].getLon())+" "+Math.max(coord[0].getLat(), coord[2].getLat()));
        if (hDataset.GetProjectionRef() != null){
            SpatialReference hSRS;
            String pszProjection;
            pszProjection = hDataset.GetProjectionRef();
            hSRS = new SpatialReference(pszProjection);
            try{
            imgDetails.setEpsg(Integer.parseInt(hSRS.GetAttrValue("AUTHORITY", 1)));
            }catch(NumberFormatException e){
                imgDetails.setEpsg(0);
            }
            if (hSRS != null && pszProjection.length() != 0)
            {
                String proj4 = hSRS.ExportToProj4();
                imgDetails.setProj4(proj4);
                imgDetails.setProj(proj4.substring(proj4.indexOf("+proj=")+6, (proj4.substring(proj4.indexOf("+proj"))+6).indexOf(" ")));
                imgDetails.setDat((proj4.substring(proj4.indexOf("+datum=")+7)).substring(0, (proj4.substring(proj4.indexOf("+datum=")+7)).indexOf(" ")));
            }
            else{
                imgDetails.setProj("Unknown");
                imgDetails.setDat("Unknown");
            }
            hSRS.delete();
        }
        return imgDetails;
    }
	//Method to retrieve raster corner coordinates
    private static Coordinate GDALInfoReportCorner(Dataset hDataset, String corner_name, double x, double y){
        Coordinate coordinates = new Coordinate();
        double dfGeoX, dfGeoY;
        String pszProjection;
        double[] adfGeoTransform = new double[6];
        CoordinateTransformation hTransform = null;

        hDataset.GetGeoTransform(adfGeoTransform);
        {
            pszProjection = hDataset.GetProjectionRef();
            dfGeoX = adfGeoTransform[0] + adfGeoTransform[1] * x + adfGeoTransform[2] * y;
            dfGeoY = adfGeoTransform[3] + adfGeoTransform[4] * x + adfGeoTransform[5] * y;
        }

        if (pszProjection != null && pszProjection.length() > 0){
            SpatialReference hProj, hLatLong = null;

            hProj = new SpatialReference(pszProjection);
            if (hProj != null)
                hLatLong = hProj.CloneGeogCS();

            if (hLatLong != null)
            {
                hTransform = new CoordinateTransformation(hProj, hLatLong);
                hLatLong.delete();
            }

            if (hProj != null)
                hProj.delete();
        }

        if (hTransform != null)
        {
            double[] transPoint = new double[3];
            hTransform.TransformPoint(transPoint, dfGeoX, dfGeoY, 0);
            coordinates.setLon(transPoint[0]);
            coordinates.setLat(transPoint[1]);
        }

        if (hTransform != null)
            hTransform.delete();

        return coordinates;
    }
    //Method to delete extra \ from folder location which is passed as argument
    private static String validateFolder(String folderloc){
        if(folderloc.endsWith("\\") || folderloc.endsWith("/")){
            folderloc = folderloc.substring(0, folderloc.length());
        }
        return folderloc;
    }
    //Method to save GeoJSON file
    private static void createJSON(String location, String json){
        File file = new File(location+"\\footprint.geojson");
            FileWriter fr = null;
            BufferedWriter br = null;
            try{
                fr = new FileWriter(file);
                br = new BufferedWriter(fr);

                    br.write(json);

            } catch (IOException e) {
                e.printStackTrace();
            }finally{
                try {
                    br.close();
                    fr.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    }
    //Method to get folder path where the footprint.geojson to be saved
    private static String saveLocation(String loc){
        String location = "";
        File dir = new File(loc);
        if(dir.isFile()){
           location = dir.getParent();
        }else{
            location = dir.getAbsolutePath();
        }
        return location;
    }
}


You can create a batch script and past in sendTo folder of your PC so that folder/raster file can be passed as argument by right clicking over it and sendTo batch script. Footprint.geojson will still be saved in folder or file's location which was provided as argument.

QUICK LINKS
Coordinates

Earth Shape

Ellipsoid & Geoid

Datum

Projection

UTM

Rasters

Vectors
GDAL

GDAL Setup

GDAL Rasters

GDAL Vectors

GDAL Tools
WMS

MS4W

Spatial DB

Oracle Spatial

SDO_GEOMETRY

Geo-Crawler
Web Clients

Openlayers

OL3

Closest Distance Map

Openlayers v2.x

ThreeJS

Terrain Viewer

Bluemarble (250m tiff)

JS Tools

Geographiclib

JS2Shapefile

CSV2Shape


GeoSpatialEarth.in Copyright © All rights reserved.