UIImagePickerController's cameraViewTransform is ignoring 'scaling' and 'translation' on iOS 10 beta
Asked Answered
E

5

11

I have been using below code to scale my UIImagePickerController's live preview to fill the entire screen. This worked perfectly till now. Before few days, I installed iOS 10 beta 7 on an iPhone 5 and it doesn't scale anymore. I can see black patch at the bottom of UIImagePickerController's view. Seems like cameraViewTransform is ignoring the CGAffineTransformMakeScale and CGAffineTransformMakeTranslation calls.

This is how I initiate my camera controller. I have set both "allowsEditing" and "showsCameraControls" to 'NO' in order to provide my own custom overlay view.

objImagePickerController =[[UIImagePickerController alloc] init];

objImagePickerController.delegate = self;
objImagePickerController.sourceType =UIImagePickerControllerSourceTypeCamera;
objImagePickerController.cameraCaptureMode = UIImagePickerControllerCameraCaptureModePhoto;
objImagePickerController.allowsEditing = NO;
objImagePickerController.showsCameraControls= NO;

This is what I use to scale the camera live preview.

CGSize screenSize = [[UIScreen mainScreen] bounds].size;
float screenHeight= MAX(screenSize.height, screenSize.width);
float screenWidth= MIN(screenSize.height, screenSize.width);

float cameraAspectRatio = 4.0 / 3.0;
float imageWidth = floorf(screenWidth * cameraAspectRatio);
float scale = ceilf((screenHeight / imageWidth) * 10.0) / 10.0;

objImagePickerController.cameraViewTransform= CGAffineTransformMakeScale(scale, scale);

This is how I add the camera view as a subview instead of traditional modal presentation method, to suit my own requirements.

 [[[UIApplication sharedApplication] keyWindow]addSubview:objImagePickerController.view];

screenshot from iPhone 5s running on iOS 10 beta 8

enter image description here

screenshot from iPhone 5s running on iOS 8.2

enter image description here

As noticeable from the above screenshots, the cameraViewTransform doesn't respect the CGAffineTransformMakeScale in iOS 10 beta.

Did anybody else face this issue? This is a really weird behavior appearing in iOS 10 beta OS. I am unable to find a workaround for this. Please advise.

NOTE:: objImagePickerController is an instance of UIImagePickerController.

Eldoneldora answered 24/8, 2016 at 13:32 Comment(11)
why do you give two different objs to cameraViewTransform ?Bonn
@TejaNandamuri: Sorry, I didn't get you!Eldoneldora
Please note that this transform affects only live preview images but nothing else. I don't think live preview images are available on iphone 5.Bonn
No, this is not live preview. "cameraViewTransform" refers to the transform property of UIImagePickerController's view.Eldoneldora
I'm not sure, that's what it says in the documentation. There is a similar question asked here #25735462Bonn
Not sure if that solution works or not. I will give a try.Eldoneldora
An update- iOS 10 beta 8 is already released and the same issue persists there too.Eldoneldora
I'm experiencing this bug too and submitted it to bugreport.apple.com.Korn
looks like the GM release has the same issue... great..Gunderson
Sad news!! So, any workaround for this?Eldoneldora
nope ive tried every different way to call cameraViewTransform nothing works, i suppose we wait to see if they fix it, or have to change our custom views to accommodate the black bar, for > ios 10Gunderson
I
7

Strangely it only allows us to transform it after the presentation was completed.

Example:

self.presentViewController(
        self.imagePicker,
        animated: true,
        completion: {
            let screenSize = UIScreen.mainScreen().bounds.size
            let ratio: CGFloat = 4.0 / 3.0
            let cameraHeight: CGFloat = screenSize.width * ratio
            let scale: CGFloat = screenSize.height / cameraHeight

            self.imagePicker.cameraViewTransform = CGAffineTransformMakeTranslation(0, (screenSize.height - cameraHeight) / 2.0)
            self.imagePicker.cameraViewTransform = CGAffineTransformScale(self.imagePicker.cameraViewTransform, scale, scale)
        }
    )

This code will transform the camera view to match the screen size.

Note that this is a workaround. It works, but the user will see it resizing upon presentation.

Intricate answered 16/9, 2016 at 14:57 Comment(2)
This worked for me by adding it to my cameraIsReadyNotification method.Sadden
Doesn't work when you change imagePicker source to "UIImagePickerControllerSourceTypePhotoLibrary" and then back to "UIImagePickerControllerSourceTypeCamera"Sisile
W
5

As answered here, this issue has been fixed in iOS 10.2 and you can use the cameraViewTransform property before presenting the camera again.

Wyatt answered 12/11, 2016 at 9:46 Comment(1)
Ohh really? I will definitely test it on latest beta versionEldoneldora
S
2

I've solved by delaying set cameraViewTransform after camera e AVCaptureSessionDidStartRunningNotification is raised:

 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(cameraIsReadyNotification:) name:AVCaptureSessionDidStartRunningNotification object:nil]; 

-

- (void)cameraIsReadyNotification:(NSNotification *)notification  
 {  
          dispatch_async(dispatch_get_main_queue(), ^{  
          float scale = ceilf((screenHeight / imageWidth) * 10.0) / 10.0;

          objImagePickerController.cameraViewTransform=CGAffineTransformMakeScale(scale, scale);
          });  
  }
Straw answered 23/9, 2016 at 9:44 Comment(4)
So, is it working fine on iOS 10? When does this notification event gets fired?Eldoneldora
Yes, in my case. The only bad is that the change is visible to the user like a flick effect.Straw
Ohh okay. Hope that's a minor flickeringEldoneldora
Doesn't work when you change imagePicker source to "UIImagePickerControllerSourceTypePhotoLibrary" and then back to "UIImagePickerControllerSourceTypeCamera"Sisile
M
1

I had the same problem earlier in IOS 9.3 also. Here is the code i used

//transform values for full screen support
#define CAMERA_TRANSFORM_X 1
#define CAMERA_TRANSFORM_Y 1.12412    

        if (IS_IPAD)
            CGAffineTransformScale(objImagePickerController.cameraViewTransform, CAMERA_TRANSFORM_X,  CAMERA_TRANSFORM_Y);
        else if (IS_IPHONE_5_Land||IS_IPHONE_4_Land||IS_IPHONE_6_Land||IS_IPHONE_6_PLUS_Land)
        {
            objImagePickerController.cameraViewTransform = CGAffineTransformScale(CGAffineTransformIdentity, 2, 2);
        }

Hope this helps

Mauramauralia answered 6/9, 2016 at 6:47 Comment(3)
Thanks for your answer. But, for me, my existing code works fine till the latest 9.x.x iOS version. Only the problem comes with iOS 10. I tried your code but that doesn't help me either.Eldoneldora
Ok just checking what i can add into it. I'm also checking various blogs and finding this issue for 10.7 and 10.8Mauramauralia
Yes, exactly. When I initially tested this, it did work in iOS 10 beta 1, 2 and 3. But later, it surprisingly doesn't work since the arrival of iOS 10 beta 7.Eldoneldora
P
1

I had the same problem in my augmented reality application and finally solved it by using AVFoundation framework instead of UIImagePickerController. It seems that cameraViewTransform no longer works on iOS 10.

The code below worked for me. Add the function to your UIViewController subclass and call it.

- (BOOL) initCamera {

    AVCaptureSession *captureSesion = [[AVCaptureSession alloc] init];
    if ([captureSesion canSetSessionPreset:AVCaptureSessionPresetHigh]) {
        [captureSesion setSessionPreset:AVCaptureSessionPresetHigh];
    } else {
        return false;
    }
    AVCaptureDevice *camera = nil;
    NSArray<AVCaptureDevice*>* devices = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    // Select back camera
    for (AVCaptureDevice *device in devices) {
        if ([device position]==AVCaptureDevicePositionBack) {
            camera = device;
            break;
        }
    }
    if (camera == nil) {
        // Back camera not found.
        return false;
    }

    AVCaptureStillImageOutput *imageOutput = [[AVCaptureStillImageOutput alloc]init];
    [imageOutput setOutputSettings: @{AVVideoCodecKey: AVVideoCodecJPEG}];
    AVCaptureDeviceInput *deviceInput = [[AVCaptureDeviceInput alloc]initWithDevice:camera error: nil];

    if (![captureSesion canAddInput:deviceInput] || ![captureSesion canAddOutput:imageOutput]) {
        return false;
    }
    [captureSesion addInput:deviceInput];
    [captureSesion addOutput:imageOutput];

    AVCaptureVideoPreviewLayer *layer = [[AVCaptureVideoPreviewLayer alloc]initWithSession:captureSesion];

    // "Aspect Fill" is suitable for fullscreen camera.
    layer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    layer.frame = self.view.bounds;
    layer.connection.videoOrientation = AVCaptureVideoOrientationPortrait;

    [self.view.layer addSublayer:layer];
    [captureSesion startRunning];

    return true;
}

The most important thing is to use AVLayerVideoGravityResizeAspectFill. With this configuration, the camera view fills the container view keeping its original aspect ratio.

Don't forget to import the framework:)

#import <AVFoundation/AVFoundation.h>
Patency answered 16/9, 2016 at 14:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.