CIRadialGradient减小了图像大小。

3

在对我的图片应用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)

需要澄清的是,bgImage 是一个 UIImageView

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

没有 RadialMask:

enter image description here

有 RadialMask:

enter image description here

在我的实体 iPhone 上,小图像向左对齐的区别。


你能发布一下应用滤镜前后的图片吗? - EmilioPelaez
是的,我刚刚编辑了我的帖子。 - Sinan Samet
3个回答

3

我倾向于使用CIContext并创建一个特定大小的CGImage来明确说明图像的大小,而不是简单地使用UIImage(ciImage:)。如果你的输入图像叫做coreGraphics,可以尝试以下方法:

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

一些注意事项....

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

(2) 您没有解释您试图做什么的许多内容,但当我看到名为selectivelyFocusedCIImage的变量时,我会担心您可能正在尝试以比“仅”创建一个图像更交互的方式使用CoreImage。如果您想要“接近实时”的性能,请在(已于iOS 12停用的)GLKViewMTKView中呈现CIImage,而不是UIImageView。后者只使用CPU,而前两者使用GPU。

(3) 最后,关于CIContexts的警告 - 它们的创建费用很高!通常,您可以对其进行编码,以便有一个上下文可以由应用程序中的所有内容共享。


这真的解决了问题,谢谢!我的目的是添加模糊效果,但由于图像已经模糊,很难看到。但现在问题已经解决,我可以尝试调整它并使其更好。只是我不确定它是如何解决问题的。 - Sinan Samet
1
我无法对UIImage(ciImage:)为什么有时会随意处理事情发表评论,但使用我描述的方法是有效的,因为(1)它仅适用于CoreImage - CIImage、CIContext等,然后(2)在您需要的“范围”中呈现最终的CIImage。请注意,CIRadialGradient可以使用实际的“输入图像”作为“某物”,但输出实际上是用作其他东西的 - 在您的情况下是蒙版。在我的情况下?我想要一个输出CIImage的,但需要一个“图像大小”,因此我的输入图像是具有特定用户定义范围的黑色CIImage。 - user7014451
1
根据个人经验,在你的情况下,我知道你需要使你的CIImage成为特定大小(原始图像)。虽然模糊滤镜扭曲输出图像的大小,但渐变滤镜呢?这对我来说是新的。但是,使用CIContext调整输出大小并不是新鲜事。记住,CIImage并不是真正的图像。它是一种“配方”。有些滤镜会给你一个单像素输出(是的,像素,而不是点)。如何选择使这个“配方”成为你想要的东西,我认为使用UIImage(ciImage:)就会崩溃...非常糟糕的快捷方式! - user7014451
大小差异是由于模糊滤镜改变了图像的(虚拟)扩展。检查一下我的答案,你可以很容易地修复这个问题,而不需要每次都创建一个CIContext - Frank Rupprecht

2
请查看文档,这是应用于图像的蒙版: enter image description here 文档链接:CIRadialGradient

是的,这似乎确实是情况。但是我如何解决这个问题并保持原始大小呢? - Sinan Samet
这是一个RadialGradient,而不是RadialMask - Sinan Samet
这是一个渐变,但它将您的图像视为掩码。文档中的相同链接引导我们到可以自定义的参数:inputRadius1inputColor1似乎是可以调整的候选项。 - inokey
我确实尝试过这些,但不幸的是除了模糊效果之外什么都没有改变。 - Sinan Samet

0
不同的尺寸是由于模糊滤镜内核大小引起的:
模糊滤镜需要对每个像素周围的区域进行采样。由于图像边界没有像素,Core Image会将结果图像的 extend 减少一半的内核大小(模糊半径),以表明这些像素上没有足够的信息进行正确的模糊处理。
但是,您可以告诉 Core Image 将边框像素视为在所有方向上无限扩展,以便模糊滤镜即使在图像边缘也能获取足够的信息。然后,您可以将结果裁剪回原始尺寸。
在您的代码中,只需更改以下两行:
maskedVariableBlur.setValue(coreImage.clampedToExtent(), forKey: kCIInputImageKey)

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接