1

我想我可能有一个奇怪的要求,但希望有人能提供帮助。我正在使用众所周知的UIScrollView+UIImageView来放大和缩小图像以及平移。这很好用,但我们当前的项目需要能够裁剪图像,但如果图像小于裁剪矩形,还包括侧面的黑条。请参阅下面的图片。

我们希望捕获蓝色框内的所有内容,包括白色(将是黑色,因为 opaque 设置为YES)。

这适用于完全缩小的图像(白色只是 UIImageView 的额外空间)。 在此处输入图像描述

但是,当我们尝试放大图像并仅捕获该部分以及空白区域时,就会出现问题。 在此处输入图像描述

这导致以下图像 在此处输入图像描述

我们看到的问题是我们需要能够创建一个与裁剪矩形中完全相同的图像,无论那里是否有图像的一部分。另一个问题是我们希望能够动态改变输出分辨率。纵横比为 16:9,对于本示例kMaxWidth = 1136kMaxHeight = 639,但是将来我们可能希望请求更大或更小的 16:9 分辨率。

以下是我到目前为止的功能:

- (UIImage *)createCroppedImageFromImage:(UIImage *)image {
    CGSize newRect = CGSizeMake(kMaxWidth, kMaxHeight);
    UIGraphicsBeginImageContextWithOptions(newRect, YES, 0.0);

    // 0 is the edge of the screen, to help with zooming
    CGFloat xDisplacement = ((abs(0 - imageView.frame.origin.x) * kMaxWidth) / (self.cropSize.width / self.scrollView.zoomScale) / self.scrollView.zoomScale);

    CGFloat yDisplacement = ((abs(self.cropImageView.frame.origin.y - imageView.frame.origin.y) * kMaxHeight) / (self.cropSize.height / self.scrollView.zoomScale) / self.scrollView.zoomScale);

    CGFloat newImageWidth = (self.image.size.width * kMaxWidth) / (self.cropSize.width / self.scrollView.zoomScale);
    CGFloat newImageHeight = (self.image.size.height * kMaxHeight) / (self.cropSize.height / self.scrollView.zoomScale);    
   [image drawInRect:CGRectMake(xDisplacement, 0, newImageWidth, newImageHeight)];
    UIImage *croppedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return croppedImage;
}

任何帮助将不胜感激。

4

2 回答 2

3

我最终只是截取了一个截图,然后裁剪了它。它似乎工作得很好。

- (UIImage *)cropImage {
    CGRect cropRect = self.cropOverlay.cropRect;
    UIGraphicsBeginImageContext(self.view.frame.size);

    [self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *fullScreenshot = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    CGImageRef croppedImage = CGImageCreateWithImageInRect(fullScreenshot.CGImage, cropRect);
    UIImage *crop = [[UIImage imageWithCGImage:croppedImage] resizedImage:self.outputSize interpolationQuality:kCGInterpolationHigh];
    CGImageRelease(croppedImage);
    return crop;
}

如果使用 iOS 7,您将使用drawViewHierarchyInRect:afterScreenUpdates:, 而不是renderInContext:

于 2013-10-18T03:07:49.833 回答
0

我认为图像视图的翻译矩形计算不正确。由于 UIImageView 是 UIScrollView 内的子视图,因此您应该能够通过调用[scrollView convertRect:scrollView.bounds toView:imageView];. 这将是您的图像视图的可见矩形。你现在需要做的就是裁剪它。

-(UIImage*)cropImage:(UIImage*)img inRect:(CGRect)rect{
    CGImageRef cropped = CGImageCreateWithImageInRect(img.CGImage, rect);
    UIImage *image =  [UIImage imageWithCGImage:cropped];

    CGImageRelease(cropped);
    return image;
}

编辑:是的......我忘了提到应该在(0,1)坐标空间中进行裁剪。我已经为您修改了裁剪功能,因此它会根据您提供的所有参数、UIScrollView 中的 UIImageView 和图像来裁剪图像。

-(UIImage*)cropImage:(UIImage*)image inImageView:(UIImageView*)imageView scrollView:(UIScrollView*)scrollView{
    // get visible rect from image scrollview
    CGRect visibleRect = [scrollView convertRect:scrollView.bounds toView:imageView];
    UIImage* rCroppedImage;

    CALayer* maskLayer= [[CALayer alloc] init];

    maskLayer.contents= (id)image.CGImage;
    maskLayer.frame= CGRectMake(0, 0, visibleRect.size.width, visibleRect.size.height);

    CGRect rect= CGRectMake(visibleRect.origin.x / image.size.width,
                            visibleRect.origin.y / image.size.height,
                            visibleRect.size.width / image.size.width,
                            visibleRect.size.height / image.size.height);
    maskLayer.contentsRect= rect;
    UIGraphicsBeginImageContext(visibleRect.size);

    CGContextRef context= UIGraphicsGetCurrentContext();

    [maskLayer renderInContext:context];

    rCroppedImage= UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return rCroppedImage;
}
于 2013-10-04T20:48:39.323 回答