捕捉 UIScrollView 的可见部分后裁剪图像的透明部分

Posted

技术标签:

【中文标题】捕捉 UIScrollView 的可见部分后裁剪图像的透明部分【英文标题】:Crop transparent part of the image after snaping visible part of UIScrollView 【发布时间】:2016-06-14 13:13:41 【问题描述】:

我有 UIScrollView 和 UIImageView 。您可以缩放它并裁剪可见部分。

这是我的 snap 代码:

    UIImage *visibleScrollImage = nil;

    UIGraphicsBeginImageContextWithOptions(self.scrollView.bounds.size, YES, [UIScreen mainScreen].scale);
    
        CGPoint offset = self.scrollView.contentOffset;
        CGContextTranslateCTM(UIGraphicsGetCurrentContext(), -offset.x, -offset.y);
        [self.scrollView.layer renderInContext:UIGraphicsGetCurrentContext()];
        visibleScrollImage = UIGraphicsGetImageFromCurrentImageContext();
    
    UIGraphicsEndImageContext();

    eivc.editImage = visibleScrollImage;

当图像没有占据 UIScrollView 的所有可见部分时,我不明白如何在没有 UIImageView 透明部分的情况下拍摄图像。我试图猜测上下文和偏移坐标的不同大小,但没有成功,因为我显然不了解图像、滚动视图或/和 CGContext。

以下是一些示例,我将 backgroundColor 设置为红色以显示可见性。

编辑:

现在我做了一半的解决方案 我像这样设置 imageView.frame

self.imageView.contentMode = UIViewContentModeScaleAspectFill;
        CGFloat initialImageHeight = result.size.height;
        CGFloat initialImageWidth = result.size.width;
        CGFloat height = self.scrollView.bounds.size.height;
        CGFloat width = self.scrollView.bounds.size.width;
        CGFloat frameHeight = height;
        CGFloat frameWidth = width;

        if ((initialImageHeight / initialImageWidth) > (height / width)) 
            frameHeight = width * initialImageHeight / initialImageWidth;
         else if ((initialImageHeight / initialImageWidth) < (height / width)) 
            frameWidth = height * initialImageWidth / initialImageHeight;
        

        self.imageView.frame = CGRectMake(0, 0, frameWidth, frameHeight);
        self.imageView.image = result;

我设置了 minimumZoomScale = 1.0

它可以防止图像占据不完整的滚动视图可见部分。

【问题讨论】:

【参考方案1】:

正如你的描述,我猜你的需求是enter image description here

enter image description here

第一个图像是正常的,第二个图像是缩放图像。让您感到困惑的是,在没有 imageView 透明部分的情况下拍摄图像,因此当您缩放 imageView 时,imageView 的原点和边界会随之变化。你可以截屏,然后根据imageView的坐标,计算一个rect就是imageView,拍一张短图,这张图就是你的imageView的图片,代码如下。

- (UIImage*)cropImage
    UIImage *screenImage = [UIImage imageFromView:self];
    CGFloat imageViewWidth = self.imageView.frame.size.width;
    CGFloat imageViewHeight = self.imageView.frame.size.height;

    CGRect rect;
    UIImage *clipImage;

    if (type == 1) 
        if (imageViewHeight < SCREENWIDTH) 

            rect = CGRectMake(0, SCREENHEIGHT/2-imageViewHeight/2, SCREENWIDTH, imageViewHeight);
        else

            rect = CGRectMake(0, SCREENHEIGHT/2-SCREENWIDTH/2, SCREENWIDTH, SCREENWIDTH);
        
    else if (type == 2)
        if (imageViewWidth < SCREENWIDTH) 
            rect = CGRectMake(SCREENWIDTH/2-imageViewWidth/2, SCREENHEIGHT/2-SCREENWIDTH/2, imageViewWidth, SCREENWIDTH);
        else

            rect = CGRectMake(0, SCREENHEIGHT/2-SCREENWIDTH/2, SCREENWIDTH, SCREENWIDTH);
        
    else
            rect = CGRectMake(0, SCREENHEIGHT/2-SCREENWIDTH/2, SCREENWIDTH, SCREENWIDTH);
    
    clipImage = [screenImage cropImage:screenImage inRect:rect];
    return clipImage;



+ (UIImage *) imageFromView:(UIView *)imageView 
    CGFloat scale = 1;
    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)] == YES)       
    scale = [[UIScreen mainScreen] scale];
    
    if (scale > 1) 
        UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, scale);
     else 
        UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, 2);
    

    CGContextRef context = UIGraphicsGetCurrentContext();
    [imageView.layer renderInContext: context];
    UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    return viewImage;



- (UIImage *)cropImage:(UIImage*)image inRect:(CGRect)rect

    double (^rad)(double) = ^(double deg) 
        return deg / 180.0 * M_PI;
    ;

CGAffineTransform rectTransform;
switch (image.imageOrientation) 
    case UIImageOrientationLeft:
        rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(90)), 0, -image.size.height);
        break;
    case UIImageOrientationRight:
        rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(-90)), -image.size.width, 0);
        break;
    case UIImageOrientationDown:
        rectTransform = CGAffineTransformTranslate(CGAffineTransformMakeRotation(rad(-180)), -image.size.width, -image.size.height);
        break;
    default:
        rectTransform = CGAffineTransformIdentity;
;
rectTransform = CGAffineTransformScale(rectTransform, image.scale, image.scale);

CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], CGRectApplyAffineTransform(rect, rectTransform));
UIImage *result = [UIImage imageWithCGImage:imageRef scale:image.scale orientation:image.imageOrientation];
CGImageRelease(imageRef);

return result;

【讨论】:

我得到了缩放时图像视图边界发生变化的部分。只是不知道如何正确计算。所以我尝试了你的解决方案,这里的交易它没有削减正确的矩形,它没有考虑滚动视图偏移,这里有一些例子这里有 2 个不同的可见部分12 在这两种情况下我都明白了result 和这里是一样的 1 2 结果 result 我也不明白“类型”变量的用途。

以上是关于捕捉 UIScrollView 的可见部分后裁剪图像的透明部分的主要内容,如果未能解决你的问题,请参考以下文章

如何裁剪 UIScrollView 中显示的 UIImageView 部分并将其保存到 UIImage 变量?

在 UIScrollView 问题中裁剪缩放图像

wordpress 缩略图后裁剪问题。这甚至可能吗?

UIScrollView 内的 UITableView 在 Xcode 7.0.1 中部分不可见?

在 iPhone 中裁剪后 UIImage 显示模糊

裁剪算法——多边形裁剪/文字裁剪