【问题标题】:Rotate and blend image in iOS swift在 iOS swift 中旋转和混合图像
【发布时间】:2017-12-22 08:02:30
【问题描述】:

如何获得与下方图像混合并围绕其中心旋转的图像?

我正在尝试显示与该图像下方的任何视图混合的图像。在我的应用程序中,用户可以移动、扩展和旋转正在混合的图像。

为此,我有一个主图像视图,顶部还有一个用于混合的较小图像视图。每次位置更改时,都会更新混合 imageview 图像属性。

只要图像没有旋转,图像的混合就可以正常工作,只要旋转发生变化,我的函数返回的图像就不是在正确的位置。

我已经尝试了相同功能的 2 个不同版本。

版本 1:更新混合视图

  1. 创建具有混合图像视图大小的上下文
  2. 在偏移处绘制主图像视图,以便上下文位于混合图像视图的位置。
  3. 将上下文移动到其中心
  4. 将上下文旋转到混合图像视图的旋转
  5. 使用 blendMode 绘制混合图像视图
  6. 从上下文中获取图像并更新图像视图

版本 2:updateBlendingView2

  1. 创建具有混合图像视图大小的上下文
  2. 将上下文移动到其中心
  3. 反向旋转上下文
  4. 在偏离中心的位置绘制主图像视图
  5. 撤消旋转
  6. 在从上下文原点偏移的原点处绘制混合视图
  7. 从上下文中获取图像并更新混合图像视图

当前结果:

预期结果:

注意:请记住,草图中的混合强度可能与应用程序不同,但问题不在于图像定位:)

func updateBlendingView() {

    guard let mainViewImage = getImageFromView(view: mainImageView) else {return}

    // Reset image to original state before blending
    blendingImageView.image = UIImage(named: "square")!
    guard let blendingImage = getImageFromView(view: blendingImageView) else {return}

    UIGraphicsBeginImageContextWithOptions(blendingImageView.bounds.size, true, UIScreen.main.scale)
    guard let context = UIGraphicsGetCurrentContext() else { UIGraphicsEndImageContext();return}

    let blendingOriginTransform = CGAffineTransform(translationX: (blendingImageView.bounds.width * 0.5), y: (blendingImageView.bounds.height * 0.5))

    let radians:Float = atan2f(Float(blendingImageView.transform.b), Float(blendingImageView.transform.a))
    let rotateTransform: CGAffineTransform = CGAffineTransform(rotationAngle: CGFloat(radians))

    let mainViewOrigin = CGPoint(x: -blendingImageView.frame.origin.x , y: -blendingImageView.frame.origin.y )
    mainViewImage.draw(at: mainViewOrigin)

    context.concatenate(blendingOriginTransform)
    context.concatenate(rotateTransform)


    let blendingDrawingOrigin = CGPoint(x: -blendingImageView.bounds.width * 0.5, y: -blendingImageView.bounds.height * 0.5)
    blendingImage.draw(at: blendingDrawingOrigin, blendMode: .multiply , alpha: 0.5)

    guard let blendedImage = UIGraphicsGetImageFromCurrentImageContext() else {
        UIGraphicsEndImageContext()
        return
    }

    UIGraphicsEndImageContext()

    blendingImageView.image = blendedImage
}

func updateBlendingView2() {

    guard let mainViewImage = getImageFromView(view: mainImageView) else {return}

    // Reset image to original state before blending
    blendingImageView.image = UIImage(named: "square")!
    guard let blendingImage = getImageFromView(view: blendingImageView) else {return}

    UIGraphicsBeginImageContextWithOptions(blendingImageView.bounds.size, true, UIScreen.main.scale)
    guard let context = UIGraphicsGetCurrentContext() else { UIGraphicsEndImageContext();return}

    let blendingOriginTransform = CGAffineTransform(translationX: (blendingImageView.bounds.width * 0.5), y: (blendingImageView.bounds.height * 0.5))

    let radians:Float = atan2f(Float(blendingImageView.transform.b), Float(blendingImageView.transform.a))
    let rotateTransform: CGAffineTransform = CGAffineTransform(rotationAngle: CGFloat(radians))

    context.concatenate(blendingOriginTransform)
    context.concatenate(rotateTransform.inverted())

    let mainViewOrigin = CGPoint(x: -blendingImageView.frame.origin.x - (blendingImageView.bounds.width * 0.5) , y: -blendingImageView.frame.origin.y - (blendingImageView.bounds.height * 0.5))
    mainViewImage.draw(at: mainViewOrigin)

    // undo the rotate
    context.concatenate(rotateTransform)

    let blendingDrawingOrigin = CGPoint(x: -blendingImageView.bounds.width * 0.5, y: -blendingImageView.bounds.height * 0.5)
    blendingImage.draw(at: blendingDrawingOrigin, blendMode: .multiply , alpha: 0.5)

    guard let blendedImage = UIGraphicsGetImageFromCurrentImageContext() else {
        UIGraphicsEndImageContext()
        return
    }

    UIGraphicsEndImageContext()
    blendingImageView.image = blendedImage
}

func getImageFromView(view: UIView) -> UIImage? {
    UIGraphicsBeginImageContextWithOptions(view.bounds.size, true, UIScreen.main.scale)
    guard let context = UIGraphicsGetCurrentContext() else { UIGraphicsEndImageContext();return nil}
    view.layer.render(in: context)
    let snapshotImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return snapshotImage
}

任何帮助将不胜感激,非常感谢。 您可以在此链接中找到一个小型演示项目来说明此问题 https://github.com/Gregortega/BlendDemo

我还查看了有关核心图形的不同教程以了解该问题。 Swift: Translating and Rotating a CGContext, A Visual Explanation (iOS/Xcode)

【问题讨论】:

    标签: ios swift image rotation core-graphics


    【解决方案1】:

    我会回答我自己的问题。一位朋友给了我一个轮换问题的解决方案。

    解决方案是考虑混合图像视图位置的差异或变化。

    func updateBlendingView2(xDiff: CGFloat = 0, yDiff: CGFloat = 0) {
    
        guard let mainViewImage = getImageFromView(view: mainImageView) else {return}
    
        // Reset image to original state before blending
        blendingImageView.image = UIImage(named: "square")!
        guard let blendingImage = getImageFromView(view: blendingImageView) else {return}
    
        UIGraphicsBeginImageContextWithOptions(blendingImageView.bounds.size, true, UIScreen.main.scale)
        guard let context = UIGraphicsGetCurrentContext() else { UIGraphicsEndImageContext();return}
    
        // X, Y translation
        let blendingOriginTransform = CGAffineTransform(translationX: (blendingImageView.bounds.width * 0.5), y: (blendingImageView.bounds.height * 0.5))
        context.concatenate(blendingOriginTransform)
    
        // Rotation
        let radians:Float = atan2f(Float(blendingImageView.transform.b), Float(blendingImageView.transform.a))
        let rotateTransform: CGAffineTransform = CGAffineTransform(rotationAngle: CGFloat(radians))
        context.concatenate(rotateTransform.inverted())
    
        var mainViewOrigin = self.lastMainViewOrign
        mainViewOrigin = CGPoint(x: mainViewOrigin.x + xDiff, y: mainViewOrigin.y + yDiff)
        mainViewImage.draw(at: mainViewOrigin)
        self.lastMainViewOrign = mainViewOrigin
    
        // undo the rotate
        context.concatenate(rotateTransform)
    
        let blendingDrawingOrigin = CGPoint(x: -blendingImageView.bounds.width * 0.5, y: -blendingImageView.bounds.height * 0.5)
        blendingImage.draw(at: blendingDrawingOrigin, blendMode: .multiply , alpha: 0.5)
    
        guard let blendedImage = UIGraphicsGetImageFromCurrentImageContext() else {
            UIGraphicsEndImageContext()
            return
        }
    
        UIGraphicsEndImageContext()
        blendingImageView.image = blendedImage
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-03
      • 1970-01-01
      • 1970-01-01
      • 2018-01-01
      • 2017-04-14
      • 2016-09-30
      • 2017-07-09
      • 1970-01-01
      相关资源
      最近更新 更多