将点从图像转换为UIImageView点,contentMode-aware

时间:2011-08-27 19:00:33

标签: iphone objective-c ios cocoa-touch

假设我有一个图像(例如1024 x 768像素),它以UIImageView(例如300 x 300像素)显示。 现在,我想从图像中转换一个点,例如一个人的鼻子(x:500,y:600)的位置到UIImageView上的相应点,并考虑了其contentMode。

如果在UIViewContentModeScaleToFill中修复了contentMode,转换将很容易。但如果它是UIViewContentModeScaleAspectFit,事情会变得更加复杂。

有没有一种优雅的方法来实现这一目标?我真的不想为每一个contentMode计算出来(我认为超过10个。)

谢谢!

4 个答案:

答案 0 :(得分:31)

今天,我有一些空余时间来解决这个问题并将其发布到GitHub上:UIImageView-GeometryConversion

这是UIImageView上的一个类别,它提供了从图像转换点和视角以查看坐标并尊重所有13种不同内容模式的方法。

希望你喜欢它!

答案 1 :(得分:10)

这是我的快速解决方案:

- (CGPoint)convertPoint:(CGPoint)sourcePoint fromContentSize:(CGSize)sourceSize {
    CGPoint targetPoint = sourcePoint;
    CGSize  targetSize  = self.bounds.size;

    CGFloat ratioX = targetSize.width / sourceSize.width;
    CGFloat ratioY = targetSize.height / sourceSize.height;

    if (self.contentMode == UIViewContentModeScaleToFill) {
        targetPoint.x *= ratioX;
        targetPoint.y *= ratioY;
    }
    else if(self.contentMode == UIViewContentModeScaleAspectFit) {
        CGFloat scale = MIN(ratioX, ratioY);

        targetPoint.x *= scale;
        targetPoint.y *= scale;

        targetPoint.x += (self.frame.size.width - sourceSize.width * scale) / 2.0f;
        targetPoint.y += (self.frame.size.height - sourceSize.height * scale) / 2.0f;
    }
    else if(self.contentMode == UIViewContentModeScaleAspectFill) {
        CGFloat scale = MAX(ratioX, ratioY);

        targetPoint.x *= scale;
        targetPoint.y *= scale;

        targetPoint.x += (self.frame.size.width - sourceSize.width * scale) / 2.0f;
        targetPoint.y += (self.frame.size.height - sourceSize.height * scale) / 2.0f;
    }

    return targetPoint;
}

- (CGRect)convertRect:(CGRect)sourceRect fromContentSize:(CGSize)sourceSize {
    CGRect targetRect = sourceRect;
    CGSize targetSize  = self.bounds.size;

    CGFloat ratioX = targetSize.width / sourceSize.width;
    CGFloat ratioY = targetSize.height / sourceSize.height;

    if (self.contentMode == UIViewContentModeScaleToFill) {
        targetRect.origin.x *= ratioX;
        targetRect.origin.y *= ratioY;

        targetRect.size.width *= ratioX;
        targetRect.size.height *= ratioY;
    }
    else if(self.contentMode == UIViewContentModeScaleAspectFit) {
        CGFloat scale = MIN(ratioX, ratioY);

        targetRect.origin.x *= scale;
        targetRect.origin.y *= scale;

        targetRect.origin.x += (self.frame.size.width - sourceSize.width * scale) / 2.0f;
        targetRect.origin.y += (self.frame.size.height - sourceSize.height * scale) / 2.0f;

        targetRect.size.width *= scale;
        targetRect.size.height *= scale;
    }
    else if(self.contentMode == UIViewContentModeScaleAspectFill) {
        CGFloat scale = MAX(ratioX, ratioY);

        targetRect.origin.x *= scale;
        targetRect.origin.y *= scale;

        targetRect.origin.x += (self.frame.size.width - sourceSize.width * scale) / 2.0f;
        targetRect.origin.y += (self.frame.size.height - sourceSize.height * scale) / 2.0f;

        targetRect.size.width *= scale;
        targetRect.size.height *= scale;
    }

    return targetRect;
}

当它被重构和优化时,我会在github上发布它并在此处发布链接。 也许甚至那个片段对某人也有帮助。

答案 2 :(得分:2)

不,没有内置,公开或优雅的方式来做到这一点。

您需要对自己需要的内容模式的功能进行反向工程。

答案 3 :(得分:-1)

为什么你不能重新缩放坐标:

X(UIImageView)=(X(图像)/ 1024)* 300

Y(UIImageView)=(Y(图像)/ 768)* 300