혼자 적어보는 노트

모바일 이미지 업로드 시 이미지 회전 현상 본문

Error

모바일 이미지 업로드 시 이미지 회전 현상

jinist 2022. 7. 12. 22:37

 

모바일 이미지 업로드 시 이미지 회전 현상

프로젝트를 리팩토링하고 확인하는 과정에서

핸드폰으로 촬영한 이미지를 업로드할 때 회전되어서 보여지는 현상이 발생했다.

사용하는 핸드폰은 아이폰이고 원본(실제크기) 그대로 올릴 경우 제대로 나타나지만
업로드 할 때 아이폰 기능에서 파일 사이즈를 줄일 경우 회전이된다.

 

 

왜 사진이 회전될까?

휴대폰을 세워서 정상적인 각도에서 사진을 찍으면 정상적으로 나타나지만
핸드폰의 각도를 기울여서 찍은 경우 틀어져서 저장이 되고 이 회전 정보를 기억한다고 한다.

이 회전된 정보는 EXIF라는 메타정보의 orientation 에 저장이 되는데
핸드폰의 경우 이 정보를 읽어서 정상적으로 갤러리에 보여주지만
브라우저는 이 orientation정보를 읽지 못한다고 한다,,

 

 

해결을 위해 시도한 방법

blueimp-load-image 라이브러리 사용

File, Blob 객체로 제공되는 이미지를 img 또는 canvas요소로 변환해주는 라이브러리이다.
옵션이되는 기능에 메타데이터를 분석하고 Exif의 방향값을 덮어쓰고 크기 조정 후에

이미지 헤더를 복원하는 방법을 제공한다고 한다.

 

[promise방식]

    loadImage(fileBlob, { meta: true, orientation: true, canvas: true }).then(
      async (data) => {
        data.image.toBlob((blob) => {
          const rotateFile = new File([blob], fileBlob.name, { type: fileBlob.type });

          const reader = new FileReader();
          reader.readAsDataURL(rotateFile);
          reader.onload = () => {
            setImageSrc(reader.result);
            onChange(reader.result);
          };
        });
      },
    );

찾아보니 위와 같이 promise 형식으로 orientation을 변경시키고 변경된 data를 받아서

처리하는 코드를 작성할 수 있었다.

 

=> 그런데 안된다..??

 

[콜백 방식]

    loadImage(fileBlob, { meta: true, orientation: true, canvas: true }).then(
      (data) => {
        if (data.imageHead && data.exif) {
          // data.imageHead가 있는 것만 변경.
          loadImage.writeExifData(data.imageHead, data, 'Orientation', 6);
          alert(data.exif + ' imageHead');
          data.image.toBlob(async function (blob) {
            loadImage.replaceHead(blob, data.imageHead, async function (newBlob) {
              newBlob.name = fileBlob.name;

              alert(newBlob);

              const reader = new FileReader();
              reader.readAsDataURL(newBlob);
              reader.onload = () => {
                setImageSrc(reader.result);
                onChange(reader.result);
              };
            });
          }, 'image/jpeg');
        } else {
          // const reader = new FileReader();
          // reader.readAsDataURL(fileBlob);
          // reader.onload = () => {
          //   setImageSrc(reader.result);
          //   onChange(reader.result);
          // };
        }
      },
    );

 

위와 같이 콜백방식으로도 작성해보았다. 일단 되는지부터 확인하기위해 코드를 조금 막 작성했다.

(위 방법 말고도 내 코드에 문제가 있나 해서 여러 코드를 작성했었음...)

 

그런데!!

다른사람들이 된다는 코드를 사용했음에도 불구하고 업로드 시 회전된 이미지로 보였다.

 

 

exif-js 라이브러리 사용

 

orientation값을 직접 확인하기위해 exif-js 라이브러리를 설치해서

이미지 업로드 시 값을 띄워보기로 했다.

 

    EXIF.getData(fileBlob, () => {
      const orientation = EXIF.getTag(fileBlob, 'Orientation');
      alert(orientation + ' data');
    });

 

그런데 갤러리에서 원본 이미지로 올렸을 때는 값이 6이 나타났다. (값이 6이면 왼쪽으로 90도 회전되어야 한다)

근데 값과는 달리 원본 이미지의 경우는 업로드 시 정방향으로 제대로 보이는 상태이다.😱

 

그리고 업로드 시 이미지 사이즈를 조절하여 등록할 경우 orientation값은 1이 나왔다.

???? orientation값이 1인데 왜 회전이 되어서 보이는걸까??

 

추측..

원본 이미지의 orientation는 업로드할 때 알아서 1로 변경되어 업로드 되게끔 처리가 되는데

아이폰 내부의 파일 크기 변환 과정에있어서 기존의 orientation (6)인 상태로 압축이 되어버려서

회전된 이미지가 정방향 이미지인 것 처럼 데이터가 덮어 씌워져버린 것이 아닐까 추측해봤다.

 

결국 회전된 상태 자체가 1(정방향)으로 인식을 해버리니까

orientation값을 아무리 1로 다시 변경해도 당연히!!! 변경이 안되는 것이다!! 

 

그러면 다른 방법을 사용할 순 없을까 하는 생각으로

키워드를 변경해서 검색을 해본 결과

 

https://stackoverflow.com/questions/66661973/iphone-os-image-photo-resizing-tool-changing-exif-orientation-data/66836205#66836205

 

iPhone OS image/photo resizing tool changing EXIF orientation data

It looks like when taking an HDR photo from an iOS device, because Apple doesn't rotate images and shoots them all in landscape, there's EXIF metadata (orientation in specific) that tell other soft...

stackoverflow.com

 

나와 같은 문제를 겪는 사람이 있었고 이전에도 제기된 문제였다고 하는데

추측으로는 IOS의 버그라고 한다.

 

다른 사이트나 앱을 살펴보니 보통 내 사례처럼 회전이 되는채로 두거나

이미지 크기 조정하는 창으로 넘어가지 않고 바로 원본이미지를 편집할 수 있는

에디터로 넘어가는 형태로 구현되어 있었다.

 

꽤 시간을 썼지만 일단 이미지를 자동으로 맞춰주는 방법은 미루고

차라리 사용자가 이미지를 직접 회전할 수 있게 방식을 바꾸기로 했다.

 

해결하지 못하고 끝난 사례지만 혹시나 해결하는 방법을 알게 되면 포스팅을 수정할 예정이다.

Comments