Reputation: 1190
I am using UIImagePickerController to select image from camera or gallery in my SwiftUI app. I set allowsEditing to true. After setting it to true it is showing a square to select the photo like this:
I want to select image of size (e.g width = 150 and height = 150) instead of that square. Can I do that in SwiftUI. If yes, how can I achieve this?
This is my code:
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()
}
}
}
I had tried allows editing which gives me the square to select the photo but I need my given width and height selection of the photo. This is the desired result:
Upvotes: 3
Views: 1698
Reputation: 1
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]
}
}
}
how to work this
.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)
}
}
Upvotes: 0