Reputation: 115
I know many people had asked this question, but I am not found some correct answer to fix this issue,My problem is : How can I make the photo on preview view(after user tap the capture button,and then go to the preview view to let the user preview) not mirror, can this prossible fix in UIImagePickerController, I know how to rotate the photo , something in enum in UIImageOrientation
like UIImageOrientationUp
, I know what this mean.
I attend to get the photo after user tap capture button before go to the preview view and use the photo which I have mirror to cover the default photo (use cameraOverlayView
), I can detect the user tap the capture button use NSNotificationCenter
with @"_UIImagePickerControllerUserDidCaptureItem", but I find no way to get the photo.
I use cameraViewTransform
, but when user take photo (front camera) when the Home button on the bottom or top, the image on preview view is not mirror, but when the Home
button on the left or right, the image on phone have some problem before user tap the capture, although the image on the preview view is not mirror.use AVCaptureDeviceDidStartRunningNotification
notification.
- (void)cameraChanged:(NSNotification *)notification
{
if(self.imagePickerController.cameraDevice == UIImagePickerControllerCameraDeviceFront)
{
self.imagePickerController.cameraViewTransform = CGAffineTransformIdentity;
self.imagePickerController.cameraViewTransform = CGAffineTransformScale(self.imagePickerController.cameraViewTransform, -1, 1);
if (self.imagePickerController.cameraOverlayView) {
NSLog_DEBUG(@"self.imagePickerController.cameraOverlayView is not nil");
} else {
NSLog_DEBUG(@"self.imagePickerController.cameraOverlayView is nil");
}
self.imagePickerController.cameraOverlayView.transform = CGAffineTransformScale(self.imagePickerController.cameraViewTransform, -1, 1);
} else {
self.imagePickerController.cameraViewTransform = CGAffineTransformIdentity;
}
}
Upvotes: 1
Views: 1636
Reputation: 11
Good afternoon. Maybe I'm answering late, but today I solved this problem. Here is the code to solve the UIImagePickerController preview mirroring issue.
`
struct AddImageFromLibrary: UIViewControllerRepresentable {
@Environment(\.presentationMode) private var presentationMode
@Binding var sourceType: UIImagePickerController.SourceType
@Binding var selectedImage: UIImage?
func makeUIViewController(context: UIViewControllerRepresentableContext<AddImageFromLibrary>) -> UIImagePickerController {
let imagePicker = CameraCaptureViewController()
imagePicker.allowsEditing = true
imagePicker.sourceType = sourceType
imagePicker.delegate = context.coordinator
imagePicker.modalPresentationStyle = .fullScreen
return imagePicker
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<AddImageFromLibrary>) {}
func makeCoordinator() -> Coordinator {
return Coordinator(self)
}
final class Coordinator: NSObject, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var parent: AddImageFromLibrary
init(_ parent: AddImageFromLibrary) {
self.parent = parent
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let image = info[.editedImage] as? UIImage {
let imageMirroriedNorm = UIImage(cgImage: image.cgImage!, scale: image.scale, orientation: .upMirrored) // mirroed photo
parent.selectedImage = image
if picker.sourceType == .camera && picker.cameraDevice == .front{
parent.selectedImage = imageMirroriedNorm
print("Mirror")
}else{
parent.selectedImage = image
print("Original")
}
}
parent.presentationMode.wrappedValue.dismiss()
}
}
}
protocol CameraCaptureViewControllerDelegate {
func cameraPositionDidChanged(newPosition: AVCaptureDevice.Position)
}
class CameraCaptureViewController: UIImagePickerController {
var lastKnownPosition = AVCaptureDevice.Position.unspecified {
didSet {
cameraDelegate?.cameraPositionDidChanged(newPosition: lastKnownPosition)
}
}
var cameraDelegate: CameraCaptureViewControllerDelegate?
weak private var session: AVCaptureSession?
private var context = 0
deinit {
session?.removeObserver(self, forKeyPath: "inputs")
NotificationCenter.default.removeObserver(self)
}
override func viewDidLoad() {
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(forName: NSNotification.Name(rawValue: "_UIImagePickerControllerUserDidCaptureItem"), object: nil, queue: nil) { [weak self] (notification) in
if self?.lastKnownPosition == .front {
self?.changePhotoOrientation()
}
}
notificationCenter.addObserver(forName: NSNotification.Name(rawValue: "AVCaptureSessionDidStartRunningNotification"), object: nil, queue: nil) { [weak self] notification in
self?.handleCaptureSessionDidStartRunning(notification: notification)
}
notificationCenter.addObserver(forName: NSNotification.Name(rawValue: "AVCaptureSessionDidStopRunningNotification"), object: nil, queue: nil) { [weak self] notification in
self?.handleCaptureSessionDidStopRunning(notification: notification)
}
}
func changePhotoOrientation() {
var subviews: [UIView] = [view]
while !subviews.isEmpty {
let subview = subviews.removeFirst()
subviews += subview.subviews
if (subview.isKind(of: UIImageView.self)) {
subview.transform = cameraViewTransform.scaledBy(x: -1, y: 1)
}
}
}
func handleCaptureSessionDidStartRunning(notification: Notification){
guard let session = notification.object as? AVCaptureSession else { return }
self.session = session
if let input = session.inputs.first as? AVCaptureDeviceInput {
lastKnownPosition = input.device.position
}
session.addObserver(self, forKeyPath: "inputs", options: [ .old, .new ], context: &context)
}
func handleCaptureSessionDidStopRunning(notification: Notification) {
guard let session = notification.object as? AVCaptureSession else { return }
session.removeObserver(self, forKeyPath: "inputs")
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if let inputs = change?[NSKeyValueChangeKey.newKey] as? [AnyObject], let captureDevice = (inputs.first as? AVCaptureDeviceInput)?.device {
lastKnownPosition = captureDevice.position
}
}
}
`
Upvotes: 1
Reputation: 115
finally, i can not solve this issue in UIImagePickerController
, but i solve this issue using AVFoundation
and CoreMotion
, you can see AVCam
//init the motionManager
- (void)initializeMotionManager{
motionManager = [[CMMotionManager alloc] init];
motionManager.accelerometerUpdateInterval = .1;
motionManager.gyroUpdateInterval = .1;
[motionManager startAccelerometerUpdatesToQueue:[NSOperationQueue currentQueue]
withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) {
if (!error) {
[self outputAccelertionData:accelerometerData.acceleration];
}
else{
NSLog_DEBUG(@"%@", error);
}
}];
}
//detect the device orientation
- (void)outputAccelertionData:(CMAcceleration)acceleration{
if (acceleration.x >= 0.75) {
_orientationNew = UIInterfaceOrientationLandscapeLeft;
}
else if (acceleration.x <= -0.75) {
_orientationNew = UIInterfaceOrientationLandscapeRight;
}
else if (acceleration.y <= -0.75) {
_orientationNew = UIInterfaceOrientationPortrait;
}
else if (acceleration.y >= 0.75) {
_orientationNew = UIInterfaceOrientationPortraitUpsideDown;
}
else {
// Consider same as last time
return;
}
if (_orientationNew == _orientationLast)
return;
_orientationLast = _orientationNew;
}
Upvotes: 2