iPhone AVFoundation la orientación de la cámara

He estado tirando de los pelos tratando de conseguir la AVFoundation de la cámara para capturar una imagen con la orientación correcta (es decir, la orientación del dispositivo) pero no puedo conseguir que funcione.

He mirado tutoriales, he visto la presentación de la WWDC y he descargado el WWDC programa de ejemplo pero aun que no lo haga.

El código de mi aplicación es…

AVCaptureConnection *videoConnection = [CameraVC connectionWithMediaType:AVMediaTypeVideo fromConnections:[imageCaptureOutput connections]];
if ([videoConnection isVideoOrientationSupported])
{
    [videoConnection setVideoOrientation:[UIApplication sharedApplication].statusBarOrientation];
}

[imageCaptureOutput captureStillImageAsynchronouslyFromConnection:videoConnection
                                                completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error)
{
    if (imageDataSampleBuffer != NULL)
    {
        //NSLog(@"%d", screenOrientation);

        //CMSetAttachment(imageDataSampleBuffer, kCGImagePropertyOrientation, [NSString stringWithFormat:@"%d", screenOrientation], 0);

        NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
        UIImage *image = [[UIImage alloc] initWithData:imageData];

        [self processImage:image];
    }
}];

(processImage utiliza el mismo writeImage… como el método de la WWDC código)

y el código de la WWDC app es…

AVCaptureConnection *videoConnection = [AVCamDemoCaptureManager connectionWithMediaType:AVMediaTypeVideo fromConnections:[[self stillImageOutput] connections]];
        if ([videoConnection isVideoOrientationSupported]) {
            [videoConnection setVideoOrientation:AVCaptureVideoOrientationPortrait];
        }

[[self stillImageOutput] captureStillImageAsynchronouslyFromConnection:videoConnection
                                                             completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
                                                                 if (imageDataSampleBuffer != NULL) {
                                                                     NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
                                                                     UIImage *image = [[UIImage alloc] initWithData:imageData];                                                                 
                                                                     ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
                                                                     [library writeImageToSavedPhotosAlbum:[image CGImage]
                                                                                               orientation:(ALAssetOrientation)[image imageOrientation]
                                                                                           completionBlock:^(NSURL *assetURL, NSError *error){
                                                                                               if (error) {
                                                                                                   id delegate = [self delegate];
                                                                                                   if ([delegate respondsToSelector:@selector(captureStillImageFailedWithError:)]) {
                                                                                                       [delegate captureStillImageFailedWithError:error];
                                                                                                   }                                                                                               
                                                                                               }
                                                                                           }];
                                                                     [library release];
                                                                     [image release];
                                                                 } else if (error) {
                                                                     id delegate = [self delegate];
                                                                     if ([delegate respondsToSelector:@selector(captureStillImageFailedWithError:)]) {
                                                                         [delegate captureStillImageFailedWithError:error];
                                                                     }
                                                                 }
                                                             }];

Al principio de su código que establezca la AVOrientation el retrato que parece muy extraño, pero estoy tratando de llegar a detectar el dispositivo actual de la orientación y el uso que.

Como se puede ver he puesto [UIApplication sharedApplication]statusBarOrientation para intentar y conseguir esto, pero todavía sólo guardar las fotos en vertical.

¿Alguien puede ofrecer cualquier ayuda o consejo sobre lo que debo hacer?

Gracias!

Oliver

InformationsquelleAutor Fogmeister | 2010-09-07

11 Kommentare

  1. 45

    Bien, que me ha llevado fracking para siempre, pero yo lo he hecho!

    El trozo de código que yo estaba buscando es

    [UIDevice currentDevice].orientation;

    Esto va en como lo

    AVCaptureConnection *videoConnection = [CameraVC connectionWithMediaType:AVMediaTypeVideo fromConnections:[imageCaptureOutput connections]];
    if ([videoConnection isVideoOrientationSupported])
    {
        [videoConnection setVideoOrientation:[UIDevice currentDevice].orientation];
    }

    Y funciona perfectamente 😀

    Woop woop!

    • Bien, pensé que me había fijado, pero por desgracia yo estaba equivocado. Soluciona el problema de la visualización de la imagen en el teléfono y se guarda en la biblioteca correctamente pero cuando subido a Facebook o ver en mi equipo todavía están al revés 🙁
    • ¿Cuál fue su solución final? Me di cuenta de una rareza que tu post me ayudó con. UIDeviceOrientation y AVCaptureVideoOrientation no son idénticos. LandscapeRight y LandscapeLeft se intercambian en la enumeración. Yo estaba haciendo un largo (vertical / set retrato, si el paisaje a la izquierda / set paisaje a la izquierda) y mis fotos de paisaje fueron siempre al revés! Parece que el swap es necesaria para mantener la asignación correcta, no estoy seguro de cómo funciona, aunque.
    • Hmm. Para mí, la miniatura de la orientación en la biblioteca de fotos se gira, pero la imagen sí está bien.
    • …para volver a Desbordamiento de la Pila cuando la primera respuesta que reciben es alguien que tiene ir a por ellos por hacer una pregunta? Desbordamiento de la pila es un lugar para la gente a encontrar respuestas. No para que la gente se gritaba por la utilización incorrecta de la etiqueta. Publicar un enlace a Google en el comentario es sarcástico. Usted no puede decir que no lo es, es la definición misma. ¿Crees que si yo hubiera sabido la respuesta a mi pregunta que me han preguntado lo mismo? Dejar de tratar a las personas como son estúpidos. OK, tienes un estúpido cantidad de rep aquí, pero no abusar de ella, o piensa que le da el poder para insultar a las preguntas de otras personas.
    • Estoy teniendo el mismo problema, puede usted por favor decirme cómo lo solucionó?
    • el problema es que cuando la carga es porque UIImage tiene un indicador que le dice cómo se ha girado, probablemente en el exif… se refieren a este ASÍ que la pregunta para obtener más información de stackoverflow.com/questions/5427656/…
    • Esto salvó mi día!

  2. 14

    No es este un poco más limpia?

        AVCaptureVideoOrientation newOrientation;
        switch ([[UIDevice currentDevice] orientation]) {
        case UIDeviceOrientationPortrait:
            newOrientation = AVCaptureVideoOrientationPortrait;
            break;
        case UIDeviceOrientationPortraitUpsideDown:
            newOrientation = AVCaptureVideoOrientationPortraitUpsideDown;
            break;
        case UIDeviceOrientationLandscapeLeft:
            newOrientation = AVCaptureVideoOrientationLandscapeRight;
            break;
        case UIDeviceOrientationLandscapeRight:
            newOrientation = AVCaptureVideoOrientationLandscapeLeft;
            break;
        default:
            newOrientation = AVCaptureVideoOrientationPortrait;
        }
        [stillConnection setVideoOrientation: newOrientation];
    • Posiblemente. Esta pregunta es de tres años de edad, aunque. Ni siquiera puedo recordar la app que yo estaba escribiendo cuando le pregunté 🙂
    • Se sigue produciendo imagen de un paisaje si yo soy la captura en el dispositivo en orientación horizontal. Quiero la imagen en el modo de retrato de siempre. por favor, me sugieren.
    • Muchas gracias. Se trabajó junto con la Imagen+fixOrientation.
  3. 11

    El siguiente es de AVCam, he añadido también:

    - (void)deviceOrientationDidChange{
    
        UIDeviceOrientation deviceOrientation = [[UIDevice currentDevice] orientation];
    
        AVCaptureVideoOrientation newOrientation;
    
        if (deviceOrientation == UIDeviceOrientationPortrait){
            NSLog(@"deviceOrientationDidChange - Portrait");
            newOrientation = AVCaptureVideoOrientationPortrait;
        }
        else if (deviceOrientation == UIDeviceOrientationPortraitUpsideDown){
            NSLog(@"deviceOrientationDidChange - UpsideDown");
            newOrientation = AVCaptureVideoOrientationPortraitUpsideDown;
        }
    
        //AVCapture and UIDevice have opposite meanings for landscape left and right (AVCapture orientation is the same as UIInterfaceOrientation)
        else if (deviceOrientation == UIDeviceOrientationLandscapeLeft){
            NSLog(@"deviceOrientationDidChange - LandscapeLeft");
            newOrientation = AVCaptureVideoOrientationLandscapeRight;
        }
        else if (deviceOrientation == UIDeviceOrientationLandscapeRight){
            NSLog(@"deviceOrientationDidChange - LandscapeRight");
            newOrientation = AVCaptureVideoOrientationLandscapeLeft;
        }
    
        else if (deviceOrientation == UIDeviceOrientationUnknown){
            NSLog(@"deviceOrientationDidChange - Unknown ");
            newOrientation = AVCaptureVideoOrientationPortrait;
        }
    
        else{
            NSLog(@"deviceOrientationDidChange - Face Up or Down");
            newOrientation = AVCaptureVideoOrientationPortrait;
        }
    
        [self setOrientation:newOrientation];
    }

    Y asegúrese de agregar esto a su método init:

    NSNotificationCenter *notificationCenter = [NSNotificationCenter defaultCenter];
    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
    [notificationCenter addObserver:self
        selector:@selector(deviceOrientationDidChange) 
        name:UIDeviceOrientationDidChangeNotification object:nil];
    [self setOrientation:AVCaptureVideoOrientationPortrait];
    • No es este un poco más limpia?
    • Esta solución, junto con UIImage+fixOrientation.h soluciona el problema de la orientación por completo
  4. 4

    hay dos cosas a notar

    a) como Brian King escribió – LandscapeRight y LandscapeLeft se intercambian en la enumeración. ver AVCamCaptureManager ejemplo:

    //AVCapture and UIDevice have opposite meanings for landscape left and right (AVCapture orientation is the same as UIInterfaceOrientation)
    else if (deviceOrientation == UIDeviceOrientationLandscapeLeft)
        orientation = AVCaptureVideoOrientationLandscapeRight;
    else if (deviceOrientation == UIDeviceOrientationLandscapeRight)
        orientation = AVCaptureVideoOrientationLandscapeLeft;

    b) también Hay UIDeviceOrientationFaceUp y UIDeviceOrientationFaceDown los estados, que si se intenta establecer como el vídeo de orientación, el vídeo se producirá la grabación. Asegúrese de que usted no los uso cuando se llama a [UIDevice currentDevice].orientation !

  5. 3

    Si usted está usando AVCaptureVideoPreviewLayer puede hacer lo siguiente en el interior de su controlador de vista.

    (suponiendo que se tiene una instancia de AVCaptureVideoPreviewLayer llamado «previewLayer»)

    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
       [self.previewLayer setOrientation:[[UIDevice currentDevice] orientation]];
    }
    • AVCaptureVideoPreviewLayer setOrientation: está en desuso.
    • en el momento en que esta respuesta fue escrito, no era obsoleto.
  6. 2

    Estoy escribiendo este código en Swift en caso de ser necesario para alguien.

    Paso 1: Generar la Orientación de las notificaciones (en suviewDidLoad)

        UIDevice.currentDevice().beginGeneratingDeviceOrientationNotifications()
    NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("deviceOrientationDidChange:"), name: UIDeviceOrientationDidChangeNotification, object: nil)

    Paso 2: Tome la imagen. Aquí vamos de intercambio de orientación de videoConnection. En AVFoundation hay un pequeño cambio en la orientación especialmente para la orientación horizontal. Por lo que acaba de intercambio. Por ejemplo, vamos a cambiar de LandscapeRight a LandscapeLeft y viceversa

      func takePicture() {
    if let videoConnection = stillImageOutput!.connectionWithMediaType(AVMediaTypeVideo) {
    
        var newOrientation: AVCaptureVideoOrientation?
        switch (UIDevice.currentDevice().orientation) {
        case .Portrait:
            newOrientation = .Portrait
            break
        case .PortraitUpsideDown:
            newOrientation = .PortraitUpsideDown
            break
        case .LandscapeLeft:
            newOrientation = .LandscapeRight
            break
        case .LandscapeRight:
            newOrientation = .LandscapeLeft
            break
        default :
            newOrientation = .Portrait
            break
    
        }
        videoConnection.videoOrientation = newOrientation!
    
    
      stillImageOutput!.captureStillImageAsynchronouslyFromConnection(videoConnection) {
        (imageDataSampleBuffer, error) -> Void in
    
        let imageData = AVCaptureStillImageOutput.jpegStillImageNSDataRepresentation(imageDataSampleBuffer)
    
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) {
    
          dispatch_async(dispatch_get_main_queue()) {
    
            let image = UIImage(data: imageData!)!
            let portraitImage = image.fixOrientation()
    
    
          }
        }
    
    
      }
    }
    
      }

    NOTA: tenga en cuenta la nueva orientación de valor para el Paisaje orientaciones. Su justo el contrario. (Este es el culpable ::UHHHH)

    Paso 3: Revisión de la orientación (UIImage extensión)

    extension UIImage {
    
    func fixOrientation() -> UIImage {
    
        if imageOrientation == UIImageOrientation.Up {
            return self
        }
    
        var transform: CGAffineTransform = CGAffineTransformIdentity
    
        switch imageOrientation {
        case UIImageOrientation.Down, UIImageOrientation.DownMirrored:
            transform = CGAffineTransformTranslate(transform, size.width, size.height)
            transform = CGAffineTransformRotate(transform, CGFloat(M_PI))
            break
        case UIImageOrientation.Left, UIImageOrientation.LeftMirrored:
            transform = CGAffineTransformTranslate(transform, size.width, 0)
            transform = CGAffineTransformRotate(transform, CGFloat(M_PI_2))
            break
        case UIImageOrientation.Right, UIImageOrientation.RightMirrored:
            transform = CGAffineTransformTranslate(transform, 0, size.height)
            transform = CGAffineTransformRotate(transform, CGFloat(-M_PI_2))
            break
        case UIImageOrientation.Up, UIImageOrientation.UpMirrored:
            break
        }
    
        switch imageOrientation {
        case UIImageOrientation.UpMirrored, UIImageOrientation.DownMirrored:
            CGAffineTransformTranslate(transform, size.width, 0)
            CGAffineTransformScale(transform, -1, 1)
            break
        case UIImageOrientation.LeftMirrored, UIImageOrientation.RightMirrored:
            CGAffineTransformTranslate(transform, size.height, 0)
            CGAffineTransformScale(transform, -1, 1)
        case UIImageOrientation.Up, UIImageOrientation.Down, UIImageOrientation.Left, UIImageOrientation.Right:
            break
        }
    
        let ctx: CGContextRef = CGBitmapContextCreate(nil, Int(size.width), Int(size.height), CGImageGetBitsPerComponent(CGImage), 0, CGImageGetColorSpace(CGImage), CGImageAlphaInfo.PremultipliedLast.rawValue)!
    
        CGContextConcatCTM(ctx, transform)
    
        switch imageOrientation {
        case UIImageOrientation.Left, UIImageOrientation.LeftMirrored, UIImageOrientation.Right, UIImageOrientation.RightMirrored:
            CGContextDrawImage(ctx, CGRectMake(0, 0, size.height, size.width), CGImage)
            break
        default:
            CGContextDrawImage(ctx, CGRectMake(0, 0, size.width, size.height), CGImage)
            break
        }
    
        let cgImage: CGImageRef = CGBitmapContextCreateImage(ctx)!
    
        return UIImage(CGImage: cgImage)
    }
    
    
       }
  7. 1

    Para ello se utiliza el controlador de vista de la orientación del método. Esto funciona para mí, espero que funcione para usted.

    - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
    {
        [super willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
    
        AVCaptureConnection *videoConnection = self.prevLayer.connection;
        [videoConnection setVideoOrientation:(AVCaptureVideoOrientation)toInterfaceOrientation];
    }
  8. 1

    En Swift usted debe hacer esto:

        videoOutput = AVCaptureVideoDataOutput()
        videoOutput!.setSampleBufferDelegate(self, queue: dispatch_queue_create("sample buffer delegate", DISPATCH_QUEUE_SERIAL))
    
        if captureSession!.canAddOutput(self.videoOutput) {
            captureSession!.addOutput(self.videoOutput)
        }
    
        videoOutput!.connectionWithMediaType(AVMediaTypeVideo).videoOrientation = AVCaptureVideoOrientation.PortraitUpsideDown

    Funciona a la perfección para mí!

  9. 1

    Actualización de la orientación en la vista previa de la capa después de iniciar la sesión de captura y cada vez que se gira el dispositivo.

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        coordinator.animate(alongsideTransition: { [weak self] context in
            if let connection = self?.previewLayer?.connection, connection.isVideoOrientationSupported {
                if let orientation = AVCaptureVideoOrientation(orientation: UIDevice.current.orientation) {
                    connection.videoOrientation = orientation
                }
            }
        }, completion: nil)
        super.viewWillTransition(to: size, with: coordinator)
    }
    
    extension AVCaptureVideoOrientation {
        init?(orientation: UIDeviceOrientation) {
            switch orientation {
            case .landscapeRight: self = .landscapeLeft
            case .landscapeLeft: self = .landscapeRight
            case .portrait: self = .portrait
            case .portraitUpsideDown: self = .portraitUpsideDown
            default: return nil
            }
        }
    }
  10. 0

    También puede crear un intermedio CIImage, y apoderarse de las propiedades diccionario

    NSDictionary *propDict = [aCIImage properties];
    NSString *orientString = [propDict objectForKey:kCGImagePropertyOrientation];

    Y Transformar en consecuencia 🙂

    Me encanta lo fácil que es acceder a todo esto los metadatos de la imagen en iOS5!

  11. -1

    Cómo utilizar con AVCaptureFileOutput ?

    - (void)detectVideoOrientation:(AVCaptureFileOutput *)captureOutput {
        for(int i = 0; i < [[captureOutput connections] count]; i++) {
            AVCaptureConnection *captureConnection = [[captureOutput connections] objectAtIndex:i];
            if([captureConnection isVideoOrientationSupported]) {
                [captureConnection setVideoOrientation:[[UIDevice currentDevice] orientation]];
            }
        }
    }
    • Gracias, voy a ir mañana por la noche. No tendrá acceso a mi MBP hasta entonces.

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea