【问题标题】:When using avfoundation - crop visible portion of captured image represented in display layer使用 avfoundation 时 - 裁剪显示层中表示的捕获图像的可见部分
【发布时间】:2014-01-22 07:58:30
【问题描述】:

我正在使用PBJVision 库来捕获图像。

实际上它使用的是 AVFoundation。

我将相机设置为使用以下选项

    PBJVision *camera = [[PBJVision alloc] init];
    self.camera = camera;
    self.camera.delegate = self;
    [self.camera setCameraMode:PBJCameraModePhoto];
    [self.camera setCameraDevice:PBJCameraDeviceFront];
    [self.camera setCameraOrientation:PBJCameraOrientationPortrait];
    [self.camera setFocusMode:PBJFocusModeAutoFocus];
    [self.camera setPresentationFrame:self.previewView.frame];
    [self.camera previewLayer].frame = self.previewView.bounds;

    [self.camera previewLayer].videoGravity = AVLayerVideoGravityResizeAspectFill;

    [self.previewView.layer addSublayer:[self.camera previewLayer]];

由于预览层重力设置为AVLayerVideoGravityResizeAspectFill,因此捕获的图像与预览图像不同。

如何根据视频重力进行裁剪?

【问题讨论】:

    标签: ios objective-c avfoundation avcapturesession


    【解决方案1】:

    基于 Erica Sadun 的优秀 Cookbook,将下面的代码添加到您的视图控制器将允许您这样做
    UIImage *newImage = [self.applyAspectFillImage: image InRect: self.previewView.bounds];

    您可以通过使用原始照片图像的较小边缘(宽度或高度)来调整目标矩形的大小来获得最大图像尺寸。

    CGFloat scaleW = image.size.width / previewView.bounds.size.width;
    CGRect destRect = CGRectMake(0, 0, image.size.width, preview.bounds.size.height * scaleW);
    UIImage *newImage = [self.applyAspectFillImage: image InRect: destRect];
    

    代码:

    CGRect CGRectCenteredInRect(CGRect rect, CGRect mainRect)
    {
        CGFloat xOffset = CGRectGetMidX(mainRect)-CGRectGetMidX(rect);
        CGFloat yOffset = CGRectGetMidY(mainRect)-CGRectGetMidY(rect);
        return CGRectOffset(rect, xOffset, yOffset);
    }
    
    
    // Calculate the destination scale for filling
    CGFloat CGAspectScaleFill(CGSize sourceSize, CGRect destRect)
    {
        CGSize destSize = destRect.size;
        CGFloat scaleW = destSize.width / sourceSize.width;
        CGFloat scaleH = destSize.height / sourceSize.height;
        return MAX(scaleW, scaleH);
    }
    
    
    CGRect CGRectAspectFillRect(CGSize sourceSize, CGRect destRect)
    {
        CGSize destSize = destRect.size;
        CGFloat destScale = CGAspectScaleFill(sourceSize, destRect);
        CGFloat newWidth = sourceSize.width * destScale;
        CGFloat newHeight = sourceSize.height * destScale;
        CGFloat dWidth = ((destSize.width - newWidth) / 2.0f);
        CGFloat dHeight = ((destSize.height - newHeight) / 2.0f);
        CGRect rect = CGRectMake (dWidth, dHeight, newWidth, newHeight);
        return rect;
    }
    
    
    
    - (UIImage *) applyAspectFillImage: (UIImage *) image InRect: (CGRect) bounds
    {
        CGRect destRect;
    
        UIGraphicsBeginImageContext(bounds.size);
        CGRect rect = CGRectAspectFillRect(image.size, bounds);
        destRect = CGRectCenteredInRect(rect, bounds);
    
        [image drawInRect: destRect];
        UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
        return newImage;
    
    }
    

    【讨论】:

    • 假设我有一个委托调用的方法,我该如何使用它:-(void)vision:(PBJVision *)vision capturePhoto:(NSDictionary *)photoDict error:(NSError *)error { UIImage *image = [photoDict objectForKey:PBJVisionPhotoImageKey]; if (image) { // 根据预览层裁剪图像 } }
    • 抱歉缩进不好
    • 没错。 Erica 将该方法作为 UIImage 上的类别,这更有意义。我不想让答案复杂化。
    • 假设您将方法添加到 ViewController,UIImage *newImage = [self.applyAspectFillImage: image InRect: self.previewView.bounds];
    • 将返回根据纵横比和内容模式裁剪的全分辨率图像,还是将其裁剪为视图的大小(不需要后者:) 想要正确裁剪全尺寸)。可以链接图书馆吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-18
    • 1970-01-01
    • 2015-07-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多