티스토리 뷰

이 페이지에서는 사진의 메타정보를 통해 각도를 얻어 회전시켜주는 방법에 대해 설명하고 있다.

모바일에서 사진을 찍어 업로드할 때, 아이폰 ios는 자동 회전을 지원하고 android는 사진이 돌아간 상태로 저장되는 이슈가 생겼다. 이를 해결하기 위한 방법으로  이미지의 메타정보를 통해 사진의 각도를 확인하고 그 각도에 맞게 회전시키는 방식으로 진행하려 한다.

해당 프로젝트에서 클라이언트가 보내주는 이미지 타입은 MultipartFile이기 때문에 편의를 위해 File로 변환한 후 진행한다.

 

참고) 타입 변환 및 userAgent 정보 가져오기

1. Converting MultipartFile to File

 

[JAVA] Converting MultipartFile to File

이 페이지에서는 멀티파트파일을 파일객체로 변환하는 방식에 대해 설명하고 있다. # MultipartFile vs File 변환하는 코드 작성에 앞서 두 객체에 대해 간단하게 설명하려한다. 1) MultipartFile 멀티파트파일이..

kkumalog.tistory.com

2. Get User Agent And IP Information

 

[JAVA] Get User Agent And IP Information

이 페이지에서는 IP, Agent, 브라우저, OS등의 접속자 정보를 가져오는 방법에 대해 설명하고 있다. # IP X-Forwarded-For (XFF) 헤더는 HTTP 프록시나 로드 밸런서를 통해 웹 서버에 접속하는 클라이언트의 원 IP..

kkumalog.tistory.com

 

# 코드 구현

이슈가 발생한 안드로이드일 때에만 회전 로직을 수행하게 한다.
(마지막에 ImageIO.write 이용해 BufferedImage를 File객체로 변환하여 반환하는 부분에서 gif는 오류가 발생할 수 있기 때문에 예외처리를 해주었다)

이 로직을 완료한 후 리턴된 결과값 fileData를 원하는 곳에 활용하면된다.

File fileData = convert(file);
String origin = fileData.getName();
if (request.getHeader("User-Agent").contains("Android") && !origin.substring(origin.lastIndexOf(".") + 1).equals("gif")) {
	BufferedImage image = checkImage(fileData, getOrientation(fileData));
	ImageIO.write(image,"jpg", fileData);
}


orientation의 값으로 현재 이미지 회전 상태를 확인하고 각도에 맞는 회전을 적용시켜준다. (정방향인 1 일때에는 그대로 리턴)

아래 getOrientation함수에서 리턴하는 integer타입의 결과값을 파라미터로 받는다.

private BufferedImage checkImage(File file, int orientation) throws Exception {
	BufferedImage bi = ImageIO.read(file);
	if (orientation === 1) { // 정위치
    	return bi;
	} else if (orientation == 6) {
    	return rotateImage(bi, 90);
	} else if (orientation == 3) {
		return rotateImage(bi, 180);
	} else if (orientation == 8) {
		return rotateImage(bi, 270);
	} else{
		return bi;
	}
}


아래 함수는 checkImage의 파라미터인 orientation 값을 얻어오는 코드이다.

먼저 Metadata를 사용하기 위해서는 pom.xml에 metadata-extractor lib를 추가해야 한다.

변환시킨 File객체를 이용해 메타데이터를 추출하여 orientation을 반환한다.

<dependency>
	<groupId>com.drewnoakes</groupId>
	<artifactId>metadata-extractor</artifactId>
	<version>2.12.0</version>
</dependency>
private int getOrientation(File file) throws Exception {
	int orientation = 1;
	Metadata metadata = ImageMetadataReader.readMetadata(file);
	Directory directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
	if (directory != null) {
		orientation = directory.getInt(ExifIFD0Directory.TAG_ORIENTATION);
	}
	return orientation;
}


아래 함수는 checkImage에서 조건에 맞게 회전 시켜주기 위해 호출하는 코드이다.

File객체를 BufferedImage로 변환시켜준 후, radians와 함께 파라미터로 받아서 사용한다.

private BufferedImage rotateImage (BufferedImage bimage, int radians) {
	BufferedImage newImage;
	if(radians == 90 || radians == 270) {
		newImage = new BufferedImage(bimage.getHeight(),bimage.getWidth(),bimage.getType());
	} else if (radians==180){
		newImage = new BufferedImage(bimage.getWidth(),bimage.getHeight(),bimage.getType());
 	} else{
		return orgImage;
	}
	Graphics2D graphics = (Graphics2D) newImage.getGraphics();
	graphics.rotate(Math.toRadians(radians), newImage.getWidth() / 2, newImage.getHeight() / 2);
	graphics.translate((newImage.getWidth() - bimage.getWidth()) / 2, (newImage.getHeight() - bimage.getHeight()) / 2);
	graphics.drawImage(bimage, 0, 0, bimage.getWidth(), bimage.getHeight(), null);

	return newImage;
}

 

댓글
최근에 올라온 글
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Total
Today
Yesterday