UIImage의 이미지가 방향이 바뀌는 경우

PHPicker로 가져온 이미지 방향이 회전

PHPicker를 이용하여 이미지를 여럿 선택하여 ImageView에 렌더링 할 때, 이미지 방향이 바뀌는 문제가 발생했다. 또 가져온 UIImage를 png() 함수를 이용해 Filemanager에 저장한 후, 해당 이미지를 가져와서 다시 UIImage로 렌더링 할 경우에도 같은 문제가 발생했다.

원인은 UIImage.Orientation 때문이었다. iOS에서 카메라로 사진을 찍을 때, 여러 방향에서 사진을 찍을 수 있다. 이때, 사진을 저장할 때, 기본적으로 가로모드 (카메라가 왼쪽에 있는 방향)를 기본으로 사진을 저장한다. 즉 사진을 찍었을 때, 세로 모드로 찍었어도, 저장될 때 가로 방향으로 픽셀 데이터를 인코딩하여 저장한다. 

왼쪽 사진처럼 세로 모드로 찍어도 실제로 저장되는 파일은 오른쪽처럼 저장된다는 것이다. 사진이 저장될 때, 메타데이터에서 찍은 사진의 회전된 사진과 어떤 방향으로 회전되었는지에 대한 메타데이터를 가지고 있다. 이 메타데이터값으로 UIImage는 회전된 이미지라면 자동으로 데이터를 회전시키고 이미지를 렌더링 한다.

 

하지만 나의 경우에는 UIImage를 생성하는 것이 아닌 NSItemProvider의 loadObject로 NSItemProviderReading을 형변환을 통해 이미지를 만들었기 때문에, 이런 문제가 발생한 것이 아닐까 싶다. 그래서 이미지가 자동으로 회전되지 않고 원본이미지 그대로 렌더링 된 게 아닐까 하고 추측해 본다.

    func convertImage(provider: NSItemProvider) -> Observable<UIImage> {
        return Observable<UIImage>.create { observer in
            if provider.canLoadObject(ofClass: UIImage.self) {
                provider.loadObject(ofClass: UIImage.self) { image, error in
                    if let errror = error {
                        observer.onError(error!)
                    } else {
                        guard let convertImage = image as? UIImage else { return }
                        observer.onNext(convertImage)
                        observer.onCompleted()
                    }
                }
            }
            return Disposables.create()
        }
    }

 

해결방식

다행히 UIImage는 orientation을 인자값으로 받는 생성자가 존재한다. 이를 이용해서 원본 이미지의 orientation 값으로 회전시켜서 올바르게 보이게 했다. 

extension UIImage {
   func orientImage() -> UIImage {
        if imageOrientation == .up {
            return self
        }
        guard let cgImage else { return self }
        return UIImage(cgImage: cgImage, scale: 1.0, orientation: imageOrientation)
    }
}

 

+ 추가

이 글을 쓰기위해 해당 문제를 재현해 보려고 회전하는 코드를 제거해 봤는데, 이번에는 회전하는 코드가 안 들어갔음에도 이미지가 회전한 채로 들어갔다. 깃으로 해당 문제가 아직 해결되지 않았던 버전으로 돌아가서 실행했는데도 불구하고 실행하니 정상적으로 이미지가 들어갔다. 왜 이런 걸까..

 

 

참고: https://developer.apple.com/documentation/uikit/uiimage/orientation