package cn.piesat.pielib.common.utils;
import org.gdal.gdal.Band;
import org.gdal.gdal.ColorTable;
import org.gdal.gdal.Dataset;
import org.gdal.gdal.gdal;
import org.gdal.ogr.*;
import org.gdal.osr.SpatialReference;
import javax.imageio.ImageIO;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class GdalUtil {
// GBK的编码格式
private static final String CODE_GBK="0x4D";
// CGCS2000坐标系
private static String proWkt = "GEOGCS['GCS_China_Geodetic_Coordinate_System_2000',DATUM['China_2000',SPHEROID['CGCS2000',6378137.0,298.257222101]],PRIMEM['Greenwich',0.0],UNIT['Degree',0.0174532925199433]]";
private static Driver shpDriver;
private static Driver tiffDriver;
static {
ogr.RegisterAll();
gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES");
gdal.SetConfigOption("SHAPE_ENCODING", "");
shpDriver = ogr.GetDriverByName("ESRI Shapefile");
}
/**
* 获取DataSource
*/
public static DataSource getShpDataSource(String shpFilePath){
if(isShpFileGBK(shpFilePath)){
gdal.SetConfigOption("SHAPE_ENCODING", "CP936");
}else{
gdal.SetConfigOption("SHAPE_ENCODING", "");
}
shpDriver = ogr.GetDriverByName("ESRI Shapefile");
DataSource dataSource = shpDriver.Open(shpFilePath);
return dataSource;
}
/**
* 判断shp编码格式是否为GBK
*/
public static boolean isShpFileGBK(String shpFilePath){
InputStream in =null;
File dbfFile = null;
boolean isGBK = false;
try {
String dbfFilePath = shpFilePath.substring(0,shpFilePath.lastIndexOf("."));
dbfFile = new File(dbfFilePath+".dbf");
if(dbfFile.exists()){
in = new FileInputStream(dbfFile);
byte[] bytes = new byte[30];
in.read(bytes);
byte b = bytes[29];
if(CODE_GBK.equalsIgnoreCase("0x"+Integer.toHexString(Byte.toUnsignedInt(b)))){
isGBK = true;
}
}
in.close();
return false;
} catch (Exception e) {
e.printStackTrace();
}finally {
if (in!=null){
try {
in.close();
}catch (Exception ex){
ex.printStackTrace();
}
}
}
return isGBK;
}
/**
* 获取Shp文件的投影信息
*/
public static SpatialReference getShpSpatialReference(String shpFilePath){
DataSource ds = getShpDataSource(shpFilePath);
if(null != ds){
return ds.GetLayer(0).GetSpatialRef();
}
ds.delete();
ds = null;
return null;
}
/**
* 获取Shp的中心点
*/
public double[] getShpCenter(String shpFilePath){
double[] center = {0,0};
double[] envelope = getShpEnvelope(shpFilePath);
if(null != envelope && envelope.length ==4){
double xMin = envelope[0];
double yMin = envelope[1];
double xMax = envelope[2];
double yMax = envelope[3];
double xCenter = (xMin + xMax)/2;
double yCenter = (yMin + yMax)/2;
center[0] = xCenter;
center[1] = yCenter;
}
return center;
}
/**
* 获取Shp的最小外接矩形
*/
public double[] getShpEnvelope(String shpFilePath){
DataSource ds = getShpDataSource(shpFilePath);
if(ds == null){
return null;
}
Layer lyr = ds.GetLayer(0);
long size = lyr.GetFeatureCount();
System.out.println(size);
Feature feature = lyr.GetNextFeature();
double [] envelope = new double[]{1,2,3,4};
feature.GetGeometryRef().GetEnvelope(envelope);
feature.delete();
feature = null;
lyr.delete();
lyr = null;
ds.delete();
ds = null;
return envelope;
}
/**
* 获取Geometry的中心点
*/
public double[] getGeometryCenter(Geometry geometry){
double [] envelope = new double[]{1,2,3,4};
geometry.GetEnvelope(envelope);
double[] center = {0,0};
if(null != envelope && envelope.length ==4){
double xMin = envelope[0];
double yMin = envelope[1];
double xMax = envelope[2];
double yMax = envelope[3];
double xCenter = (xMin + xMax)/2;
double yCenter = (yMin + yMax)/2;
center[0] = xCenter;
center[1] = yCenter;
}
return center;
}
/**
* 获取Geometry的最小外接矩形
*/
public double[] getGeometryEnvelope(Geometry geometry){
double [] envelope = new double[]{1,2,3,4};
geometry.GetEnvelope(envelope);
return envelope;
}
/**
* GeoJSON转WKT
*/
public static String geoJson2WKT(String geoJson){
Geometry geometry = Geometry.CreateFromJson(geoJson);
String wkt = geometry.ExportToWkt();
geometry.delete();
geometry = null;
return wkt;
}
/**
* WKT转GeoJSON
*/
public static String wkt2GeoJson(String wkt){
Geometry geometry = Geometry.CreateFromJson(wkt);
String geoJson = geometry.ExportToJson();
geometry.delete();
geometry = null;
return geoJson;
}
/**
* Geometry投影转换
*/
public static void geometryTransform(Geometry geometry, int destEpsg){
SpatialReference destSr = new SpatialReference();
destSr.ImportFromEPSG(destEpsg);
if(null != geometry){
geometry.TransformTo(destSr);
}
destSr.delete();
destSr = null;
}
/**
* Geometry投影转换
*/
public static void geometryTransform(Geometry geometry,int oldEpsg, int destEpsg){
SpatialReference oldSr = new SpatialReference();
oldSr.ImportFromEPSG(oldEpsg);
SpatialReference destSr = new SpatialReference();
destSr.ImportFromEPSG(destEpsg);
if(null != geometry){
geometry.AssignSpatialReference(oldSr);
geometry.TransformTo(destSr);
}
oldSr.delete();
oldSr = null;
destSr.delete();
destSr = null;
}
/**
* Shp文件投影转换
*
* @param shpFilePath
* @param destShpFilePath
*/
public static void shpTransform(String shpFilePath, String destShpFilePath, int epsg) {
try {
if(isShpFileGBK(shpFilePath)){
gdal.SetConfigOption("SHAPE_ENCODING", "CP936");
}else{
gdal.SetConfigOption("SHAPE_ENCODING", "");
}
shpDriver = ogr.GetDriverByName("ESRI Shapefile");
DataSource resultDS = shpDriver.CreateDataSource(destShpFilePath,null);
DataSource oDS = getShpDataSource(shpFilePath);
SpatialReference dst = new SpatialReference();
dst.ImportFromEPSG(epsg);
Layer shpLayer = oDS.GetLayer(0);
String shpLayerName = shpLayer.GetName();
Layer resultLayer = resultDS.CreateLayer(shpLayerName, dst, shpLayer.GetGeomType());
FeatureDefn featureDefn = shpLayer.GetLayerDefn();
for (int fieldIndex = 0; fieldIndex < featureDefn.GetFieldCount(); fieldIndex++) {
FieldDefn fde = featureDefn.GetFieldDefn(fieldIndex);
if (fde.GetFieldType() == ogr.OFTReal) {
fde.SetPrecision(4);
}
resultLayer.CreateField(fde);
}
Feature feature = null;
while ((feature = shpLayer.GetNextFeature()) != null) {
Geometry geometry = feature.GetGeometryRef();
geometry.TransformTo(dst);
resultLayer.CreateFeature(feature.Clone());
geometry.delete();
feature.delete();
feature = null;
}
// 存储到硬盘
resultLayer.SyncToDisk();
featureDefn.delete();
dst.delete();
resultLayer.delete();
shpLayer.delete();
oDS.delete();
resultDS.delete();
featureDefn = null;
dst = null;
resultLayer = null;
shpLayer = null;
oDS = null;
resultDS = null;
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取proj.4
*/
public static String getSpatialReferenceProj4(SpatialReference sr){
return sr.ExportToProj4();
}
/**
* Tiff转Png
*/
public static void getPngFromTiff(String tiffFilePath, String pngFilePath){
Dataset tiffDataset = gdal.Open(tiffFilePath);
org.gdal.gdal.Driver pngDriver = gdal.GetDriverByName("PNG");
Dataset pngDataset = pngDriver.CreateCopy(pngFilePath, tiffDataset);
tiffDataset.delete();
tiffDataset = null;
pngDataset.delete();
pngDataset = null;
}
/**
* Tiff转png
*/
public static void getPngFromTiff(String tiffFilePath, String pngFilePath, int nWidth, int nHeight, boolean isSeries) throws IOException {
Dataset tiffDataset = gdal.Open(tiffFilePath);
int oWidth = tiffDataset.getRasterXSize();
int oHeight = tiffDataset.getRasterYSize();
if(!isSeries){
nHeight = nWidth*oHeight/oWidth;
}
int rasterCount = tiffDataset.GetRasterCount();
if(rasterCount == 1){
Band band = tiffDataset.GetRasterBand(1);
ColorTable colorTable = band.GetColorTable();
byte[] bytes = new byte[nWidth * nHeight];
band.ReadRaster(0, 0, oWidth, oHeight, nWidth, nHeight, band.getDataType(), bytes);
BufferedImage image = new BufferedImage(nWidth, nHeight, BufferedImage.TYPE_INT_RGB);
for(int i=0; i< nWidth; i++){
for(int j=0; j< nHeight; j++){
int entry = bytes[nWidth*j + i] & 0xff;
Color color = colorTable.GetColorEntry(entry);
image.setRGB(i, j, color.getRGB());
}
}
File imgFile = new File(pngFilePath);
ImageIO.write(image, "JPEG", imgFile);
}else if(rasterCount >= 3){
byte[] bytes = new byte[nWidth*nHeight*3];
tiffDataset.ReadRaster(0, 0, oWidth, oHeight, nWidth, nHeight, tiffDataset.GetRasterBand(1).getDataType(),
bytes, new int[]{1,2,3});
BufferedImage image = new BufferedImage(nWidth, nHeight, BufferedImage.TYPE_INT_RGB);
for(int i=0; i< nWidth; i++){
for(int j=0; j< nHeight; j++){
int r = bytes[nWidth*j + i] & 0xff;
int g = bytes[nWidth*nHeight + nWidth*j + i] & 0xff;
int b = bytes[nWidth*nHeight*2 + nWidth*j + i] & 0xff;
Color color = new Color(r, g, b);
image.setRGB(i, j, color.getRGB());
}
}
File imgFile = new File(pngFilePath);
ImageIO.write(image, "JPEG", imgFile);
}
tiffDataset.delete();
tiffDataset = null;
}
/**
* Tiff缩放
*/
public static void tiffScaleTranslate(String oldTiffFilePath, String newTiffFilePath, float scale){
Dataset oTiffDataset = gdal.Open(oldTiffFilePath);
int oWidth = oTiffDataset.GetRasterXSize();
int oHeight = oTiffDataset.GetRasterYSize();
int nWidth = Math.round(oWidth*scale);
int nHeight = Math.round(oHeight*scale);
int bandCount = oTiffDataset.getRasterCount();
Dataset nTiffDataset = gdal.GetDriverByName("GTiff").Create(newTiffFilePath, nWidth, nHeight, bandCount);
byte[] bytes = new byte[nWidth * nHeight*bandCount];
int[] bandArray = new int[bandCount];
for(int i=0; i<bandCount; i++){
bandArray[i] = i + 1;
}
oTiffDataset.ReadRaster(0, 0, oWidth, oHeight, nWidth, nHeight,
oTiffDataset.GetRasterBand(1).getDataType(), bytes, bandArray);
nTiffDataset.WriteRaster(0, 0, nWidth, nHeight, nWidth, nHeight,
oTiffDataset.GetRasterBand(1).getDataType(), bytes, bandArray);
nTiffDataset.delete();
nTiffDataset = null;
oTiffDataset.delete();
oTiffDataset = null;
}
}