이 문제는 회사에서 이미지 회전 현상이 일어난다는 QA를 받아서 수정하던 중 알게 되었습니다.
가끔 브라우저에서 사진을 업로드하거나 조회할 때 이미지가 본의 아니게 돌아가 있는 상태를 보실 수 있습니다.
요즘은 그런 현상이 거의 없지만, 2020년도에는 그런 현상이 있었습니다.
2022년 6월 15일부로 돌아가신 인터넷 익스플로러에도 아직까지 이러한 현상이 있습니다.
이 현상은 브라우저가 파일에 저장되어 있는 메타데이터를 읽고 대응해야 하는데, 그러지 못해서 생기는 일입니다.
일단 이미지 메타데이터는 어떤 것이 있는지 살펴보겠습니다.
메타데이터를 저장하게 해주는, 이미지 파일 포맷 : EXIF
디지털카메라, 스마트폰 카메라로 이미지를 찍으면 EXIF라는 이미지 파일 포맷입니다.
EXIF는 JPEG, TIFF 6.0, RIFF, WAV 파일에 정보를 담기 위해서 메타데이터를 저장합니다. (PNG, GIF는 지원 안됨)
이미지 회전 정보 : Orientation
EXIF에는 이미지 회전 정보를 담는 Orientation라는 데이터가 있습니다.
이 Orientation은 총 8가지 종류의 데이터를 가지고 있습니다.
value
|
description
|
1
|
0 degrees : the correct orientation, no adjustment is required.
|
2
|
0 degrees, mirrored : image has been flipped back-to-front.
|
3
|
180 degrees : image is upside down.
|
4
|
180 degrees, mirrored : image has been flipped back-to-front and is upside down.
|
5
|
90 degrees : image has been flipped back-to-front and is on its side.
|
6
|
90 degrees, mirrored : image is on its side.
|
7
|
270 degrees : image has been flipped back-to-front and is on its far side.
|
8
|
270 degrees, mirrored : image is on its far side.
|
문제의 원인
스마트폰으로 사진을 찍으면 세워서 찍을 때도 있고, 폰을 눕혀서 찍을 때도 있고, 셀카를 찍을 때도 있습니다.
폰을 눕혀서 찍으면 실제로 사진은 회전된 상태에서 찍힙니다. 하지만 갤러리가 이미지의 Oriantation 값을 읽어서 회전을 보정했기 때문에 회전되지 않은 사진을 볼 수 있습니다.
마찬가지로 셀카를 찍으면 거울을 보듯 반전된 사진을 보여야 하지만, Oriantation 값을 읽어 보정해 반전되지 않는 사진을 볼 수 있습니다.
대부분 최신 브라우저들은 이 Oriantation 값을 읽고 이미지를 보정해줍니다.
하지만 IE나 업데이트하지 않은 브라우저는 Oriantation 값을 읽어서 회전시켜주는 기능이 없어서 맨 위의 애니메이션처럼 회전된 이미지가 보이는 것입니다.
해결 방법
자바스크립트로 이미지 값을 읽고 메타데이터를 읽어 파일을 변경해주어야 하지만, 이 과정은 꽤나 까다롭습니다.
1. input file에서 image upload 2. File API중 FileReader를 사용하여 file의 data 확인 3. reader.onload 에서 Image 인스턴스 생성 4. read의 result값 == binary 데이터 5. img src에 result값 삽입 6. binary 데이터에서 orientation 관련 태그값 select => orientation 값 추출 7. orientation 값에 따라 img 회전 8. canvas 생성, img를 canvas에서 다시 그림 (drawImage) 9. 해당 canvas의 toDataURL를 사용하여 dataUrl추출 ... |
(출처 : https://feel5ny.github.io/2018/08/06/JS_13/)
그래서 여기저기 찾아보니 모두들 라이브러리를 사용하라고 권장하네요.
이쪽 계열의 유명한 라이브러리가 하나 있었습니다.
Load-Image.js
File, Blob 객체, URL를 통해 이미지를 로드하는 라이브러리입니다.
다양한 옵션을 주어서 이미지 크기, 자르기, 회전 등등 이미지를 컨트롤할 수 있습니다.
https://github.com/blueimp/JavaScript-Load-Image
또 라이브러리야?
보통 이미지를 다루는 개발을 할 때, FileReader와 Image 객체를 사용합니다.
그 FileReader로 file 객체를 얻으면 Image 객체를 사용하지 말고, loadImage를 사용해서 이미지를 얻을 수 있습니다.
그 이미지를 얻을 때, 다양한 옵션을 추가하여 얻을 수 있습니다.
사용방법
사용방법은 3가지가 있는데, callback, promise, async / await 중 선택하는 것입니다.
// callback 사용하기
document.getElementById('file-input').onchange = function () {
loadImage(
this.files[0],
function (img) {
document.body.appendChild(img)
},
{ orientation: true } // Options
)
}
// promise 사용하기
document.getElementById('file-input').onchange = function () {
loadImage(this.files[0], { orientation: true }).then(function (data) {
document.body.appendChild(data.image)
})
}
// async/await 사용하기
document.getElementById('file-input').onchange = async function () {
let data = await loadImage(this.files[0], { orientation: true })
document.body.appendChild(data.image)
}
최신 방법인 async / await를 사용하면 좋겠지만, 보통 이 코드는 IE를 대응하기 위한 코드이기 때문에 최신 Babel을 사용해야 합니다.
그런데 Babel을 사용해도 안될 경우가 있어서, polyfill을 사용해서 promise를 쓰거나, callback 방법을 사용해야 할 것입니다.
위의 3개의 코드를 보면 { orientation: true } // Options
라는 부분이 있습니다.
이 옵션이 이미지 회전을 보정해주는 옵션입니다. 그래서 이 옵션을 꼭 넣어야 바른 이미지의 모습을 보실 수 있습니다.
최신 브라우저는 잘 되는 이유 : image-orientation
최신 브라우저에는 image-orientation라는 CSS 속성을 지원합니다.
크롬은 2020년 8월 13일 이후로, 81 버전이 되면서 CSS의 image-orientation 속성 지원합니다.
그리고 IE 제외하고 대부분의 브라우저가 이 속성을 지원합니다.
https://chromestatus.com/feature/6313474512650240 (크로미움 81 업데이트 노트)
이 속성은 <img> 태그, css background-image 에 보이는 이미지의 EXIF를 읽고 orientation 값에 맞춰 이미지를 회전시켜줍니다.
(참고 : https://developer.mozilla.org/en-US/docs/Web/CSS/image-orientation)
그래서 최신 브라우저를 지원한다면, 애초에 이 문제를 신경 쓸 이유가 없습니다.
image-orientation : none
image-orientation을 none으로 두면 이미지 회전 보정이 안되는 모습을 볼 수 있습니다.
위에서 언급하다시피 image-orientation의 기본값인 default는 exif를 읽고 보정해줍니다.
추가 - 일렉트론 버전 문제
그런데 가끔 일렉트론 9버전 미만의 환경에서 개발하면, 이 문제가 일어날 것입니다.
일렉트론은 9버전부터 크로미움 81 버전을 지원하기 때문입니다.
https://www.electronjs.org/releases/stable?version=9&page=5#9.0.0
카카오톡 이미지 복사하면, EXIF 정보를 안 가져온다?
이 글은 작성일인 22년 7월 18일에 보이는 문제입니다. 이후 카카오톡이 업데이트가 되어있을 수 있습니다.
카카오톡에서 이미지를 열고, 이미지 복사 후 붙여넣기 하면 여전히 이미지가 돌아가는 문제를 발견했습니다.
그것은 크롬에서도 발견하는 문제였습니다. image-orientation를 지원하는 크롬에서 문제가 발생한다고?
그래서 확인해봤습니다.
카카오톡에서 이미지를 복사하는 순간 이미지의 메타데이터를 날려버리는 것으로 확인되었습니다.
이미지의 원래 방향을 알려주는 orientation 데이터를 날려버려서 어디에 복사하든 원래 이미지 방향을 알 수 없기 때문에 돌아가는 모습으로 보이는 것입니다.
그래서 이 문제는 크롬뿐만 아니라, 그림판, 포토샵에도 똑같은 문제가 발생합니다.
'개발 아카이브 > HTML, CSS' 카테고리의 다른 글
[CSS] background에 fade color 넣기 (0) | 2023.01.10 |
---|---|
[CSS] 긴 글자를 Fade Out으로 숨기는 CSS (0) | 2023.01.09 |
[CSS] CSS 텍스트 줄이기 ... 표시 (0) | 2021.08.23 |
[HTML] 웹 컬러 도구 사이트 (0) | 2021.03.22 |
[CSS 프레임워크] CSS 프레임워크 모음 (0) | 2021.02.13 |