我有一個使用AV基礎的照片應用程序。我使用AVCaptureVideoPreviewLayer設置了一個預覽圖層,該圖層佔據了屏幕的上半部分。所以當用戶試圖拍攝他們的照片時,他們只能看到屏幕上半部分所看到的內容。裁剪捕獲的圖像完全相同,它看起來在AVCaptureVideoPreviewLayer
這個效果很好,但是當用戶實際拍攝照片並嘗試將照片設置爲圖層內容時,圖像會失真。我做了研究,並意識到我需要裁剪圖像。
我想要做的就是裁剪完整捕捉的圖像,這樣所有剩下的就是用戶最初可以在屏幕上半部分看到的東西。
我已經能夠做到這一點,但我通過輸入手動CGRect值來做到這一點,它仍然看起來不完美。必須有一個更簡單的方法來做到這一點。
我已經從字面上看過去兩天關於裁剪圖像的堆棧溢出的每一篇文章,沒有任何工作。
必須有一種以編程方式裁剪捕獲圖像的方法,以便最終圖像與預覽圖層中最初看到的完全相同。
這裏是我的viewDidLoad中實現:
- (void)viewDidLoad
{
[super viewDidLoad];
AVCaptureSession *session =[[AVCaptureSession alloc]init];
[session setSessionPreset:AVCaptureSessionPresetPhoto];
AVCaptureDevice *inputDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *error = [[NSError alloc]init];
AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:inputDevice error:&error];
if([session canAddInput:deviceInput])
[session addInput:deviceInput];
CALayer *rootLayer = [[self view]layer];
[rootLayer setMasksToBounds:YES];
_previewLayer = [[AVCaptureVideoPreviewLayer alloc]initWithSession:session];
[_previewLayer setFrame:CGRectMake(0, 0, rootLayer.bounds.size.width, rootLayer.bounds.size.height/2)];
[_previewLayer setVideoGravity:AVLayerVideoGravityResizeAspectFill];
[rootLayer insertSublayer:_previewLayer atIndex:0];
_stillImageOutput = [[AVCaptureStillImageOutput alloc] init];
[session addOutput:_stillImageOutput];
[session startRunning];
}
這裏是運行時,用戶按下按鈕,拍攝照片的代碼:
-(IBAction)stillImageCapture {
AVCaptureConnection *videoConnection = nil;
for (AVCaptureConnection *connection in _stillImageOutput.connections){
for (AVCaptureInputPort *port in [connection inputPorts]){
if ([[port mediaType] isEqual:AVMediaTypeVideo]){
videoConnection = connection;
break;
}
}
if (videoConnection) {
break;
}
}
NSLog(@"about to request a capture from: %@", _stillImageOutput);
[_stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
if(imageDataSampleBuffer) {
NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
UIImage *image = [[UIImage alloc]initWithData:imageData];
CALayer *subLayer = [CALayer layer];
subLayer.frame = _previewLayer.frame;
image = [self rotate:image andOrientation:image.imageOrientation];
//Below is the crop that is sort of working for me, but as you can see I am manually entering in values and just guessing and it still does not look perfect.
CGRect cropRect = CGRectMake(0, 650, 3000, 2000);
CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], cropRect);
subLayer.contents = (id)[UIImage imageWithCGImage:imageRef].CGImage;
subLayer.frame = _previewLayer.frame;
[_previewLayer addSublayer:subLayer];
}
}];
}
@ user3117509這個答案應有的點,請接受吧! – Daniel
和@Cabus你不旋轉圖像。我用下面的代碼做到了這一點 'UIImage * croppedImage = [UIImage imageWithCGImage:imageRef]; UIGraphicsBeginImageContext(croppedImage.size);我們可以通過下面的例子來說明如何使用裁剪圖像來裁剪圖像:裁剪圖像CGImage:縮放:1.0方向:UIImageOrientationRight] drawInRect:CGRectMake(0,0,croppedImage.size.height,croppedImage.size.width)]; UIImage * rotatedCroppedImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();' – Daniel