根据UIPinch缩放图像

13

我非常困惑如何完成我需要的内容!非常感谢任何帮助!我有一个透明图像覆盖层,下面有另一张图片,上面附着有UIPanGestureRecognizer和UIPinchGestureRecognizer手势。顶部图像有一个完全透明的中间部分,作为“玻璃”视图。我正在尝试基于平移和缩放将底部图像裁剪到“玻璃”部分。 (请参见下面的图像以了解我在说什么)我已经成功地处理了平移裁剪,但在应用缩放时裁剪它时出现问题。

我没有使用snapshotViewAfterScreenUpdates。

这是我目前的代码:

 UIImage *snapshotImage;

/* draw the image of all the views below our view */
UIGraphicsBeginImageContextWithOptions(self.pendantImageView.bounds.size, NO, 0);
BOOL successfulDrawHierarchy = [self.pendantImageView drawViewHierarchyInRect:self.pendantImageView.bounds afterScreenUpdates:YES];
if ( successfulDrawHierarchy ) {
    snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
} else {
    NSLog(@"drawViewHierarchyInRect:afterScreenUpdates: failed - there's nothing to draw...");
}
UIGraphicsEndImageContext();
UIImage *croppedImage;
if ( successfulDrawHierarchy ) {

    /* calculate the coordinates of the rectangle we're interested in within the returned image */
    CGRect cropRect = CGRectOffset(pendantFrame, - self.pendantImageView.frame.origin.x, - self.pendantImageView.frame.origin.y);

    /* draw the cropped section with a clipping region */
    UIGraphicsBeginImageContextWithOptions(cropRect.size, YES, 0);
    CGContextRef context = UIGraphicsGetCurrentContext();
    CGContextClipToRect(context, CGRectMake(0, 0, cropRect.size.width, cropRect.size.height));
    CGRect targetRectangeForCrop = CGRectMake(-cropRect.origin.x, -cropRect.origin.y, snapshotImage.size.width, snapshotImage.size.height);
    [snapshotImage drawInRect:targetRectangeForCrop];
    croppedImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();  
}

pendantImageView是底部的imageView,pendantFrame是我尝试裁剪到的区域的中间坐标。

提前感谢!

将图像裁剪到中间区域


嗨,我的回答有帮助到你吗? - OlDor
@OlDor 你好!抱歉我没有及时回复。这并不是我所询问的内容。我想我的问题表述可能不够清楚,我将进行修改。感谢您作为唯一一位尝试帮助我的人。 - gikygik
2个回答

3

我不确定我是否正确理解了你的意思,但这是我的结果:

(点击视频观看完整版本)

演示版计数页面 alpha

注:该gif图片可能需要加载一段时间。

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    UIImageView *theImageView = [UIImageView new];
    [self.view addSubview:theImageView];
    theImageView.image = [UIImage imageNamed:@"image1.jpg"];
    theImageView.frame = self.view.frame;
    theImageView.userInteractionEnabled = YES;
    theImageView.alpha = 0.6;

    UIImageView *thePanImageView = [UIImageView new];
    [self.view addSubview:thePanImageView];
    thePanImageView.frame = CGRectMake(0, 0, 100, 100);
    thePanImageView.center = CGPointMake(theImageView.frame.size.width/2, theImageView.frame.size.height/2);
    thePanImageView.image = [self screenshotFromRect:thePanImageView.frame fromView:theImageView];
    thePanImageView.userInteractionEnabled = YES;
    thePanImageView.layer.cornerRadius = thePanImageView.frame.size.width/2;
    thePanImageView.clipsToBounds = YES;
    thePanImageView.theWeakObject = theImageView;
    {
        UIPanGestureRecognizer *thePanGesture = [UIPanGestureRecognizer new];
        [thePanGesture addTarget:self action:@selector(handlePanGesture:)];
        [thePanImageView addGestureRecognizer:thePanGesture];

        UIPinchGestureRecognizer *thePinchGesture = [UIPinchGestureRecognizer new];
        [thePinchGesture addTarget:self action:@selector(handlePinchGesture:)];
        [thePanImageView addGestureRecognizer:thePinchGesture];
    }
}

- (void)handlePanGesture:(UIPanGestureRecognizer *)thePanGesture
{
    UIImageView *thePanImageView = (id)thePanGesture.view;

    UIImageView *theImageView = thePanImageView.theWeakObject;
    thePanImageView.center = [thePanGesture locationInView:theImageView];

    thePanImageView.image = [self screenshotFromRect:thePanImageView.frame fromView:theImageView];
}

- (void)handlePinchGesture:(UIPinchGestureRecognizer *)thePinchGesture
{
    UIImageView *thePanImageView = (id)thePinchGesture.view;
    static CGRect theInitialFrame;
    if (thePinchGesture.state == UIGestureRecognizerStateBegan)
    {
        theInitialFrame = thePanImageView.frame;
    }
    else
    {
        CGRect theFrame = theInitialFrame;
        theFrame.size.width *= thePinchGesture.scale;
        theFrame.size.height *= thePinchGesture.scale;
        thePanImageView.frame = theFrame;
    }

    thePanImageView.layer.cornerRadius = thePanImageView.frame.size.width/2;

    UIImageView *theImageView = thePanImageView.theWeakObject;
    thePanImageView.center = [thePinchGesture locationInView:theImageView];

    thePanImageView.image = [self screenshotFromRect:thePanImageView.frame fromView:theImageView];
}

- (UIImage * __nonnull)screenshotFromRect:(CGRect)theRect fromView:(UIView * __nonnull)theView;
{
    if (!theView)
    {
        abort();
    }
    if (theRect.size.height < 1 || theRect.size.width < 1)
    {
        abort();
    }

    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)])
    {
        UIGraphicsBeginImageContextWithOptions(theRect.size, YES, [UIScreen mainScreen].scale);
    }
    else
    {
        UIGraphicsBeginImageContext(theRect.size);
    }

    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextTranslateCTM(ctx, -theRect.origin.x, -theRect.origin.y);
    [theView.layer renderInContext:ctx];

    UIImage *snapshotImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    return snapshotImage;
}

编辑:

以上解决方案在CPU方面效率低下,因为它每次移动视图时都会截屏。

一个更加高效的方法是创建一个额外的UIImageView,并将其简单地移动到thePanImageView内部。

代码如下:

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    UIImageView *theImageView = [UIImageView new];
    [self.view addSubview:theImageView];
    theImageView.image = [UIImage imageNamed:@"image1.jpg"];
    theImageView.frame = self.view.frame;
    theImageView.userInteractionEnabled = YES;
    theImageView.alpha = 0.6;

    UIImageView *thePanImageView = [UIImageView new];
    [self.view addSubview:thePanImageView];
    thePanImageView.frame = CGRectMake(0, 0, 100, 100);
    thePanImageView.center = CGPointMake(theImageView.frame.size.width/2, theImageView.frame.size.height/2);
    thePanImageView.userInteractionEnabled = YES;
    thePanImageView.layer.cornerRadius = thePanImageView.frame.size.width/2;
    thePanImageView.clipsToBounds = YES;
    thePanImageView.layer.borderColor = [UIColor redColor].CGColor;
    thePanImageView.layer.borderWidth = 1;
    thePanImageView.theWeakObject = theImageView;
    {
        UIPanGestureRecognizer *thePanGesture = [UIPanGestureRecognizer new];
        [thePanGesture addTarget:self action:@selector(handlePanGesture:)];
        [thePanImageView addGestureRecognizer:thePanGesture];

        UIPinchGestureRecognizer *thePinchGesture = [UIPinchGestureRecognizer new];
        [thePinchGesture addTarget:self action:@selector(handlePinchGesture:)];
        [thePanImageView addGestureRecognizer:thePinchGesture];

        UIImageView *theExtraImageView = [UIImageView new];
        [thePanImageView addSubview:theExtraImageView];
        theExtraImageView.frame = CGRectMake(-thePanImageView.frame.origin.x, -thePanImageView.frame.origin.y, theImageView.frame.size.width, theImageView.frame.size.height);
        theExtraImageView.image = theImageView.image;
    }
}

- (void)handlePanGesture:(UIPanGestureRecognizer *)thePanGesture
{
    UIImageView *thePanImageView = (id)thePanGesture.view;

    UIImageView *theImageView = thePanImageView.theWeakObject;
    thePanImageView.center = [thePanGesture locationInView:theImageView];

    UIImageView *theExtraImageView = thePanImageView.subviews.firstObject;
    theExtraImageView.frame = CGRectMake(-thePanImageView.frame.origin.x, -thePanImageView.frame.origin.y, theExtraImageView.frame.size.width, theExtraImageView.frame.size.height);
}

- (void)handlePinchGesture:(UIPinchGestureRecognizer *)thePinchGesture
{
    UIImageView *thePanImageView = (id)thePinchGesture.view;
    static CGRect theInitialFrame;
    if (thePinchGesture.state == UIGestureRecognizerStateBegan)
    {
        theInitialFrame = thePanImageView.frame;
    }
    else
    {
        CGRect theFrame = theInitialFrame;
        theFrame.size.width *= thePinchGesture.scale;
        theFrame.size.height *= thePinchGesture.scale;
        thePanImageView.frame = theFrame;
    }

    thePanImageView.layer.cornerRadius = thePanImageView.frame.size.width/2;

    UIImageView *theImageView = thePanImageView.theWeakObject;
    thePanImageView.center = [thePinchGesture locationInView:theImageView];

    UIImageView *theExtraImageView = thePanImageView.subviews.firstObject;
    theExtraImageView.frame = CGRectMake(-thePanImageView.frame.origin.x, -thePanImageView.frame.origin.y, theExtraImageView.frame.size.width, theExtraImageView.frame.size.height);
}

注意:

theWeakObject 是我自己添加到 NSObject 的自定义属性。我这样做是因为我比较懒,不想创建全局可见的 @property


0

你应该问如何使用掩码输出图像!这是解决方案的链接:

CGContextClipToMask 返回空白图像

你需要更改:

CGContextClipToRect(context, CGRectMake(0, 0, cropRect.size.width, cropRect.size.height));

转换成类似于:

CGContextClipToMask(context, CGRectMake(0, 0, cropRect.size.width, cropRect.size.height), maskImage); 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接