io.jeo.gdal.GDALDataset Maven / Gradle / Ivy
The newest version!
/* Copyright 2014 The jeo project. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.jeo.gdal;
import io.jeo.geom.Bounds;
import io.jeo.raster.Band;
import io.jeo.raster.DataBuffer;
import io.jeo.raster.DataType;
import io.jeo.raster.Raster;
import io.jeo.raster.Stats;
import io.jeo.util.Dimension;
import io.jeo.util.Key;
import io.jeo.util.Rect;
import io.jeo.util.Util;
import org.gdal.gdal.Dataset;
import org.gdal.gdal.gdal;
import org.gdal.osr.SpatialReference;
import io.jeo.data.Driver;
import io.jeo.data.FileData;
import io.jeo.raster.RasterDataset;
import io.jeo.raster.RasterQuery;
import io.jeo.proj.Proj;
import org.osgeo.proj4j.CoordinateReferenceSystem;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import static org.gdal.gdalconst.gdalconstConstants.*;
public class GDALDataset implements RasterDataset, FileData {
Dataset dataset;
File file;
GDAL driver;
public GDALDataset(File file, Dataset dataset, GDAL driver) {
this.file = file;
this.dataset = dataset;
this.driver = driver;
}
@Override
public File file() {
return file;
}
@Override
public String name() {
return Util.base(file.getName());
}
public String description() {
return dataset.GetDescription();
}
@Override
public Driver> driver() {
return driver;
}
@Override
public Map, Object> driverOptions() {
LinkedHashMap, Object> opts = new LinkedHashMap, Object>();
opts.put(GDAL.FILE, file);
return opts;
}
@Override
public CoordinateReferenceSystem crs() throws IOException {
String proj = dataset.GetProjection();
if (proj != null) {
SpatialReference ref = new SpatialReference(proj);
return Proj.crs(ref.ExportToProj4());
}
return null;
}
@Override
public Bounds bounds() throws IOException {
return bounds(dataset);
}
Bounds bounds(Dataset dataset) {
Dimension size = size(dataset);
double[] tx = dataset.GetGeoTransform();
return new Bounds(tx[0], tx[0] + size.width() * tx[1],
tx[3], tx[3] + size.width()*tx[4] + size.height()*tx[5]);
}
@Override
public Dimension size() {
return size(dataset);
}
Dimension size(Dataset dataset) {
return new Dimension(dataset.getRasterXSize(), dataset.getRasterYSize());
}
public Rect rect() {
return rect(dataset);
}
Rect rect(Dataset dataset) {
Dimension size = size(dataset);
return new Rect(0, 0, size.width(), size.height());
}
@Override
public List bands() throws IOException {
int nbands = dataset.GetRasterCount();
List bands = new ArrayList(nbands);
for (int i = 1; i <= nbands; i++) {
bands.add(new GDALBand(dataset.GetRasterBand(i)));
}
return bands;
}
@Override
public Raster read(RasterQuery query) throws IOException {
Raster raster = new Raster();
Dataset data = dataset;
// reprojection
raster.crs(crs());
if (query.crs() != null && !Proj.equal(query.crs(), crs())) {
String srcWkt = toWKT(crs());
String dstWkt = toWKT(query.crs());
//TODO: allow query to specify interpolation method
data = gdal.AutoCreateWarpedVRT(dataset, srcWkt, dstWkt);
raster.crs(query.crs());
}
// area of raster to load
Rect r = rect(data); // raster space
Bounds bbox = bounds(data); // world space
if (query.bounds() != null) {
// intersect bounds with query bounds
Bounds i = bbox.intersection(query.bounds());
r = r.map(i, bbox);
bbox = i;
}
raster.bounds(bbox);
// raster size
Dimension s = query.size();
if (s == null) {
s = size(data);
}
raster.size(s);
// band selection
List queryBands = bands(query.bands());
int[] bands = new int[queryBands.size()];
for (int i = 0 ; i < queryBands.size(); i++) {
GDALBand band = queryBands.get(i);
bands[i] = band.index();
}
raster.bands((List)queryBands);
// figure out the buffer type if not specified
DataType datatype = query.datatype();
if (datatype == null) {
datatype = DataType.BYTE;
for (int i = 0 ; i < queryBands.size(); i++) {
GDALBand band = queryBands.get(i);
DataType dt = band.datatype();
if (dt.compareTo(datatype) > 0) {
datatype = dt;
}
}
}
ByteBuffer buffer = ByteBuffer.allocateDirect(s.width()*s.height()*datatype.size());
buffer.order(ByteOrder.nativeOrder());
if (bands.length == 1) {
// single band, read in same units as requested buffer
data.ReadRaster_Direct(r.left, r.top, r.width(), r.height(), s.width(), s.height(),
toGDAL(datatype), buffer, bands, 0, 0, 0);
}
else {
// multi band mode, read as byte and back into buffer
data.ReadRaster_Direct(r.left, r.top, r.width(), r.height(), s.width(), s.height(),
GDT_Byte, buffer, bands, datatype.size(), 0, 1);
}
return raster.data(DataBuffer.create(buffer, datatype));
}
int toGDAL(DataType datatype) {
switch(datatype) {
case CHAR:
break;
case BYTE:
return GDT_Byte;
case SHORT:
return GDT_Int16;
case INT:
return GDT_Int32;
case LONG:
return GDT_UInt32;
case FLOAT:
return GDT_Float32;
case DOUBLE:
return GDT_Float64;
}
throw new IllegalArgumentException("unsupported data type: " + datatype);
}
String toWKT(CoordinateReferenceSystem crs) {
SpatialReference ref = new SpatialReference();
ref.ImportFromProj4(Proj.toString(crs));
return ref.ExportToWkt();
}
List bands(int[] bands) throws IOException {
List allBands = bands();
if (bands == null || bands.length == 0) {
return (List) allBands;
}
List list = new ArrayList(bands.length);
for (int b : bands) {
list.add((GDALBand) allBands.get(b));
}
return list;
}
@Override
public void close() {
if (dataset != null) {
dataset.delete();
dataset = null;
}
}
static class GDALBand implements Band {
org.gdal.gdal.Band band;
GDALBand(org.gdal.gdal.Band band) {
this.band = band;
}
@Override
public String name() {
return band.GetDescription();
}
int index() {
return band.GetBand();
}
@Override
public Color color() {
int ci = band.GetColorInterpretation();
return ci == GCI_Undefined ? Color.UNDEFINED :
ci == GCI_GrayIndex ? Color.GRAY :
ci == GCI_RedBand ? Color.RED :
ci == GCI_GreenBand ? Color.GREEN :
ci == GCI_BlueBand ? Color.BLUE : Color.GRAY;
}
@Override
public DataType datatype() {
int dt = band.GetRasterDataType();
return dt == GDT_Byte ? DataType.BYTE :
dt == GDT_Int16 ? DataType.SHORT :
dt == GDT_UInt16 ? DataType.INT :
dt == GDT_Int32 ? DataType.INT :
dt == GDT_UInt32 ? DataType.LONG :
dt == GDT_Float32 ? DataType.FLOAT :
dt == GDT_Float64 ? DataType.DOUBLE :
null;
//TODO
//GDT_CInt16
//GDT_CInt32
//GDT_CFloat32
//GDT_CFloat64
}
@Override
public Double nodata() {
Double[] nodata = new Double[]{null};
band.GetNoDataValue(nodata);
return nodata[0];
}
@Override
public Stats stats() throws IOException {
Stats stats = new Stats();
double[] arr = new double[2];
band.ComputeRasterMinMax(arr);
stats.min(arr[0]).max(arr[1]);
band.ComputeBandStats(arr);
stats.mean(arr[0]).stdev(arr[1]);
return stats;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy