L’anteprima della fotocamera UIImagePickerController è verticale nell’app Landscape

Nella mia applicazione iPhone solo per paesaggio, lancio un UIImagePickerController per scattare una foto, ma l’immagine dal vivo visualizzata dalla fotocamera è in orientamento verticale, con uno spazio vuoto attorno ad essa. L’immagine è ruotata.

Una volta premuto il pulsante della fotocamera, l’anteprima è molto caotica, con la maggior parte dell’anteprima fuori dallo schermo e le viste non allineate correttamente.

Apple ha riconosciuto che questo è un difetto e ci sta lavorando.

La mia domanda è, qualcuno ha un work-around (legale o illegale) che mi permetterebbe di farlo funzionare ora. Non distribuirò su App Store con una correzione illegale, ma avrei un’app molto migliore per i test degli utenti – attualmente la fotocamera è praticamente inutilizzabile in orizzontale.

Allegherò un semplice progetto di test e immagini se posso.

Modifica – solo per chiarire, l’immagine che ottengo è correttamente orizzontale. Voglio che la fotocamera e l’anteprima delle UI siano a posto!


Fotocamera http://sofit.miximages.com/iphone/2zqsbpy.jpg

testo alternativo http://sofit.miximages.com/iphone/168zam0.jpg

La risposta è più ridicola di quanto tu possa pensare. Ho avuto lo stesso problema e ho trovato una soluzione in un forum da qualche parte. Passa la tua immagine presa in un metodo come questo:

// 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; } 

🙁

Non penso che tu abbia bisogno del lavoro extra per occuparti di imageRotation o dei dati EXIF. L’immagine drawInRect si occuperà di ciò automaticamente.

Quindi, è sufficiente ottenere questa dimensione o l’immagine e ridisegnarla a una nuova immagine, sarebbe sufficiente.

Non voglio ruotare l’immagine dopo l’acquisizione; Voglio che l’anteprima sia visualizzata correttamente in modalità orizzontale. Pertanto, in iOS 6, autorizzo la modalità MyNonrotatingNavigationController livello di applicazione, ma il controller della vista radice dell’app è di class MyNonrotatingNavigationController , definito come segue:

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

Quindi tutto ciò che viene mostrato all’interno di questo controller nav sarà in orientamento orizzontale (puoi farlo con qualsiasi controller di visualizzazione). Ora, quando ho bisogno di mostrare un selettore di immagini, sostituisco il controller di visualizzazione radice della finestra dell’app con uno generico che supporta la modalità verticale. Per evitare che il vecchio controller della vista radice e le sue viste vengano deallocate, mantengo i puntatori su di esse finché non sono pronto a reinserirle nella finestra dell’app.

 #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; }); }]; } 

È una specie di dolore, ma sembra funzionare sia per foto che per video. I controlli del selettore di immagini vengono mostrati in modalità verticale, ma il resto dell’app è solo orizzontale.

Ho risolto questo problema rendendo UIImagePickerController visualizzato in modalità a schermo intero, che è anche ciò che Apple consiglia per iPad.

Dalla documentazione di UIImagePickerController :

Su iPad, se si specifica un tipo di origine di UIImagePickerControllerSourceTypeCamera, è ansible presentare il selettore di immagini in modo modale (a schermo intero) o utilizzando un popover. Tuttavia, Apple consiglia di presentare l’interfaccia della fotocamera solo a schermo intero.

Avrai bisogno di impostare la visualizzazione personalizzata (con barra degli strumenti e titolo) come cameraOverlayView , inoltre dovrai impostare allowsEditing e showsCameraControls su NO da hide i controlli standard e l’anteprima. Questo è quello che ho trovato necessario in app che sto facendo (ho pensato che fosse necessario che il picker fosse in verticale, ma ho bisogno di applicare alcune modifiche dell’interfaccia utente se l’utente ruota il suo dispositivo in orizzontale).
Il codice può essere fornito se ce n’è bisogno.

PS Ci sono ancora alcuni errori nel mio codice, ma ci sto lavorando 🙂