从 SwiftUI 中的图像选择器裁剪图像

问题描述 投票:0回答:1

我正在使用 UIImagePickerController 从 SwiftUI 应用程序中的 cameragallery 选择图像。我将 allowsEditing 设置为 true。将其设置为 true 后,它会显示一个正方形来选择照片,如下所示:

image selection

我想选择尺寸的图像(例如width = 150height = 150)而不是那个square。我可以在 SwiftUI 中做到这一点吗?如果是,我怎样才能实现这一目标?

这是我的代码:

import Foundation
import SwiftUI

public struct ImagePickerView: UIViewControllerRepresentable {

    private let sourceType: UIImagePickerController.SourceType
    private let onImagePicked: (UIImage) -> Void
    @Environment(\.presentationMode) private var presentationMode

    public init(sourceType: UIImagePickerController.SourceType, onImagePicked: @escaping (UIImage) -> Void) {
        self.sourceType = sourceType
        self.onImagePicked = onImagePicked
    }

    public func makeUIViewController(context: Context) -> UIImagePickerController {
        let picker = UIImagePickerController()
        picker.sourceType = self.sourceType
        picker.delegate = context.coordinator
        picker.allowsEditing = true
        return picker
    }

    public func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {}

    public func makeCoordinator() -> Coordinator {
        Coordinator(
            onDismiss: { self.presentationMode.wrappedValue.dismiss() },
            onImagePicked: self.onImagePicked
        )
    }

    final public class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {

        private let onDismiss: () -> Void
        private let onImagePicked: (UIImage) -> Void

        init(onDismiss: @escaping () -> Void, onImagePicked: @escaping (UIImage) -> Void) {
            self.onDismiss = onDismiss
            self.onImagePicked = onImagePicked
        }

        public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
            
            if let img = info[.editedImage] as? UIImage {
                
                self.onImagePicked(img)
                
            } else if let image = info[.originalImage] as? UIImage {
                self.onImagePicked(image)
            }
            self.onDismiss()
        }

        public func imagePickerControllerDidCancel(_: UIImagePickerController) {
            self.onDismiss()
        }
    }
}

我尝试过允许编辑,这给了我选择照片的方块,但我需要给定照片的宽度和高度选择。这就是想要的结果:

desired

swift swiftui uiimage uiimagepickercontroller crop
1个回答
0
投票
struct ImagePicker: UIViewControllerRepresentable {
@Environment(\.presentationMode) private var presentationMode
var sourceType: UIImagePickerController.SourceType = .photoLibrary
@Binding var image: UIImage
var selectedImage: (UIImage, URL, CGSize) -> Void
var isApplyingCrop: Bool = false

func makeUIViewController(context: Context) -> UIImagePickerController {
    let imagePicker = UIImagePickerController()
    imagePicker.allowsEditing = false // Disable built-in editing
    imagePicker.sourceType = sourceType
    imagePicker.delegate = context.coordinator
    return imagePicker
}

func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {}

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

final class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate, CropViewControllerDelegate {
    var parent: ImagePicker
    var isApplyingCrop: Bool {
        parent.isApplyingCrop
    }

    init(_ parent: ImagePicker) {
        self.parent = parent
    }

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
        guard let originalImage = info[.originalImage] as? UIImage else {
            print("No image found")
            parent.presentationMode.wrappedValue.dismiss()
            return
        }

        // Proceed to the cropping controller with the selected image
        let cropViewController = CropViewController(image: originalImage)
        cropViewController.delegate = self
        if isApplyingCrop {
            cropViewController.customAspectRatio = CGSize(width: 270, height: 350)
        }
        picker.present(cropViewController, animated: true, completion: nil)
    }

    // CropViewControllerDelegate methods
    func cropViewController(_ cropViewController: CropViewController, didCropToImage croppedImage: UIImage, withRect cropRect: CGRect, angle: Int) {
        // Generate unique name and URL for the cropped image
        let imageName = UUID().uuidString
        let imagePath = getDocumentsDirectory().appendingPathComponent(imageName).appendingPathExtension("jpg")

        // Save the cropped image
        if let jpegData = croppedImage.jpegData(compressionQuality: 0.8) {
            do {
                try jpegData.write(to: imagePath)
            } catch {
                print("Error saving cropped image: \(error.localizedDescription)")
            }
        }

        // Pass cropped image, URL, and crop size to the closure
        parent.selectedImage(croppedImage, imagePath, cropRect.size)
        parent.image = croppedImage

        // Dismiss both CropViewController and UIImagePickerController
        cropViewController.dismiss(animated: true) {
            self.parent.presentationMode.wrappedValue.dismiss()
        }
    }

    func cropViewControllerDidCancel(_ cropViewController: CropViewController) {
        // Dismiss the CropViewController if the user cancels
        cropViewController.dismiss(animated: true, completion: nil)
    }

    // Helper function to get the documents directory path
    func getDocumentsDirectory() -> URL {
        FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
    }
}

}

如何工作

 .fullScreenCover(isPresented: $showImagePicker) {
        if let sourceType = self.sourceType {
            ImagePicker(sourceType: sourceType,
                        image: self.$image,isApplyingCrop:true) { img, url, size  in
                self.isAnyImageGotPicked = true
                self.image = img
                self.filePath = url
            }
            .edgesIgnoringSafeArea(.all)
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.