Ios 从较大的UIImage裁剪UIImage的一部分,并包括非映像部分

Ios 从较大的UIImage裁剪UIImage的一部分,并包括非映像部分,ios,uiscrollview,uiimage,ios7,crop,Ios,Uiscrollview,Uiimage,Ios7,Crop,我想我可能有一个奇怪的要求,但希望有人能帮助我。我正在使用众所周知的uicrollview+UIImageView放大和缩小图像,以及平移。这工作得很好,但我们当前的项目需要能够裁剪图像,但如果图像小于裁剪矩形,还需要在侧面包含黑色条。请参见下面的图片 我们希望捕获蓝色框中的所有内容,包括白色(白色为黑色,因为不透明设置为YES)。 这对于完全缩小的图像非常有用(白色只是UIImageView的额外空间)。 然而,当我们试图放大图像,并仅捕获该部分加上空白时,问题就出现了。 这将产生下图

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

我们希望捕获蓝色框中的所有内容,包括白色(白色为黑色,因为不透明设置为
YES
)。

这对于完全缩小的图像非常有用(白色只是UIImageView的额外空间)。

然而,当我们试图放大图像,并仅捕获该部分加上空白时,问题就出现了。

这将产生下图

我们看到的问题是,我们需要能够创建一个与裁剪矩形中的图像完全相同的图像,而不管该图像是否有一部分。另一个问题是,我们希望能够动态更改输出分辨率。纵横比为16:9,在本例中,
kMaxWidth=1136
kMaxHeight=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;
}

任何帮助都将不胜感激。

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

-(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;
}

最后我只是截图,然后剪下来。它似乎工作得很好

- (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:AfterScreenUpdate:
,而不是
RenderContext:

我使用了类似于
[self cropImage:self.image inRect:[self.scrollView convertRect:self.scrollView.bounds to View:imageView]]的函数
但是它根本不起作用。你能告诉我你得到的rect值是多少吗?有几件事。1.这需要使用
UIGraphicsBeginImageContextWithOptions
,将“不透明”设置为“是”,以显示左右两侧的黑条(这是必需的)。2.将此选项与不透明=是一起使用会导致手机崩溃,而不仅仅是应用程序崩溃。3.没有使用
kMaxWidth
kMaxHeight
来指定输出图像的大小。使用
UIGraphicsBeginImageContextWithOptions(visibleRect.size,是,scrollView.zoomScale)
有助于使
ui图像
不会导致崩溃,但是图像不是我要找的。这是屏幕的大小,在这里我只寻找裁剪矩形,它也是整个图像。