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:
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. |