사진을 찍고 있습니다. 사용자가 버튼을 눌러 사진을 찍을 때 과 같은 글로벌 NSString 변수를 self.hasUserTakenAPhoto
으로 설정합니다. 후방 카메라를 사용할 때 완벽하게 100 % 작동합니다. 그러나 앞면 카메라를 사용할 때만 약 50 %의 시간이 걸리며 그 이유는 모르겠습니다.전체 변수가 충분히 빠르게 업데이트되지 않습니다.
아래 코드는 중요한 코드와 기능에 대한 간단한 설명입니다.
여기 내 viewDidLoad에 있습니다 :
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.topHalfView.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height/2);
self.takingPhotoView.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height);
self.afterPhotoView.frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height);
self.bottomHalfView.frame = CGRectMake(0, 240, self.view.bounds.size.width, self.view.bounds.size.height/2);
PFFile *imageFile = [self.message objectForKey:@"file"];
NSURL *imageFileURL = [[NSURL alloc]initWithString:imageFile.url];
imageFile = nil;
self.imageData = [NSData dataWithContentsOfURL:imageFileURL];
imageFileURL = nil;
self.topHalfView.image = [UIImage imageWithData:self.imageData];
//START CREATING THE SESSION
self.session =[[AVCaptureSession alloc]init];
[self.session setSessionPreset:AVCaptureSessionPresetPhoto];
self.inputDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error;
self.deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:self.inputDevice error:&error];
if([self.session canAddInput:self.deviceInput])
[self.session addInput:self.deviceInput];
_previewLayer = [[AVCaptureVideoPreviewLayer alloc]initWithSession:_session];
self.rootLayer = [[self view]layer];
[self.rootLayer setMasksToBounds:YES];
[_previewLayer setFrame:CGRectMake(0, 240, self.rootLayer.bounds.size.width, self.rootLayer.bounds.size.height/2)];
[_previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
[self.rootLayer insertSublayer:_previewLayer atIndex:0];
self.videoOutput = [[AVCaptureVideoDataOutput alloc] init];
self.videoOutput.videoSettings = @{ (NSString *)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32BGRA) };
[self.session addOutput:self.videoOutput];
dispatch_queue_t queue = dispatch_queue_create("MyQueue", NULL);
[self.videoOutput setSampleBufferDelegate:self queue:queue];
[_session startRunning];
}
나는 기본적으로 세션을 생성 한 후 실행을 시작 //START CREATING THE SESSION
의 코멘트를 남겼 viewDidLoad
시작의 중요한 부분. 이 뷰 컨트롤러를 AVCaptureVideoDataOutputSampleBufferDelegate
으로 설정 했으므로 세션이 시작되면 곧 아래 메서드가 호출되기 시작합니다.
- (void)captureOutput:(AVCaptureOutput *)captureOutput
didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer
fromConnection:(AVCaptureConnection *)connection
{
//Sample buffer data is being sent, but don't actually use it until self.hasUserTakenAPhoto has been set to YES.
NSLog(@"Has the user taken a photo?: %@", self.hasUserTakenAPhoto);
if([self.hasUserTakenAPhoto isEqualToString:@"YES"]) {
//Now that self.hasUserTakenAPhoto is equal to YES, grab the current sample buffer and use it for the value of self.image aka the captured photo.
self.image = [self imageFromSampleBuffer:sampleBuffer];
}
}
이 코드는 매 초마다 카메라에서 비디오 출력되고 있지만 실제로 self.hasUserTakenAPhoto
때까지 그것으로 아무것도하지 않는 것은 YES
같다. 그 YES
의 문자열 값이되면, 그때 self.hasUserTakenAPhoto
실제로 YES
로 설정되어있는 경우 그래서, 여기에 카메라에서 현재 sampleBuffer
를 사용하고 self.image
라는 내 전역 변수 안에 넣습니다.
다음은 사용자가 버튼을 눌러 사진을 찍을 때 호출되는 IBAction 코드입니다. 그래서 기본적으로 viewDidLoad
방법이 실행되고 세션이 시작되고 세션이 카메라가에보고 모두를 보내는 self.hasUserTakenAPhoto = @"YES";
-(IBAction)stillImageCapture {
self.hasUserTakenAPhoto = @"YES";
[self.session stopRunning];
if(self.inputDevice.position == 2) {
self.image = [self selfieCorrection:self.image];
} else {
self.image = [self rotate:UIImageOrientationRight];
}
CGFloat widthToHeightRatio = _previewLayer.bounds.size.width/_previewLayer.bounds.size.height;
CGRect cropRect;
// Set the crop rect's smaller dimension to match the image's smaller dimension, and
// scale its other dimension according to the width:height ratio.
if (self.image.size.width < self.image.size.height) {
cropRect.size.width = self.image.size.width;
cropRect.size.height = cropRect.size.width/widthToHeightRatio;
} else {
cropRect.size.width = self.image.size.height * widthToHeightRatio;
cropRect.size.height = self.image.size.height;
}
// Center the rect in the longer dimension
if (cropRect.size.width < cropRect.size.height) {
cropRect.origin.x = 0;
cropRect.origin.y = (self.image.size.height - cropRect.size.height)/2.0;
NSLog(@"Y Math: %f", (self.image.size.height - cropRect.size.height));
} else {
cropRect.origin.x = (self.image.size.width - cropRect.size.width)/2.0;
cropRect.origin.y = 0;
float cropValueDoubled = self.image.size.height - cropRect.size.height;
float final = cropValueDoubled/2;
finalXValueForCrop = final;
}
CGRect cropRectFinal = CGRectMake(cropRect.origin.x, finalXValueForCrop, cropRect.size.width, cropRect.size.height);
CGImageRef imageRef = CGImageCreateWithImageInRect([self.image CGImage], cropRectFinal);
UIImage *image2 = [[UIImage alloc]initWithCGImage:imageRef];
self.image = image2;
CGImageRelease(imageRef);
self.bottomHalfView.image = self.image;
if ([self.hasUserTakenAPhoto isEqual:@"YES"]) {
[self.takingPhotoView setHidden:YES];
self.image = [self screenshot];
[_afterPhotoView setHidden:NO];
}
}
:이 코드를 실행하지만 정말 중요한 것은 모든이의 첫 번째 문이 때 많이 발생 captureOutput
메서드를 호출 한 다음 사용자가 "사진 찍기"버튼을 누르면 문자열 값 을 YES
으로 설정하고 세션이 중지되고 self.hasUserTakenAPhoto
이 예와 같으므로 captureOutput
메서드는 마지막 카메라 버퍼 나를 위해 self.image
개체에.
내가 뒤에서 카메라를 사용할 때 100 %의 시간 동안 작동한다고 말했기 때문에 나는 이것을 이해할 수 없다. 그러나 앞면 카메라를 사용할 때 시간의 50 % 만 작동합니다.
나는 카메라에 직면 ront를 사용하는 경우 self.hasUserTakenAPhoto
이 충분히 빨리 YES
에 업데이트되지 않는다는 사실까지 문제를 좁혀, 당신은 내 두번째 코드에서 보면 나는 그것이 NSLog(@"Has the user taken a photo?: %@", self.hasUserTakenAPhoto);
의 문이 게시 때문에 나는 알고있다.
올바르게 작동하고 사용자가 방금 세션을 중지하는 사진을 캡처하기 위해 버튼을 누르면 방금 NSLog(@"Has the user taken a photo?: %@", self.hasUserTakenAPhoto);
을 실행하면 올바른 값인 YES로 인쇄됩니다.
그러나 제대로 실행되지 않고 충분히 빠르게 업데이트되지 않으면 마지막으로 실행될 때 여전히 null
값으로 로그에 인쇄됩니다.
왜 self.hasUserTakenAPhoto
에 대한 아이디어가 전면 카메라를 사용하여 50 %의 시간 동안 충분히 빠르게 업데이트되지 않습니까? 우리가 그걸 알아 내지 못하더라도, 그건 중요하지 않습니다. 그저 다른 해결책을 찾아야합니다.
도움 주셔서 감사합니다.
감사를 추가합니다. 내 콜백은 무엇입니까? – user3344977
방금 콜백 메소드를 나열하는 대답을 업데이트했습니다. –
그렇다면 올바르게 이해한다면, 두 번째 코드에서 captureOutput이라는 메서드를 공유 했으므로 CFRunLoopRun(); 마지막 2 개의 중괄호 사이에 정확한? – user3344977