2015-05-03 14 views
19

Si verificano problemi con il mio metodo AVCaptureVideoPreviewLayer quando si acquisisce un UIImage ritagliato dello schermo visualizzabile. Attualmente funziona, ma non emette il raccolto corretto di cui ho bisogno.Ritaglio di AVCaptureVideoPreviewLayer su un quadrato

Sto provando ad emettere un quadrato ma sembra che stia dando l'altezza e comprimendo l'immagine.

L'immagine precedente mostra la schermata LIVE e l'immagine successiva mostra l'immagine dopo aver premuto il pulsante di acquisizione. Puoi vedere che è stato modificato verticalmente per adattarsi al quadrato, ma l'altezza non è stata ritagliata verticalmente.

enter image description here

Codice Acquisizione Immagine

[stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error) { 

    if (imageSampleBuffer != NULL) { 

     NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer]; 
     [self processImage:[UIImage imageWithData:imageData]]; 

    } 
}]; 

Ritaglio codice

- (void) processImage:(UIImage *)image { //process captured image, crop, resize and rotate 

     haveImage = YES; 

    CGRect deviceScreen = _previewLayer.bounds; 
    CGFloat width = deviceScreen.size.width; 
    CGFloat height = deviceScreen.size.height; 

    NSLog(@"WIDTH %f", width); // Outputing 320 
    NSLog(@"HEIGHT %f", height); // Outputting 320 

    UIGraphicsBeginImageContext(CGSizeMake(width, width)); 
    [image drawInRect: CGRectMake(0, 0, width, width)]; 

    UIImage *smallImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    CGRect cropRect = CGRectMake(0, 0, width, width); 

    CGImageRef imageRef = CGImageCreateWithImageInRect([smallImage CGImage], cropRect); 

    CGImageRelease(imageRef); 

    [captureImageGrab setImage:[UIImage imageWithCGImage:imageRef]]; 

} 
+0

Potrebbe anche registrare la dimensione dell'immagine all'interno di 'processImage'? E anche cosa 'captureImageGrab'? È un 'UIImageView'? –

risposta

7

Anche se lo strato di anteprima è quadrato, tenere presente che l'immagine generata ancora mantiene la sua dimensione originale.

Da quello che vedo, il problema è qui:

UIGraphicsBeginImageContext(CGSizeMake(width, width)); 
[image drawInRect: CGRectMake(0, 0, width, width)]; 

hai già fatto la vostra piazza contesto con la prima linea. Hai ancora bisogno di disegnare la tua immagine nel suo formato originale, verrà ritagliata da quel contesto. Sulla seconda riga, stai forzando il disegno dell'immagine originale in un quadrato, facendolo sembrare "schiacciato".

Si dovrebbe trovare l'altezza dell'immagine giusta che mantiene il rapporto originale mentre si adatta la "larghezza". Successivamente, vorrai disegnare quell'immagine con la dimensione corretta (mantenendo il rapporto originale) nel tuo contesto quadrato. Se si desidera ritagliare il centro, modificare la posizione Y del disegno.

Qualcosa di simile a questo:

- (void) processImage:(UIImage *)image { 
    UIGraphicsBeginImageContext(CGSizeMake(width, width)); 
    CGFloat imageHeight = floorf(width/image.width * image.height); 
    CGFloat offsetY = floorf((imageHeight - width)/2.0f); 
    [image drawInRect: CGRectMake(0, -offsetY, width, imageHeight)]; 
    UIImage *smallImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    [captureImageGrab setImage:smallImage]; 
} 

Che dovrebbe farlo.

+0

@memyselfandmyiphone hai avuto il tempo di provarlo o hai già risolto il tuo problema? – Rufel

1

Guardando il codice mi sembra che si sta disegnando l'immagine in un quadrato. Questa è la parte che rimpicciolisce l'immagine senza considerare le proporzioni.

Invece, fare qualcosa di simile:

- (void) processImage:(UIImage *)image { //process captured image, crop, resize and rotate 

    haveImage = YES; 

    CGRect deviceScreen = _previewLayer.bounds; 
    CGFloat width = deviceScreen.size.width; 
    CGFloat height = deviceScreen.size.height; 

    NSLog(@"WIDTH %f", width); // Outputing 320 
    NSLog(@"HEIGHT %f", height); // Outputting 320 

    CGRect cropRect = CGRectZero; 
    if (image.size.width > image.size.height) { 
     cropRect.origin.x = (image.size.width-image.size.height)/2; 
     cropRect.size = CGSizeMake(image.size.height, image.size.height); 
    } else { 
     cropRect.origin.y = (image.size.height-image.size.width)/2; 
     cropRect.size = CGSizeMake(image.size.width, image.size.width); 
    } 
    CGImageRef croppedImage = CGImageCreateWithImageInRect(image.CGImage, cropRect); 

    UIGraphicsBeginImageContext(CGSizeMake(width, width)); 
    [[UIImage imageWithCGImage:croppedImage] drawInRect:CGRectMake(0, 0, width, width)]; 
    UIImage *smallImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    CGImageRelease(croppedImage); 

    [captureImageGrab setImage:[UIImage imageWithCGImage:smallImage.CGImage scale:image.scale orientation:image.imageOrientation]]; 
} 
+0

questo capovolge la foto? È difficile dire se funziona. – memyselfandmyiphone

+0

@memyselfandmyiphone oh si, lo fa davvero. Vedere il codice aggiornato (ho sostituito la chiamata CGContextDrawImage). –

+0

ancora girando intorno. Sembra che si stia ancora condensando. :/ – memyselfandmyiphone

1

Le proporzioni sono distorte perché l'immagine acquisita dalla fotocamera non è quadrata. Quando lo si disegna in un quadrato, verrà disegnato con proporzioni distorte. Una possibile soluzione è quella di disegnare l'immagine nel quadrato preservare le proporzioni simili:

- (void) processImage:(UIImage *)image { //process captured image, crop, resize and rotate 

    haveImage = YES; 

    CGRect deviceScreen = _previewLayer.bounds; 
    CGFloat width = deviceScreen.size.width; 
    CGFloat height = deviceScreen.size.height; 

    NSLog(@"WIDTH %f", width); // Outputing 320 
    NSLog(@"HEIGHT %f", height); // Outputting 320 

    UIGraphicsBeginImageContext(CGSizeMake(width, width)); 

    CGFloat aspect_h = image.size.height * width/image.size.width; 

    [image drawInRect: CGRectMake(0, -(aspect_h - width)/2.0, width, aspect_h)]; 

    UIImage *smallImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    CGRect cropRect = CGRectMake(0, 0, width, width); 

    CGImageRef imageRef = CGImageCreateWithImageInRect([smallImage CGImage], cropRect); 

    CGImageRelease(imageRef); 

} 

la nuova immagine sarà di larghezza larghezza. Per tale larghezza l'altezza che preserverà le proporzioni è aspect_h. Quindi, l'immagine viene spostata lungo l'asse y per centrarlo verticalmente.

Si noti che se l'app dovesse funzionare su orientamenti che non sono ritratti, è necessario un po 'più di lavoro.

Un'altra osservazione: è possibile ottenere un'immagine con una risoluzione migliore se si utilizza image.size.width come larghezza per il nuovo contesto dell'immagine.

spero che questo aiuti!

13

Hai provato a impostare videoGravity?

previewLayer = AVCaptureVideoPreviewLayer(session: captureSession) 
previewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill 
Problemi correlati