gdal을 이용하여 java에서 tif파일 변환 및 좌표계 추출 코드 예제
(나는 웹사이트도 함께 개발하여 파일 업로드 기능과 함께 구현하였음)
IDE : Visual Studio Code
언어 : Java, JavaScript
gdal 관련 사이트 링크 포함
🔗 https://velog.io/@soyul2823/gdal
Maven Repository : 🔗 https://mvnrepository.com/
<!-- https://mvnrepository.com/artifact/org.gdal/gdal -->
<dependency>
<groupId>org.gdal</groupId>
<artifactId>gdal</artifactId>
<version>3.6.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.osgeo/proj4j -->
<dependency>
<groupId>org.osgeo</groupId>
<artifactId>proj4j</artifactId>
<version>0.1.0</version>
</dependency>
public static void gdalService(String filepath){
gdal.AllRegister();
Dataset dataset = gdal.Open(filepath);
String wkt = dataset.GetProjection();
SpatialReference src = new SpatialReference(wkt);
SpatialReference targetSRS = new SpatialReference();
targetSRS.ImportFromEPSG(3857); //변환할 좌표계 설정
CoordinateTransformation ctf = CoordinateTransformation.CreateCoordinateTransformation(src, targetSRS);
double[] geoTransform = dataset.GetGeoTransform();
int rasterXSize = dataset.getRasterXSize();
int rasterYSize = dataset.getRasterYSize();
double minX = geoTransform[0];
double maxX = minX + (rasterXSize * geoTransform[1]) + (rasterYSize * geoTransform[2]);
double maxY = geoTransform[3];
double minY = maxY + (rasterXSize * geoTransform[4]) + (rasterYSize * geoTransform[5]);
double[] minCoords = ctf.TransformPoint(minX, minY);
double[] maxCoords = ctf.TransformPoint(maxX, maxY);
ArrayList<Double> extent = new ArrayList<>();
extent.add(minCoords[0]);
extent.add(minCoords[1]);
extent.add(maxCoords[0]);
extent.add(maxCoords[1]);
System.out.println("extent : " + extent);
}
public String gdaltranslateService(String originTifFilePath){
String gdalTranslatePngFilePath = fileDir + "revision/gdal_translate/" + revisionFileName;
try {
gdal.AllRegister();
Dataset dataset = gdal.Open(originTifFilePath);
int width = dataset.getRasterXSize();
int height = dataset.getRasterYSize();
System.out.print("Width: " + width);
System.out.println(", Height: " + height);
Vector<String> optionsVector = new Vector<>();
optionsVector.add("-of");
optionsVector.add("PNG");
if(width > 10000 || height > 10000){
optionsVector.add("-outsize");
optionsVector.add("10%");
optionsVector.add("10%");
}
TranslateOptions options = new TranslateOptions(optionsVector);
gdal.Translate(gdalTranslatePngFilePath, dataset, options, null);
System.out.println("파일 변환 성공");
dataset.delete();
return gdalTranslatePngFilePath;
} catch (Exception e) {
System.err.println("파일 변환 실패 : " + e.getMessage());
return null;
}
}
public String gdaldemService(String gdalTranslatePngFilePath, MultipartFile txtFile){
try {
gdal.AllRegister();
Dataset dataset = gdal.Open(gdalTranslatePngFilePath);
String txtFilePath;
if(txtFile == null){
txtFilePath = fileDir + "colorscale_seaice_rainbow.txt"; //첨부된 txt파일이 없는 경우 기본으로 적용되는 스타일 파일
}else{
txtFilePath = fileDir + "origin/style/" + txtFile.getOriginalFilename();
//텍스트 파일 스토리지에 저장
File originTxtFile = new File(txtFilePath);
FileUtils.copyInputStreamToFile(txtFile.getInputStream(), originTxtFile);
}
String colorPngFilePath = fileDir + "revision/color_relief/" + revisionFileName;
gdal.DEMProcessing(colorPngFilePath, dataset, "color-relief", txtFilePath, null); //스타일 적용
return "color_relief/" + revisionFileName;
} catch (Exception e) {
System.err.println("스타일 적용 오류 : " + e.getMessage());
return null;
}
}
public HashMap<String, Object> gdalwarpService(String gdalTranslatePngFilePath){
HashMap<String, Object> map = new HashMap<String,Object>();
try {
gdal.AllRegister();
//원본파일의 좌표계
Dataset dataset = gdal.Open(gdalTranslatePngFilePath);
String wkt = dataset.GetProjection();
SpatialReference src = new SpatialReference(wkt);
String srcProj4 = src.ExportToProj4();
String gdalWarpPngFilePath = fileDir + "revision/gdalwarp/" + revisionFileName;
Vector<String> options = new Vector<String>(Arrays.asList(
"-s_srs", srcProj4,
"-t_srs", "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"
, "-dstalpha"
));
Dataset warpDS = gdal.Warp(gdalWarpPngFilePath, new Dataset[] {gdal.Open(gdalTranslatePngFilePath, gdalconstConstants.GA_ReadOnly)}, new WarpOptions(options));
System.out.println("좌표계 변환 완료");
//좌표
double[] geoTransform = warpDS.GetGeoTransform();
int rasterXSize = warpDS.getRasterXSize();
int rasterYSize = warpDS.getRasterYSize();
double minX = geoTransform[0];
double maxX = minX + (rasterXSize * geoTransform[1]) + (rasterYSize * geoTransform[2]);
double maxY = geoTransform[3];
double minY = maxY + (rasterXSize * geoTransform[4]) + (rasterYSize * geoTransform[5]);
ArrayList<Double> extent = new ArrayList<>();
extent.add(minX);
extent.add(minY);
extent.add(maxX);
extent.add(maxY);
System.out.println("좌표 : " + extent);
warpDS.delete();
dataset.delete();
map.put("gdalWarpPngFile", "gdalwarp/" + revisionFileName);
map.put("gdalWarpPngFilePath", gdalWarpPngFilePath);
map.put("extent", extent);
return map;
} catch (Exception e) {
System.out.println("gdalwarp 실패 : " + e.getMessage());
return null;
}
}
옵션에서 변환할 좌표계를 설정함
주요 EPSG 코드 및 proj4 좌표계
- ESPG:4326 : +proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs
- EPSG:5179 (네이버 지도) : +proj=tmerc +lat_0=38 +lon_0=127.5 +k=0.9996 +x_0=1000000 +y_0=2000000 +ellps=GRS80 +units=m +no_defs
- ESPG:5181 (카카오맵) : +proj=tmerc +lat_0=38 +lon_0=127 +k=1 +x_0=200000 +y_0=500000 +ellps=GRS80 +units=m +no_defs
- EPSG:5186 : +proj=tmerc +lat_0=38 +lon_0=127 +k=1 +x_0=200000 +y_0=600000 +ellps=GRS80 +units=m +no_defs
- EPSG:3857, EPSG:900913 (구글맵) : +proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +no_defs
Vector<String> options = new Vector<String>(Arrays.asList(
"-s_srs", srcProj4, //원본 파일의 좌표계
"-t_srs", "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"
, "-dstalpha" //변환할 좌표계(proj4 코드로 입력)
));
이외의 다른 옵션들도 추가 가능한데 구글에선 검색이 잘 안 된다
🔗 https://gdal.org/programs/gdalwarp.html#cmdoption-gdalwarp-dstalpha
이 사이트를 통해서 도움 받으면 아마 될 수도 .... ㅜ
전에 이것저것 설정 추가하면서 적용했었는데 미리 정리를 안해놔서 까묵었다