gpt4 book ai didi

swift - 我在使用 touchesBegan 中的 x 和 y 坐标作为 CI 过滤器中的中心键时遇到了一些问题

转载 作者:行者123 更新时间:2023-11-28 15:59:49 25 4
gpt4 key购买 nike

我正在尝试设置让用户点击 ImageView 中的位置,并且点击的 X、Y 成为当前使用的图像过滤器的中心点(kCIInputCenterKey)。

这些是我的全局变量:

var x: CGFloat = 0
var y: CGFloat = 0
var imgChecker = 0

这是我的 touchesBegan 函数,它检查用户是否在 ImageView 内触摸,如果没有,则将过滤器中心键设置为 ImageView 的中心:
  override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
let position = touch.location(in: self.imageView)


if (touch.view == imageView){
print("touchesBegan | This is an ImageView")
x = position.x * 4
y = position.y * 4
imgChecker = 1

}else{
print("touchesBegan | This is not an ImageView")
x = 0
y = 0
imgChecker = 0
}


print("x: \(x)")
print("y: \(y)")
}
}

如您所见,如果未点击 ImageView 内部,我在那里有检查器以使过滤器中心出现在图像中间。我还打印出点击到 xCode 控制台的坐标,它们看起来没有问题。

这是我应用过滤器的部分:
currentFilter = CIFilter(name: "CIBumpDistortion")

currentFilter.setValue(200, forKey: kCIInputRadiusKey)
currentFilter.setValue(1, forKey: kCIInputScaleKey)

if imgChecker == 1 {
self.currentFilter.setValue(CIVector(x: self.x, y: self.y), forKey: kCIInputCenterKey)
}else{

self.currentFilter.setValue(CIVector(x: currentImage.size.width / 2, y: currentImage.size.height / 2), forKey: kCIInputCenterKey)
}

x = 0
y = 0
let beginImage = CIImage(image: currentImage)
currentFilter.setValue(beginImage, forKey: kCIInputImageKey)
let cgimg = context.createCGImage(currentFilter.outputImage!, from: currentFilter.outputImage!.extent)
currentImage = UIImage(cgImage: cgimg!)
self.imageView.image = currentImage

这是我正在使用的 CGRect,忽略那里的“框架”,它只是第一个前面的 ImageView ,允许我在当前过滤的图像上保存一个“框架”:
func drawImagesAndText() {

let renderer = UIGraphicsImageRenderer(size: CGSize(width: imageView.bounds.size.width, height: imageView.bounds.size.height))

img = renderer.image { ctx in
let bgImage = currentImage
bgImage?.draw(in: CGRect(x: 0, y: 0, width: imageView.bounds.size.width, height: imageView.bounds.size.height))

frames = UIImage(named: framesAr)
frames?.draw(in: CGRect(x: 0, y: 0, width: imageView.bounds.size.width, height: imageView.bounds.size.height))
}

}

当我通过在 ImageView 内点击来设置 x,y 时,无论我在哪里点击, ImageView 中过滤器的中心都会一直出现在它的左下角。如果我继续点击 ImageView ,中心似乎确实移动了一点,但它不在我实际点击的位置附近。

任何见解将不胜感激,谢谢。

最佳答案

记住两件事。

首先(我想你可能知道这一点),CI 原点 (0,0) 位于左下方,而不是左上方。

其次(我认为这是问题所在)UIKit(意思是 UIImage 和可能的 CGPoint 坐标)与 CIVector 坐标不同。您需要将 UIKit touchesBegan 坐标转换为 CIImage.extent 坐标。

编辑:

后面的所有坐标是 X 然后是 Y,宽度是高度。

在发表我的评论后,我想我会举一个例子来说明我所说的缩放。假设您有一个大小为 250x250 的 UIImageView,使用 AspectFit 的内容模式,显示大小为 1000x500 的图像。

现在,假设 touchesBegan 是 CGPoint(200,100)。 (注意:如果你的 UIImageView 是一个更大的 super View 的一部分,它可能更像是 250,400 - 我正在处理 内的 UIImageView。)

缩小图像大小(记住,AspectFit)意味着图像实际上在 CGRect(0, 62.5, 250, 125) 处的 UIImageView 中垂直居中(出现横向)。所以首先,好!接触点不仅开始于 ImageView ,还开始希望图像。 (您可能需要考虑从图像外部开始触摸的不太边缘的情况。)

除以 4 为您提供按比例缩小的 ImageView 坐标,并且如您所料,乘以将为您提供所需的矢量坐标。所以一个 touchesBegan CGPoint(200,100) 变成了一个 CIVector(800,400)。

我写了一些代码——注释的方式不多,在 Swift 2 中完成(我认为)并且写得非常糟糕——这是 UIImageView 的子类(可能应该是扩展)的一部分,它计算了所有这些。使用 UIImageView 的边界和它的图像大小是你所需要的。请记住 - AspectFit 中的图像也可以放大!

关于 CIImage 的最后一点 - 范围。很多时候它是 UIImage 的大小。但是许多掩码和生成的输出可能有无限的消耗。

第二次编辑:

我在缩放示例中犯了一个愚蠢的错误。请记住,CIImage Origin 是 左下 ,而不是 左上 .所以在我的例子中,一个 CGPoint(200,100),缩放到 CGPoint(800,400) 将是 CGVector(800,100) .

第三次编辑:

为多次/运行编辑道歉,但这似乎很重要。 (此外,只有最后一个是由于我的愚蠢!值得一提的是,但仍然如此。)

现在我们正在谈论使用 Core Image 过滤器进行“近乎实时”的更新。我计划最终发布一些关于此的博客文章,但是 真实 您要的来源是Simon Gladman (他继续前进,回顾他在 2015-16 年的帖子)和他的电子书 Core Image for Swift (使用 Swift 2 但大多数会自动升级到 Swift 3)。只是在应得的地方给予信用。

如果你想“接近实时”使用 Core Image,你需要使用 GPU。 UIView 及其所有子类(即 UIKit)都使用 CPU。没关系,使用 GPU 意味着使用 Core Graphics,特别是使用 GLKView。它是 UIImage 的 CG 等价物。

这是我的子类:

open class GLKViewDFD: GLKView {
var renderContext: CIContext
var myClearColor:UIColor!
var rgb:(Int?,Int?,Int?)!

open var image: CIImage! {
didSet {
setNeedsDisplay()
}
}
public var clearColor: UIColor! {
didSet {
myClearColor = clearColor
}
}

public init() {
let eaglContext = EAGLContext(api: .openGLES2)
renderContext = CIContext(eaglContext: eaglContext!)
super.init(frame: CGRect.zero)
context = eaglContext!
}

override public init(frame: CGRect, context: EAGLContext) {
renderContext = CIContext(eaglContext: context)
super.init(frame: frame, context: context)
enableSetNeedsDisplay = true
}

public required init?(coder aDecoder: NSCoder) {
let eaglContext = EAGLContext(api: .openGLES2)
renderContext = CIContext(eaglContext: eaglContext!)
super.init(coder: aDecoder)
context = eaglContext!
enableSetNeedsDisplay = true
}

override open func draw(_ rect: CGRect) {
if let image = image {
let imageSize = image.extent.size
var drawFrame = CGRect(x: 0, y: 0, width: CGFloat(drawableWidth), height: CGFloat(drawableHeight))
let imageAR = imageSize.width / imageSize.height
let viewAR = drawFrame.width / drawFrame.height
if imageAR > viewAR {
drawFrame.origin.y += (drawFrame.height - drawFrame.width / imageAR) / 2.0
drawFrame.size.height = drawFrame.width / imageAR
} else {
drawFrame.origin.x += (drawFrame.width - drawFrame.height * imageAR) / 2.0
drawFrame.size.width = drawFrame.height * imageAR
}

rgb = (0,0,0)
rgb = myClearColor.rgb()
glClearColor(Float(rgb.0!)/256.0, Float(rgb.1!)/256.0, Float(rgb.2!)/256.0, 0.0);
glClear(0x00004000)
// set the blend mode to "source over" so that CI will use that
glEnable(0x0BE2);
glBlendFunc(1, 0x0303);
renderContext.draw(image, in: drawFrame, from: image.extent)
}
}
}

一些笔记。
  • 我绝对需要感谢 Objc.io大部分时间。这也是 Swift 和 UIKit 编码的一个很好的资源。
  • 我想要 AspectFit 内容模式,它有可能改变 GLKView 的“背景颜色”,这就是我子类化并调用 if clearColor 的原因。

  • 在我链接到的两个资源之间,您应该拥有使用 GPU 实现良好性能、近乎实时地使用 Core Image 所需的东西。我上述代码使用缩放的原因之一 得到过滤器的输出后从来没有更新过?它不需要它。

    我知道这里有很多要处理的。但我发现这方面的东西(核心图像效果)是 iOS 最有趣的方面(也很酷)。

    关于swift - 我在使用 touchesBegan 中的 x 和 y 坐标作为 CI 过滤器中的中心键时遇到了一些问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41251133/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com