【问题标题】:Combine 2 UIImage views with zoom and offset将 2 个 UIImage 视图与缩放和偏移相结合
【发布时间】:2014-07-30 17:35:49
【问题描述】:

感谢阅读。

我有一张背景图片和一张前景图片。前景图像位于 UIScrollView 中,因此可以在背景图像上调整大小和重新定位。背景图像设置为 Aspect Fit。我有一个将两个 UIImage 组合成一个新 UIImage 的函数。这很好用,但我无法正确理解一个视图相对于另一个视图的 x,y 坐标。

这里有一些代码:

CGFloat bgImageScale = self.backgroundImageView.bounds.size.height / self.bgImage.size.height; // Gives me the AspectFit scale.
CGFloat bgOffsetX = (self.backgroundImageView.bounds.size.width - self.bgImage.size.width * bgImageScale) / 2.0;
CGFloat bgOffsetY = 0.0;
CGFloat fgImageScale = self.fgImageScrollView.zoomScale;
CGFloat fgOffsetX = -self.fgImageScrollView.contentOffset.x;
CGFloat fgOffsetY = -self.fgImageScrollView.contentOffset.y;

CGPoint imageOffset = CGPointMake((fgOffsetX - bgOffsetX) * bgImageScale, (fgOffsetY - bgOffsetY) * bgImageScale);


[self.delegate completedOverlayImage:
  [self mergeImage:self.fgImage
         withImage:self.bgImage
        usingAlpha:0.5f
        withOffset:imageOffset
          andScale:fgImageScale / bgImageScale
]];

简而言之,completedOverlayImage 代码做了以下相关操作:

[bottomImage drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
[topImage drawInRect:CGRectMake(imageOffset.x, imageOffset.y, newSize.width*imageScale, newSize.height*imageScale) blendMode:kCGBlendModeNormal alpha:alpha];

所以我只是无法正确获取 imageOffset 的内容,以使新图像覆盖与屏幕上显示的相同。

顺便说一下,这个应用程序仅适用于 iOS 7 及更高版本。

有人可以帮忙吗?谢谢。

【问题讨论】:

    标签: ios objective-c uiscrollview uiimage


    【解决方案1】:

    好的,我自己解决了。所以对于其他尝试同样事情的人来说,这里是代码:

    CGFloat bgImageScale = self.backgroundImageView.bounds.size.height / self.bgImage.size.height;
    CGFloat bgOffsetX = (self.backgroundImageView.bounds.size.width - self.bgImage.size.width * bgImageScale) / 2.0;
    CGFloat bgOffsetY = 0.0;
    CGFloat fgImageScale = self.fgImageScrollView.zoomScale;
    CGFloat fgRelativeZoom = fgImageScale / bgImageScale; // How much is fg zoomed compared to bg?
    CGFloat fgOffsetX = -self.fgImageScrollView.contentOffset.x; // We want the offset of the (0,0), not the offset of the viewport. Hence, negative.
    CGFloat fgOffsetY = -self.fgImageScrollView.contentOffset.y;
    
    CGPoint imageOffset = CGPointMake(fgOffsetX / bgImageScale - bgOffsetX, fgOffsetY / bgImageScale - bgOffsetY);
    
    [self.delegate completedOverlayImage:
     [self mergeImage:self.fgImage
            withImage:self.bgImage
           usingAlpha:0.5f
           withOffset:imageOffset
             andScale:fgRelativeZoom
    ]];
    

    以及合并图像的功能(假设 iOS 7 允许您在 UIGraphicsBeginContextWithOptions() 调用中将比例设置为零):

    - (UIImage*) mergeImage:(UIImage*)topImage withImage:(UIImage*)bottomImage usingAlpha:(CGFloat)alpha withOffset:(CGPoint)imageOffset andScale:(CGFloat)imageScale {
    
        int width = bottomImage.size.width;
        int height = bottomImage.size.height;
    
        CGSize newSize = CGSizeMake(width, height);
    
        UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
        [bottomImage drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
        [topImage drawInRect:CGRectMake(imageOffset.x, imageOffset.y, newSize.width*imageScale, newSize.height*imageScale) blendMode:kCGBlendModeNormal alpha:alpha];
    
        UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    
        return newImage;
    }
    

    希望对其他人有所帮助。

    【讨论】:

      【解决方案2】:

      看看UIViewconvertRect:toView:方法。

      假设您的视图层次结构如下所示

      SomeViewController
         View               // the view controller's main view
            BgView          // the background view (UIImageView)
            ScrollView      
               FgView       // the foreground view (UIImageView)
      

      如果前景图像是滚动视图的子 UIImageView,那么您可以使用这样的一行代码将 FgView 框架坐标转换为主视图坐标系

      CGRect foregroundFrame = [self.foregroundImageView convertRect:self.foregroundImageView.bounds toView:self.view];
      

      由于 BgView 的框架已经在 mainView 坐标中,这将为您提供相同坐标系中的两个框架。

      【讨论】:

      • 是的,这就是正确的视图层次结构。 convertRect 是个好主意,但是 ScrollView 和 BgView 都在同一个坐标系中,所以使用 convertRect 或使用 ScrollView 的 contentOffset 都提供相同的数字。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-08-29
      • 1970-01-01
      • 2012-06-15
      • 1970-01-01
      • 1970-01-01
      • 2015-11-10
      • 2020-03-11
      相关资源
      最近更新 更多