5

I get an image with AsyncImage() to be displayed in a view.

struct Pic: View {
  var body: some View {
    let url = FileManager.default.url(forUbiquityContainerIdentifier: nil)?.appendingPathComponent("Documents").appendingPathComponent("IMG_5328.jpeg")
    
    AsyncImage(url: url) { image in
      image
      .resizable()
 //     if(image.orientation == .right) {
 //       .rotationEffect(.degrees(90))
 //     }
      .scaledToFit()
    } placeholder: {
      Color.red
    }
  }
}

The imagefile (IMG_5328.jpeg) has an orientation of 6 (90 Degree counterclockwise), but the image is not rendered with automatic rotation.
How can I get the orientation to rotate it manually.

Working with UIImage does it automatically.

let url = FileManager.default.url(forUbiquityContainerIdentifier: nil)?.appendingPathComponent("Documents").appendingPathComponent("IMG_5328.jpeg")  
    let imageData = try! Data(contentsOf: url!)
    let uiImage = UIImage(data: imageData)!
mica
  • 3,898
  • 4
  • 34
  • 62

1 Answers1

-1

I had the same problem, but there are some differences, however I think you can use this solution.

First, add an extension to detect image orientation. It's not mandatory, you can use a local function or ternary operator directly into the view modifier of rotation effect.

import SwiftUI

extension UIImage {

    func getRotationAngle() -> Angle {
        switch imageOrientation {
        case .left:
            return Angle(degrees: 270)
        case .leftMirrored:
            return Angle(degrees: 270)
         case .right:
            return Angle(degrees: 90)
        case .rightMirrored:
            return Angle(degrees: 90)
        case .down:
            return Angle(degrees: 180)
        case .downMirrored:
            return Angle(degrees: 180)
        default:
            return Angle(degrees: 0)
        }
    }

}

Then You need to get the UIImage. For that You can use this image picker or your alternative is perfect too.

import SwiftUI

struct ImagePicker: UIViewControllerRepresentable {

    @Binding var image: UIImage?
    @Binding var imageURL: URL?
    @Environment(\.presentationMode) var presentationMode

    class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
        let parent: ImagePicker

        init(_ parent: ImagePicker) {
            self.parent = parent
        }
    
        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
            if let uiImage = info[.originalImage] as? UIImage {
                parent.image = uiImage
            }
            if let imageURL = info[.imageURL] as? URL {
                parent.imageURL = imageURL
                // Alternative
                //let imageData = try! Data(contentsOf: url!)
                //parent.image = UIImage(data: imageData)!
            }
            parent.presentationMode.wrappedValue.dismiss()
        }
    }

    func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
        let picker = UIImagePickerController()
        picker.delegate = context.coordinator
        return picker
    }

    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }

    func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {

    }

}

And here the implementation.

import SwiftUI

struct ProfileView: View {
    
    @State private var showingImagePicker = Bool()
    @State private var inputImage = UIImage(systemName: "person.crop.circle")
    @State var imageURL: URL? = nil
    
    var body: some View {
        VStack(spacing: 0) {
            Text("Your profile")
                .foregroundColor(.white)
                .font(.custom("VisbyCF-Heavy", size: 24))
                .frame(maxWidth: .infinity, alignment: .leading)
                .padding(.top, 37)
                .padding(.bottom, 33)
            VStack(spacing: 0) { // Picture
                ZStack {
                    if #available(iOS 15.0, *) {
                        AsyncImage(
                            url: imageURL,
                            content: { image in
                                image
                                    .resizable()
                                    .aspectRatio(contentMode: .fill)
                                    .frame(maxWidth: 105, maxHeight: 105)
                                    .cornerRadius(53)
                                    .rotationEffect(inputImage?.getRotationAngle() ?? Angle(degrees: 0))
                            }, placeholder: {
                                Image(systemName: "person.crop.circle")
                                    .resizable()
                                    .aspectRatio(contentMode: .fill)
                                    .frame(maxWidth: 105, maxHeight: 105)
                                    .cornerRadius(53)
                            }
                        )
                    }
                    ZStack {
                        HStack{
                            Image(systemName: "pencil.circle")
                                .resizable()
                                .frame(width: 12, height: 12)
                                .padding(5)
                        }
                        .frame(width: 24, height: 24)
                        .background(Color.blue)
                        .clipShape(Circle())
                        .shadow(radius: 10)
                        .onTapGesture {
                            self.showingImagePicker = true
                        }
                    }
                    .frame(maxWidth: 105,maxHeight: .infinity, alignment: .bottom)
                    .offset(x: 35)
                }
                .frame(width: 105, height: 105)
                .padding(.bottom, 7)
                Text("Change picture")
                    .foregroundColor(Color.white)
                    .font(.custom("VisbyCF-Heavy", size: 14))
                    .padding(.bottom, 32)
            }
            Spacer()
        }
        .padding([.leading, .trailing], 35)
        .navigationBarColor(.clear)
        .navigationBarTitle(Text("Your profile"), displayMode: .inline)
        .sheet(isPresented: $showingImagePicker) {
            ImagePicker(image: $inputImage, imageURL: $imageURL)
        }
    }
    
}Ï
Erick Dávila
  • 347
  • 5
  • 9
  • 1
    thx, @Erick Dávila, don´t you get the rotation angle from the inputImage (which is "person.crop.circle") instead of the returned image from AsyncImage? – mica Feb 12 '22 at 09:49
  • I got the angle from inputImage because it's a UIImage from UIKit, the image returned by AsyncImage is a SwiftUI view. However I think you could transform that View into UIImage and get the angle from there – Erick Dávila Feb 14 '22 at 15:04
  • if you have an idea, how to convert a SwiftUI image into a UIImage, I think that would solve the problem. – mica Feb 15 '22 at 09:48
  • I found this https://stackoverflow.com/a/64005395/5938089, maybe It helps you – Erick Dávila Feb 15 '22 at 15:56