裁剪AVCaptureVideoPreviewLayer输出到一个正方形
抓取可视屏幕的裁剪UIImage时,遇到AVCaptureVideoPreviewLayer方法问题。 目前它正在工作,但没有输出我需要的正确作物。
我正在尝试输出一个正方形,但它(按其外观)似乎正在给出完整的高度并压缩图像。
之前的图像显示实时屏幕和后图像显示图像一旦捕获button已被按下。 你可以看到它已经垂直改变,以适应广场,但高度没有被垂直裁剪。
捕获图像代码
[stillImageOutput captureStillImageAsynchronouslyFromConnection:videoConnection completionHandler: ^(CMSampleBufferRef imageSampleBuffer, NSError *error) { if (imageSampleBuffer != NULL) { NSData *imageData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageSampleBuffer]; [self processImage:[UIImage imageWithData:imageData]]; } }];
裁剪代码
- (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]]; }
即使预览图层是正方形,请记住生成的静态图像保持其原始大小。
从我所看到的问题来看:
UIGraphicsBeginImageContext(CGSizeMake(width, width)); [image drawInRect: CGRectMake(0, 0, width, width)];
你已经把你的上下文与第一行一致。 您仍然需要以原始格式绘制您的图像,它将被该上下文剪切。 在第二行,你迫使原始图像在一个正方形的绘制,从而使它看起来“挤压”。
你应该find正确的图像高度,保持原来的比例,同时适合你的“宽度”。 接下来,您将需要在正方形上下文中以正确尺寸(保持原始比例)绘制该图像。 如果要剪切中心,请更改绘图的Y位置。
类似的东西:
- (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]; }
这应该做到这一点。
你有没有尝试设置video重力?
previewLayer = AVCaptureVideoPreviewLayer(session: captureSession) previewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
看看代码,在我看来,你正在将图像绘制成方形。 这是不考虑纵横比缩小图像的部分。
相反,做这样的事情:
- (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]]; }
由于相机拍摄的图像不是正方形,所以宽高比失真。 当绘制成一个正方形时,它将被画出一个畸变的高宽比。 一个可能的解决scheme是将图像绘制到保持宽高比的方形,如下所示:
- (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); }
新的图像将是宽度宽度 。 对于这个宽度来说,保持长宽比的高度是aspect_h 。 然后,图像沿着y轴移动以垂直居中。
请注意,如果您的应用程序要在不是纵向的方向上工作,则需要做更多的工作。
另一种观察:如果使用image.size.width作为新图像上下文的宽度,则可以获得更好的分辨率图像。
希望这可以帮助!
- AVCam保存全屏捕获的图像
- 如何在iOS 9中通过幻灯片和拆分视图使用AVCaptureSession?
- setPreferredHardwareSampleRate不起作用
- AVCaptureSession旋转| 定位同时传输video
- 以与预览图层相匹配的大小导出AVCaptureSessionvideo
- AVCaptureSession和AVCaptureMovieFileOutput帧时间戳
- 会话重启后,AVCapture会话缓慢启动
- 录制video/audio时播放系统声音
- 获取AvCaptureVideoDataOutput可用的实际NSStringVideoCVPixelFormatTypes