티스토리 뷰

이미지와 동영상 파일에는 방향 정보가 있어 뷰에 표시할 때에 방향을 적용해서 표시해야 한다. 적용가능한 UIImage에 적용 가능한 Orientation의 종류는 다음과 같다. (UIImage.Orientation, Image.Orientation)

  • Up
    • 원본 픽셀이 이미지의 의도와 동일. 방향 전환이 필요 없음.
  • Down
    • 180도 회전 필요.
  • Left
    • 반시계 방향으로 90도 회전 필요.
  • Right
    • 시계 방향으로 90도 회전 필요.
  • Up Mirrored
    • 좌우 반전 필요.
  • Down Mirrored
    • 위아래 반전 필요.
  • Left Mirrored
    • 좌우 반전 후 시계 방향으로 90도 회전 필요.
  • Right Mirrored
    • 좌우 반전 후 반시계 방향으로 90도 회전 필요.

아이폰에서 촬영한 사진/동영상의 경우 카메라 방향에 따라 이 방향 정보가 설정되는데 이 정보를 제대로 읽어와야 한다. 읽어온 뒤 UIImage 또는 Image(SwiftUI 뷰타입)에 넘겨주면 된다.

Orientation 가져오기

AVCapturePhoto에서 Orientation 가져오기

AVCapturePhoto의 metadata에 접근하여 방향 정보를 가져올 수 있다.

let photo: AVCapturePhoto = ...
guard let metadataOrientation = photo.metadata[String(kCGImagePropertyOrientation)] as? UInt32,
      let cgImageOrientation = CGImagePropertyOrientation(rawValue: metadataOrientation) else { return }

CGImagePropertyOrientation은 UIImage, Image의 Orientation과 동일한 case를 갖고 있지만 같은 타입이 아니고 rawValue가 다르기 때문에 직접 매핑해주어야 한다.

https://developer.apple.com/documentation/imageio/cgimagepropertyorientation

extension Image.Orientation {

    init(_ cgImageOrientation: CGImagePropertyOrientation) {
        switch cgImageOrientation {
        case .up: self = .up
        case .upMirrored: self = .upMirrored
        case .down: self = .down
        case .downMirrored: self = .downMirrored
        case .left: self = .left
        case .leftMirrored: self = .leftMirrored
        case .right: self = .right
        case .rightMirrored: self = .rightMirrored
        }
    }
}

CIImage에서 Orientation 가져오기

CIImage는 정보를 가져오기 위해 TIFF 프로퍼티에 접근해야 한다.

let ciImage: CIImage = ...
guard let tiffOrientation = ciImage.properties["Orientation"] as? Int else { return }

Orientation 키의 값을 가져오면 정수 값이 나오는데 이 숫자는 Image.Orientation의 rawValue와는 다르기 때문에 별도의 매핑이 필요하다.

extension Image.Orientation {
    init?(tiffValue: Int) {
        switch tiffValue {
        case 1:
            self = .up
        case 3:
            self = .down
        case 8:
            self = .left
        case 6:
            self = .right
        case 2:
            self = .upMirrored
        case 4:
            self = .downMirrored
        case 5:
            self = .leftMirrored
        case 7:
            self = .rightMirrored
        default:
            return nil
        }
    }
}

AVAsset에서 기기 회전 정보 및 카메라 전/후 가져오기

extension AVAsset {

    func videoOrientation() -> (orientation: UIInterfaceOrientation, device: AVCaptureDevice.Position) {
        var orientation: UIInterfaceOrientation = .unknown
        var device: AVCaptureDevice.Position = .unspecified

        let tracks :[AVAssetTrack] = self.tracks(withMediaType: AVMediaType.video)
        if let videoTrack = tracks.first {

            let t = videoTrack.preferredTransform

            if (t.a == 0 && t.b == 1.0 && t.d == 0) {
                orientation = .portrait

                if t.c == 1.0 {
                    device = .front
                } else if t.c == -1.0 {
                    device = .back
                }
            }
            else if (t.a == 0 && t.b == -1.0 && t.d == 0) {
                orientation = .portraitUpsideDown

                if t.c == -1.0 {
                    device = .front
                } else if t.c == 1.0 {
                    device = .back
                }
            }
            else if (t.a == 1.0 && t.b == 0 && t.c == 0) {
                orientation = .landscapeRight

                if t.d == -1.0 {
                    device = .front
                } else if t.d == 1.0 {
                    device = .back
                }
            }
            else if (t.a == -1.0 && t.b == 0 && t.c == 0) {
                orientation = .landscapeLeft

                if t.d == 1.0 {
                    device = .front
                } else if t.d == -1.0 {
                    device = .back
                }
            }
        }

        return (orientation, device)
    }
}

출처: https://gist.github.com/kimdwkimdw/bdc68dcbbd7b6ca994a99c90dd24a7cb

CGAffineTransform의 정보를 이용하여 회전 정보 및 카메라 정보를 가져온다. 그리고 해당 정보를 Orientation에 매핑한다.

let asset: AVAsset = ...
var orientation = Image.Orientation.up
switch asset.videoOrientation().orientation {
case .landscapeRight:
    orientation = .up
case .landscapeLeft:
    orientation = .down
case .portraitUpsideDown:
    orientation = .left
case .portrait:
    orientation = .right
case .unknown:
    break
@unknown default:
    break
}

뷰에 Orientation 적용하기

SwiftUI Image

CIImage를 CGImage로 변환해준 뒤 Image를 방향정보와 함께 이니셜라이즈한다.

let image = Image(decorative: cgImage, scale: 1, orientation: orientation)

UIKit UIImage

let uiImage = UIImage(cgImage: cgImage, scale: 1, orientation: orientation)
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/04   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30
글 보관함