핸드폰으로 사진을 세로로 찍어서 업로드 하면
웹화면에서 해당 이미지를 출력하면 가로로 누워서 보이는 현상이 있다.
이는 웹 브라우저가 이미지의 orientation 정보대로 보여주지 못하기 때문이다.
모바일 앱으로 보면 세로 이미지가 정상으로 출력된다.
위 사진은 이미지 정보중 Exif의 Orientation 값을 나타낸다.
1. 정상
2. 좌우반전
3. 180도 회전
4. 180도 회전 + 좌우반전
5. 270도 회전 + 좌우반전
6. 270도 회전
7. 90도 회전 + 좌우반전
8. 90도 회전
이를 해결하는 방법은
화면단에서 자바스크립트를 이용한 방법도 있으나 해당 이미지 파일을 이용하여 여러 문서파일도 만드는 작업이 있어
모바일 앱에서 이미지 업로드 시 자바에서 orientaion 정보를 이용하여 1값으로 회전하여 저장하는 방식으로
문제를 해결했다.
다음은 자바 소스이다.
이미지 Exit 정보를 읽기 위해서는 라이브러리 metadata-extractor 이 필요하다.
pom.xml에 아래와 같이 디펜던시를 설정한다.
<!-- image EXIF read -->
<dependency>
<groupId>com.drewnoakes</groupId>
<artifactId>metadata-extractor</artifactId>
<version>2.9.1</version>
</dependency>
// 1. 원본 파일을 읽는다.
// 2. 원본 파일의 Orientation 정보를 읽는다.
// 3. 변경할 값들을 설정한다.
// 4. 회전하여 생성할 파일을 만든다.
// 5. 원본파일을 회전하여 파일을 저장한다.
// 1. 원본 파일을 읽는다.
File imageFile = new File("D:/o6.jpg");
// 2. 원본 파일의 Orientation 정보를 읽는다.
int orientation = 1; // 회전정보, 1. 0도, 3. 180도, 6. 270도, 8. 90도 회전한 정보
int width = 0; // 이미지의 가로폭
int height = 0; // 이미지의 세로높이
int tempWidth = 0; // 이미지 가로, 세로 교차를 위한 임의 변수
Metadata metadata; // 이미지 메타 데이터 객체
Directory directory; // 이미지의 Exif 데이터를 읽기 위한 객체
JpegDirectory jpegDirectory; // JPG 이미지 정보를 읽기 위한 객체
try {
metadata = ImageMetadataReader.readMetadata(imageFile);
directory = metadata.getFirstDirectoryOfType(ExifIFD0Directory.class);
jpegDirectory = metadata.getFirstDirectoryOfType(JpegDirectory.class);
if(directory != null){
orientation = directory.getInt(ExifIFD0Directory.TAG_ORIENTATION); // 회전정보
width = jpegDirectory.getImageWidth(); // 가로
height = jpegDirectory.getImageHeight(); // 세로
}
// 3. 변경할 값들을 설정한다.
AffineTransform atf = new AffineTransform();
switch (orientation) {
case 1:
break;
case 2: // Flip X
atf.scale(-1.0, 1.0);
atf.translate(-width, 0);
break;
case 3: // PI rotation
atf.translate(width, height);
atf.rotate(Math.PI);
break;
case 4: // Flip Y
atf.scale(1.0, -1.0);
atf.translate(0, -height);
break;
case 5: // - PI/2 and Flip X
atf.rotate(-Math.PI / 2);
atf.scale(-1.0, 1.0);
break;
case 6: // -PI/2 and -width
atf.translate(height, 0);
atf.rotate(Math.PI / 2);
break;
case 7: // PI/2 and Flip
atf.scale(-1.0, 1.0);
atf.translate(-height, 0);
atf.translate(0, width);
atf.rotate( 3 * Math.PI / 2);
break;
case 8: // PI / 2
atf.translate(0, width);
atf.rotate( 3 * Math.PI / 2);
break;
}
switch (orientation) {
case 5:
case 6:
case 7:
case 8:
tempWidth = width;
width = height;
height = tempWidth;
break;
}
BufferedImage image = ImageIO.read(imageFile);
final BufferedImage afterImage = new BufferedImage(width, height, image.getType());
final AffineTransformOp rotateOp = new AffineTransformOp(atf, AffineTransformOp.TYPE_BILINEAR);
final BufferedImage rotatedImage = rotateOp.filter(image, afterImage);
Iterator<ImageWriter> iter = ImageIO.getImageWritersByFormatName("jpg");
ImageWriter writer = iter.next();
ImageWriteParam iwp = writer.getDefaultWriteParam();
iwp.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
iwp.setCompressionQuality(1.0f);
// 4. 회전하여 생성할 파일을 만든다.
File outFile = new File("D:/o6_rotated.jpg");
FileImageOutputStream fios = new FileImageOutputStream(outFile);
// 5. 원본파일을 회전하여 파일을 저장한다.
writer.setOutput(fios);
writer.write(null, new IIOImage(rotatedImage ,null,null),iwp);
fios.close();
writer.dispose();
} catch (ImageProcessingException e) {
e.printStackTrace();
} catch (MetadataException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
참고로
css 를 이용하는 방법도 있으나
image-orientation: from-image;
이는 아직 파이어폭스에서만 지원하는 방식이다.
'Java' 카테고리의 다른 글
json 형식의 string을 자바 객체(DTO)로 맵핑하기.. (0) | 2021.05.25 |
---|---|
ibatis 정규식 에러 (1) | 2021.02.15 |
자바 엑셀파일 읽기 - java read excel, xlsx, xls (0) | 2019.08.14 |
jstl <c:url value=""> 사용시 ;jsessionid= 붙는 현상 (0) | 2018.03.06 |
자바 파일다운로드 & 한글,특수문자 깨짐 방지 (1) | 2018.02.26 |