【问题标题】:CIRadialGradient reduces image sizeCIRadialGradient 减小图像大小
【发布时间】:2019-04-13 04:26:50
【问题描述】:

对我的图像应用 CIRadialGradient 后,它的宽度减少了大约 20%。

guard let image = bgImage.image, let cgimg = image.cgImage else {
    print("imageView doesn't have an image!")
    return
}
let coreImage = CIImage(cgImage:cgimg)

guard let radialMask = CIFilter(name:"CIRadialGradient") else {
    return
}

guard let maskedVariableBlur = CIFilter(name:"CIMaskedVariableBlur") else {
    print("CIMaskedVariableBlur does not exist")
    return 
}
maskedVariableBlur.setValue(coreImage, forKey: kCIInputImageKey)

maskedVariableBlur.setValue(radialMask.outputImage, forKey: "inputMask")
guard let selectivelyFocusedCIImage = maskedVariableBlur.outputImage else {
    print("Setting maskedVariableBlur failed")
    return
}


bgImage.image = UIImage(ciImage: selectivelyFocusedCIImage)

澄清一下,bgImageUIImageView

为什么会发生这种情况,我该如何解决?

没有 RadialMask:

使用 RadialMask:

不同的是,在我的物理 iPhone 上,较小的图像向左对齐。

【问题讨论】:

  • 您可以在应用过滤器之前和之后发布图像吗?
  • 是的,我刚刚编辑了我的帖子。

标签: ios swift xcode core-image


【解决方案1】:

查看文档,这是一个应用于图像的掩码:

文档:CIRadialGradient

【讨论】:

  • 是的,情况似乎确实如此。但是我该如何解决这个问题并保持原来的大小呢?
  • 这也是RadialGradient,而不是RadialMask
  • 这是一个渐变,但它会将您的图像视为蒙版。文档中的相同链接将我们引向可以自定义的参数:inputRadius1inputColor1 似乎确实可以作为候选对象。
  • 我确实玩过这些,但不幸的是,除了模糊效果之外,它并没有改变任何东西。
【解决方案2】:

我倾向于通过使用CIContext 并创建一个特定大小的CGImage 而不是简单地使用UIImage(ciImage:) 来明确说明图像的大小。试试这个,假设你的 inputImage 被称为coreGraphics:

let ciCtx = CIContext()
let cgiig = ctx.createCGImage(selectivelyFocusedCIImage, from: coreImage.extent)
let uiImage = UIImage(cgImage: cgIMG!)

一些笔记....

(1) 我从一个正在打包的应用程序中提取了这段代码。这是未经测试的代码(包括强制解包),但我正在做的事情的概念是可靠的。

(2) 你没有解释很多你想要做什么,但是当我看到一个名为 selectivelyFocusedCIImage 的变量时,我担心你可能试图以一种比“只是“创建一个图像。如果您想要“接近实时”的性能,请将 CIImage 渲染为(自 iOS 12 起已弃用)GLKViewMTKView 而不是 UIImageView。后者只使用CPU,而前者使用GPU。

(3) 最后,对CIContexts 提出警告——创建它们的成本很高!通常,您可以对其进行编码,以便您的应用程序中的所有内容都只能共享一个上下文。

【讨论】:

  • 这确实解决了问题,谢谢!我的目的是添加模糊效果,但由于图像已经模糊,因此很难看清。但是现在它已经解决了,我可以玩弄它并让它变得更好。我只是不确定它是如何解决问题的。
  • 老实说,我无法评论为什么 UIImage(ciImage:) 有时会随意对待事物,但使用我描述的方法是可行的,因为 (1) 它与 CoreImage - CIImage 一起工作, CIContext 等 - 然后 (2) 在您需要的 extent 中呈现最终的 CIImage。请注意,CIRadialGradient 可以 使用“某物”的实际inputImage,但输出实际上是用作其他东西 - 在您的情况下是掩码。在我的情况下?我想要 it 的输出 CIImage 但需要“图像大小”,所以我的输入图像是具有特定用户定义范围的黑色 CIImage。
  • 您的 案例中 - 根据个人经验 - 我知道您需要将 CIImage 设置为特定大小(原始图像)。虽然模糊滤镜扭曲输出图像的大小,但渐变滤镜呢?那对我来说是新的。但是,使用 CIContext 来调整输出大小不是。请记住,CIImage 不是真正图像。这是一个“食谱”。一些过滤器为您提供单像素输出(是的,像素,而不是点)。你如何选择制作你想要的这个“食谱”是我认为使用UIImage(ciImage:) 失败的地方......非常糟糕。这是一个捷径,直到它不起作用!
  • 大小不同是因为模糊滤镜改变了图像的(虚拟)扩展。检查我的答案 - 您可以轻松解决此问题,而无需每次都创建 CIContext
【解决方案3】:

大小不同是由于模糊滤镜的内核大小造成的:

模糊滤镜需要对每个像素周围的区域进行采样。由于没有超出图像边界的像素,Core Image 将结果图像的extend 减少一半内核大小(模糊半径),以表明对于这些像素没有足够的信息来进行适当的模糊。

但是,您可以告诉 Core Image 将边界像素视为在所有方向上无限延伸,以便模糊过滤器即使在图像边缘也能获得足够的信息。之后,您可以将结果裁剪回原始尺寸。

在您的代码中,只需更改以下两行:

maskedVariableBlur.setValue(coreImage.clampedToExtent(), forKey: kCIInputImageKey)

bgImage.image = UIImage(ciImage: selectivelyFocusedCIImage.cropped(to:coreImage.extend))

【讨论】:

    猜你喜欢
    • 2017-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多