L’aperçu de la caméra UIImagePickerController est un portrait dans l’application paysage

Dans mon application iPhone en mode paysage, je lance un UIImagePickerController pour prendre une photo, mais l’image en direct affichée depuis l’appareil photo est en orientation portrait, avec un espace vide autour. L’image est pivotée.

Une fois le bouton de la caméra enfoncé, l’aperçu est très désordonné, la plupart de l’aperçu hors écran et les vues ne sont pas correctement alignées.

Apple a reconnu que c’est un défaut et y travaille.

Ma question est la suivante: est-ce que quelqu’un a une solution de rechange (légale ou illégale) qui me permettrait de le faire fonctionner maintenant? Je ne publierais pas sur l’App Store avec un correctif illégal, mais j’aurais une bien meilleure application pour tester les utilisateurs – actuellement, l’appareil photo est pratiquement inutilisable en paysage.

Je vais joindre un projet de test simple et des images si je peux.

Edit – juste pour clarifier, l’image que je reçois est correctement paysage. Je veux que la caméra et l’aperçu des UI soient corrects!


Caméra http://soffr.miximages.com/iphone/2zqsbpy.jpg

alt text http://soffr.miximages.com/iphone/168zam0.jpg

La réponse est plus ridicule que vous ne le pensez. J’ai eu le même problème et trouvé une solution quelque part dans un forum. Transmettez votre image prise dans une méthode comme celle-ci:

// Code from: http://discussions.apple.com/thread.jspa?messageID=7949889 - (UIImage *)scaleAndRotateImage:(UIImage *)image { int kMaxResolution = 640; // Or whatever CGImageRef imgRef = image.CGImage; CGFloat width = CGImageGetWidth(imgRef); CGFloat height = CGImageGetHeight(imgRef); CGAffineTransform transform = CGAffineTransformIdentity; CGRect bounds = CGRectMake(0, 0, width, height); if (width > kMaxResolution || height > kMaxResolution) { CGFloat ratio = width/height; if (ratio > 1) { bounds.size.width = kMaxResolution; bounds.size.height = roundf(bounds.size.width / ratio); } else { bounds.size.height = kMaxResolution; bounds.size.width = roundf(bounds.size.height * ratio); } } CGFloat scaleRatio = bounds.size.width / width; CGSize imageSize = CGSizeMake(CGImageGetWidth(imgRef), CGImageGetHeight(imgRef)); CGFloat boundHeight; UIImageOrientation orient = image.imageOrientation; switch(orient) { case UIImageOrientationUp: //EXIF = 1 transform = CGAffineTransformIdentity; break; case UIImageOrientationUpMirrored: //EXIF = 2 transform = CGAffineTransformMakeTranslation(imageSize.width, 0.0); transform = CGAffineTransformScale(transform, -1.0, 1.0); break; case UIImageOrientationDown: //EXIF = 3 transform = CGAffineTransformMakeTranslation(imageSize.width, imageSize.height); transform = CGAffineTransformRotate(transform, M_PI); break; case UIImageOrientationDownMirrored: //EXIF = 4 transform = CGAffineTransformMakeTranslation(0.0, imageSize.height); transform = CGAffineTransformScale(transform, 1.0, -1.0); break; case UIImageOrientationLeftMirrored: //EXIF = 5 boundHeight = bounds.size.height; bounds.size.height = bounds.size.width; bounds.size.width = boundHeight; transform = CGAffineTransformMakeTranslation(imageSize.height, imageSize.width); transform = CGAffineTransformScale(transform, -1.0, 1.0); transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0); break; case UIImageOrientationLeft: //EXIF = 6 boundHeight = bounds.size.height; bounds.size.height = bounds.size.width; bounds.size.width = boundHeight; transform = CGAffineTransformMakeTranslation(0.0, imageSize.width); transform = CGAffineTransformRotate(transform, 3.0 * M_PI / 2.0); break; case UIImageOrientationRightMirrored: //EXIF = 7 boundHeight = bounds.size.height; bounds.size.height = bounds.size.width; bounds.size.width = boundHeight; transform = CGAffineTransformMakeScale(-1.0, 1.0); transform = CGAffineTransformRotate(transform, M_PI / 2.0); break; case UIImageOrientationRight: //EXIF = 8 boundHeight = bounds.size.height; bounds.size.height = bounds.size.width; bounds.size.width = boundHeight; transform = CGAffineTransformMakeTranslation(imageSize.height, 0.0); transform = CGAffineTransformRotate(transform, M_PI / 2.0); break; default: [NSException raise:NSInternalInconsistencyException format:@"Invalid image orientation"]; } UIGraphicsBeginImageContext(bounds.size); CGContextRef context = UIGraphicsGetCurrentContext(); if (orient == UIImageOrientationRight || orient == UIImageOrientationLeft) { CGContextScaleCTM(context, -scaleRatio, scaleRatio); CGContextTranslateCTM(context, -height, 0); } else { CGContextScaleCTM(context, scaleRatio, -scaleRatio); CGContextTranslateCTM(context, 0, -height); } CGContextConcatCTM(context, transform); CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, width, height), imgRef); UIImage *imageCopy = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return imageCopy; } 

🙁

Je ne pense pas que vous ayez besoin du travail supplémentaire pour gérer imageRotation ou les données EXIF. Image drawInRect s’en chargera automatiquement.

Il vous suffit donc d’obtenir cette taille ou cette image et de la redessiner sur une nouvelle image, ce qui serait suffisant.

Je ne veux pas faire pivoter l’image après la capture; Je veux que l’aperçu s’affiche correctement en mode paysage. Donc, dans iOS 6, MyNonrotatingNavigationController mode portrait au niveau de l’application, mais définissez le contrôleur d’affichage de l’application sur la classe MyNonrotatingNavigationController , définie comme suit:

 @implementation MyNonrotatingNavigationController -(NSUInteger) supportedInterfaceOrientations { return UIInterfaceOrientationMaskLandscape; } @end 

Donc, tout ce qui est montré dans ce contrôleur de navigation sera en orientation paysage (vous pouvez le faire avec n’importe quel contrôleur de vue). Maintenant, lorsque j’ai besoin d’afficher un sélecteur d’image, je remplace le contrôleur d’affichage de la fenêtre de l’application par un contrôleur générique qui prend en charge le mode portrait. Pour éviter que l’ancien contrôleur de vue racine et ses vues ne soient libérées, je maintiens des pointeurs jusqu’à ce que je sois prêt à les replacer dans la fenêtre de l’application.

 #define APP_DELEGATE ((MyAppDelegate*)[[UIApplication sharedApplication] delegate]) static UIViewController *pickerContainer = nil; static UIViewController *oldRoot = nil; static UIView *holdView = nil; -(void) showPicker { ...create UIImagePickerController... oldRoot = APP_DELEGATE.window.rootViewController; holdView = [[UIView alloc] initWithFrame:APP_DELEGATE.window.bounds]; [holdView addSubview:oldRoot.view]; pickerContainer = [UIViewController new]; pickerContainer.view = [[UIView alloc] initWithFrame:APP_DELEGATE.window.bounds]; APP_DELEGATE.window.rootViewController = pickerContainer; [pickerContainer presentViewController:picker animated:YES completion:NULL]; } -(void) imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info { [pickerContainer dismissViewControllerAnimated:YES completion:^{ dispatch_async( dispatch_get_main_queue(), ^{ APP_DELEGATE.window.rootViewController = oldRoot; [APP_DELEGATE.window addSubview:oldRoot.view]; pickerContainer = nil; oldRoot = nil; holdView = nil; }); }]; } 

Une sorte de douleur, mais cela semble fonctionner à la fois pour les photos et les vidéos. Les commandes du sélecteur d’image s’affichent en mode portrait, mais le rest de l’application est uniquement en mode paysage.

J’ai résolu ce problème en faisant apparaître UIImagePickerController en mode plein écran, ce que Apple recommande également pour iPad.

De la documentation UIImagePickerController :

Sur iPad, si vous spécifiez un type de source UIImagePickerControllerSourceTypeCamera, vous pouvez présenter le sélecteur d’image de manière modale (en plein écran) ou en utilisant un popover. Toutefois, Apple vous recommande de ne présenter que l’interface de l’appareil en mode plein écran.

Vous devrez définir la vue personnalisée (avec la barre d’outils et le titre) en tant que cameraOverlayView . Vous devrez également définir allowsEditing et showsCameraControls sur NO car cela showsCameraControls les contrôles standard et l’aperçu. C’est ce que j’ai trouvé si nécessaire dans l’application que je réalise (je pense que le sélecteur doit être en mode portrait, mais j’en ai besoin pour appliquer des changements d’interface utilisateur si l’utilisateur fait pivoter son périphérique en mode paysage).
Le code peut être fourni s’il en a besoin.

PS Il y a encore des bugs dans mon code, mais je travaille dessus 🙂