metadata-extractor
라이브러리를 사용하면 쉽게 이미지에서 메타데이터를 추출해올 수 있다.
해당 라이브러리를 사용하기 위해 gradle에 의존성을 추가한다.
dependencies {
implementation 'com.drewnoakes:metadata-extractor:2.16.0'
...
}
의존성을 추가한 후 ImageMetadataReader
를 사용하면 편하게 메타데이터를 가져올 수 있다.
String imageLocation = "이미지 파일 위치";
File image = new File(imageLocation);
Metadata metadata = ImageMetadataReader.readMetadata(image);
그 중 GpsDirectory
에는 이미지의 위도, 경도 정보가 존재한다.
(근데 이미지 파일을 열어보면 지도가 같이 떠서... Exif~ Directory에 주소 정보가 이미 있을 것 같긴한데, 좌표값을 input으로 다른 api를 사용해보기 위해 우선 좌표 정보를 뽑아 해보기로했다...)
public void printCoordinate() {
GpsDirectory gpsDirectory = metadata.getFirstDirectoryOfType(GpsDirectory.class);
if(hasGpsInformation(gpsDirectory)) {
double longitude = gpsDirectory.getGeoLocation().getLongitude();
double latitude = gpsDirectory.getGeoLocation().getLatitude();
System.out.println("위도 : " + latitude + ", 경도 : " + longitude);
}
}
private boolean hasGpsInformation(GpsDirectory gpsDirectory) {
return gpsDirectory.containsTag(GpsDirectory.TAG_LATITUDE) && gpsDirectory.containsTag(GpsDirectory.TAG_LONGITUDE);
}
// 출력 결과
// 위도 : 37.505522222222226, 경도 : 127.05077777777778
이제 좌표를 얻었으니 주소값을 가져와보자. Kakao가 제공하는 Api를 사용해보자
Api를 사용하기위해선 애플리케이션의 REST API키가 필요하다. kakao 애플리케이션 관리 페이지에서 내 애플리케이션을 추가한 후 생성한 애플리케이션의 REST API 키를 보관해둔다.
kakao local API를 보면 https://dapi.kakao.com/v2/local/geo/coord2address.${FORMAT}
url로 좌표 정보를 넘겨주면 주소 정보를 받아올 수 있다고 한다. 필요한 헤더와 쿼리 파라미터를 참조해 요청을 보내보자.
public String getAddressByCoordinate(double longitude, double latitude) throws Exception {
return parseAddressFromJsonData(getAddressJSONDataByCoordinate(longitude, latitude));
}
// 위치 정보를 jsonString으로 받아온다
private String getAddressJSONDataByCoordinate(double longitude, double latitude) throws Exception {
String jsonString = "";
String buf;
// 쿼리 파라미터 설정
String apiUrl = "https://dapi.kakao.com/v2/local/geo/coord2address?x="+longitude+"&y="+latitude;
URL url = new URL(apiUrl);
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
// 헤더 정보 설정
String apikey = "내 애플리케이션의 REST API 키";
String auth = "KakaoAK "+apikey;
connection.setRequestProperty("Authorization", auth);
BufferedReader br = new BufferedReader(new InputStreamReader(
connection.getInputStream(), "UTF-8"));
while ((buf = br.readLine()) != null) {
jsonString += buf;
}
return jsonString;
}
// JsonString에서 주소명을 파싱한다
private String parseAddressFromJsonData(String jsonData) {
JSONObject jsonObject = (JSONObject) JSONValue.parse(jsonData);
JSONArray documents = (JSONArray) jsonObject.get("documents");
JSONObject roadAddress = (JSONObject) ((JSONObject) documents.get(0)).get("road_address");
return (String) roadAddress.get("address_name");
}
요청을 보내면 위치 정보를 response로 받아올 수 있다.
나는 주소명을 알고 싶으므로, 받은 json data에서 document
-> road_address
에 있는 address_name
을 가져온다. (json-simple
라이브러리의 JSONObject
, JSONArray
를 사용했다.)
(더 효율적으로 json data에서 가져오는 방법이 있을 것 같지만 일단은 이렇게...ㅎㅎ 나중에 수정하겠습니다 진짜루)
public class Image {
private final File image;
private final Metadata metadata;
public ImageMetadata(String imageLocation) throws ImageProcessingException, IOException {
this.image = new File(imageLocation);
this.metadata = ImageMetadataReader.readMetadata(image);
}
public String getAddress() throws Exception {
GpsDirectory gpsDirectory = metadata.getFirstDirectoryOfType(GpsDirectory.class);
if(hasGpsInformation(gpsDirectory)) {
double longitude = gpsDirectory.getGeoLocation().getLongitude();
double latitude = gpsDirectory.getGeoLocation().getLatitude();
return getAddressByCoordinate(longitude, latitude);
}
return null;
}
private boolean hasGpsInformation(GpsDirectory gpsDirectory) {
return gpsDirectory.containsTag(GpsDirectory.TAG_LATITUDE) && gpsDirectory.containsTag(GpsDirectory.TAG_LONGITUDE);
}
private String getAddressByCoordinate(double longitude, double latitude) throws Exception {
return parseAddressFromJsonData(getAddressJSONDataByCoordinate(longitude, latitude));
}
// 위치 정보를 jsonString으로 받아온다
private String getAddressJSONDataByCoordinate(double longitude, double latitude) throws Exception {
String jsonString = "";
String buf;
// 쿼리 파라미터 설정
String apiUrl = "https://dapi.kakao.com/v2/local/geo/coord2address?x="+longitude+"&y="+latitude;
URL url = new URL(apiUrl);
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
// 헤더 정보 설정
String apikey = "내 애플리케이션의 REST API 키";
String auth = "KakaoAK "+apikey;
connection.setRequestProperty("Authorization", auth);
BufferedReader br = new BufferedReader(new InputStreamReader(
connection.getInputStream(), "UTF-8"));
while ((buf = br.readLine()) != null) {
jsonString += buf;
}
return jsonString;
}
// JsonString에서 주소명을 파싱한다
private String parseAddressFromJsonData(String jsonData) {
JSONObject jsonObject = (JSONObject) JSONValue.parse(jsonData);
JSONArray documents = (JSONArray) jsonObject.get("documents");
JSONObject roadAddress = (JSONObject) ((JSONObject) documents.get(0)).get("road_address");
return (String) roadAddress.get("address_name");
}
}