[GDAL] (2) 사용법 및 명령어 - JAVA

이로률·2023년 10월 31일
1

공간정보기술

목록 보기
2/5
post-thumbnail

gdal을 이용하여 java에서 tif파일 변환 및 좌표계 추출 코드 예제
(나는 웹사이트도 함께 개발하여 파일 업로드 기능과 함께 구현하였음)
IDE : Visual Studio Code
언어 : Java, JavaScript

cmd창에서 GDAL 사용 방법

gdal 관련 사이트 링크 포함
🔗 https://velog.io/@soyul2823/gdal


Spring Boot에서 JAVA GDAL 사용 방법

- 의존성 추가

  • GDAL
  • proj4

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>

JAVA GDAL 명령어 사용 예제 코드

1. tif파일 좌표계 추출

  • CoordinateTransformation.CreateCoordinateTransformation
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);
	}

2. tif파일을 png로 변환

  • tif파일을 경량화하여 오픈레이어스에 업로드하기 위해 png파일로 변환하는 작업
  • 이미지가 최대한 깨지지 않고 경량화되는 최적의 방법을 찾아서 옵션에 적용하였다
    (옵션이 많아서 하나하나 다 적용하고 비교해서 찾았음..ㅜ
    참고 링크 🔗 https://gdal.org/drivers/raster/gtiff.html )
  • gdal.Translate
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;
        }
        
    }

3. tif 파일에 txt파일 형식의 스타일 적용

  • 웹페이지에서 tif파일과 txt파일을 첨부하여 실행되는 코드 예제
  • gdal.DEMProcessing
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;
        }
    }

4. 좌표계 변환 후 변환된 좌표계의 좌표 추출

  • gdal.Warp
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 코드로 입력)
));
  • "-s_srs" : 원본 파일의 좌표계를 설정하는 옵션
  • srcProj4 : 원본 파일에서 추출하여 정의한 좌표계 변수명
  • "-t_srs" : 변환할 좌표계를 설정하는 옵션
  • "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs" : 변환할 좌표계를 나타내는 문자열 작성. 예제에서는 EPSG:4326 의 좌표계로 설정
  • "-dstalpha" : 데이터 없음(설정되지 않음/투명) 픽셀을 식별하기 위해 출력 알파 밴드 옵션 설정

이외의 다른 옵션들도 추가 가능한데 구글에선 검색이 잘 안 된다
🔗 https://gdal.org/programs/gdalwarp.html#cmdoption-gdalwarp-dstalpha
이 사이트를 통해서 도움 받으면 아마 될 수도 .... ㅜ
전에 이것저것 설정 추가하면서 적용했었는데 미리 정리를 안해놔서 까묵었다

profile
💻🧐💗💝💘💖

0개의 댓글