프로젝트 작업 중, 모바일 아이폰에서 이미지를 업로드하면 90도 회전되어서 업로드 되는 현상이 확인되었다.
휴대폰으로 찍은 사진의 경우 이미지의 가로, 세로가 변경되서 등록되는 경우가 종종 있다.
사진이 돌아가는 이유는 **EXIF(Exchangeable Image File Format)의 회전값(orientation)**이 반영되지 않기 때문이다. 휴대폰을 세워서 정상적인 0도 각도에서 사진을 찍으면 문제가 되지 않으나, 스마트폰을 가로 90도 각도로 기울여서 찍은 경우 사진이 90도로 틀어져서 저장된다.
휴대폰은 EXIF 메타정보의 orientation 정보를 읽을 수 있어서 정상적인 사진을 보여주시만, 크롬, 사파리, 파이어팍스 같은 브라우저는 orientation 정보를 읽지 못한다. 따라서 휴대폰에서 업로드한 사진들이 브라우저에서는 종종 회전되어 보인다.
1. Exif란?
Exif: 교환 이미지 파일 형식 (EXchangable Image File format)
Exif는 교환 이미지 파일 형식으로 디지털 카메라에서 이용되는 이미지 파일 포맷이다. 카메라가 촬영한 사진, 녹음파일에 시간 등의 각종 정보를 담기 위해 개발되었다고 한다. 이 데이터는 JPEG, TIFF 6.0과 RIFF, WAV 파일 포맷에서 이용되며 이미지나 소리에 대한 정보(메타 데이터)를 추가로 기록할 수 있다.
EXIF 데이터는 이미지 파일의 일부로 저장되며, EXIF 데이터를 지원하는 소프트웨어 사용 시 이미지를 변경해도 데이터를 보존한다.
EXIF의 메타데이터
EXIF 메타데이터는 아래와 같은 정보들을 제공한다.
- 카메라 제조사
- 카메라 모델
- 회전 방향
- 날짜와 시간
- 색 공간
- 초점 거리
- 플래시
- ISO 속도
- 조리개
- 셔터 속도
- gps
2. 해결방법
해당 프로젝트에서는 이미지를 s3에 업로드 하고 있다.
이미지를 업로드하면, 파일 제약사항 (최대 크기 등)을 확인하고 확인된 파일을 바로 s3에 업로드 하는 방식이다.
이미지 회전을 해결하는 방법은 크게 두 가지가 있는데, 후자로 해결했다.
- 이미 업로드 된 사진에서 Exif 태그를 읽어 img 태그에서 이미지를 회전시킨다.
- 업로드 중에 EXIF태그를 읽어서, 회전할 이미지를 0도로 회전하여 저장한다.
* 참고: exif의 orientation 값
exif 의 orientation(회전방향) 값은 1 ~ 8 까지 있는데 아래와 같다. orientation 을 s3 에 업로드 하기 전에 모두 ‘1’로 변경하는 방법을 적용하려고 한다.
3. 해결
blueimp-load-image
로 이미지 파일의 Exif 메타 데이터(orientation)을 변형해보자. 해당 패키지는 이미지 파일을 불러오고 변형할 때 사용되는데, 이를 위해 loadImage
함수를 사용했다.
1) blueimp-load-image 패키지 설치
yarn add blueimp-load-image
2) 코드 적용
// 이미지 업로더 파일
import loadImage from 'blueimp-load-image';
...
const onImageUpload = useCallback(
...코드 생략
// 이미지 파일 데이터
const file = fileList[0];
// 추가된 코드
// 1. 이미지 로드
loadImage(
file,
function (img, data) {
// 2. 이미지 파일 데이터에 imageHead와 exif가 있는지 확인
if (data.imageHead && data.exif) {
// 3. exif 값이 있다면 orientation 값을 1로 변경
loadImage.writeExifData(data.imageHead, data, 'Orientation', 1);
img.toBlob(function (blob) {
loadImage.replaceHead(blob, data.imageHead, async function (newBlob) {
newBlob.name = file.name;
// 4. 기존 메서드로 파일 s3에 업로드
await uploadToS3(newBlob);
});
}, 'image/jpeg');
} else {
// exif 값 없으면 바로 s3에 업로드
uploadToS3(file);
}
},
{ meta: true, orientation: true, canvas: true },
);
)
3) 작동 확인
기존에 모바일 업로드 시 회전된 이미지를 다시 업로드 하니까, 회전 되지 않은 상태로 s3에 업로되는 것이 확인되었다.