【发布时间】:2018-05-11 21:24:18
【问题描述】:
我正在尝试编写一个辅助函数,将颜色遮罩应用于给定图像。我的功能必须将图像的所有不透明像素设置为相同的颜色。
这是我目前所拥有的:
extension UIImage {
func applyColorMask(color: UIColor, context: CIContext) -> UIImage {
guard let cgImageInput = self.cgImage else {
print("applyColorMask: \(self) has no cgImage attribute.")
return self
}
// Throw away existing colors, and fill the non transparent pixels with the input color
// s.r = dot(s, redVector), s.g = dot(s, greenVector), s.b = dot(s, blueVector), s.a = dot(s, alphaVector)
// s = s + bias
let colorFilter = CIFilter(name: "CIColorMatrix")!
let ciColorInput = CIColor(cgColor: color.cgColor)
colorFilter.setValue(CIVector(x: 0, y: 0, z: 0, w: 0), forKey: "inputRVector")
colorFilter.setValue(CIVector(x: 0, y: 0, z: 0, w: 0), forKey: "inputGVector")
colorFilter.setValue(CIVector(x: 0, y: 0, z: 0, w: 0), forKey: "inputBVector")
colorFilter.setValue(CIVector(x: 0, y: 0, z: 0, w: 1), forKey: "inputAVector")
colorFilter.setValue(CIVector(x: ciColorInput.red, y: ciColorInput.green, z: ciColorInput.blue, w: 0), forKey: "inputBiasVector")
colorFilter.setValue(CIImage(cgImage: cgImageInput), forKey: kCIInputImageKey)
if let cgImageOutput = context.createCGImage(colorFilter.outputImage!, from: colorFilter.outputImage!.extent) {
return UIImage(cgImage: cgImageOutput)
} else {
print("applyColorMask: failed to apply filter to \(self)")
return self
}
}
}
代码适用于黑白,但在应用更有趣的颜色时不是我所期望的。请参阅下面的原始图像和屏幕截图:边框和图像使用相同的颜色。虽然他们不同。我的功能做错了。我是否遗漏了过滤矩阵中的某些内容?
原图(中间有白点):
从上到下:使用UIColor(1.0, 1.0, 1.0, 1.0) 过滤的图像插入到具有相同颜色边框的 UIImageView 中。然后与UIColor(0.6, 0.5, 0.4, 1.0) 相同。最后是UIColor(0.2, 0.5, 1.0, 1.0)
编辑
运行Filterpedia 给了我同样的结果。那么我对 CIColorMatrix 过滤器的理解可能是错误的。 documentation 说:
此过滤器执行矩阵乘法,如下所示,以变换 颜色向量:
- s.r = dot(s, redVector)
- s.g = dot(s, greenVector)
- s.b = dot(s, blueVector)
- s.a = dot(s, alphaVector)
- s = s + 偏差
然后,假设我用 (0,0,0,0) 向量抛出所有 RGB 数据,然后传递 (0.5, 0, 0, 0) 中红色作为偏置向量;我希望我的图像将所有完全不透明的像素都设置为 (127, 0, 0)。下面的截图显示它稍微浅一些(红色=186):
这是我想做的一些伪代码:
// image "im" is a vector of pixels
// pixel "p" is struct of rgba values
// color "col" is the input color or a struct of rgba values
for (p in im) {
p.r = col.r
p.g = col.g
p.b = col.b
// Nothing to do with the alpha channel
}
【问题讨论】:
-
如果将向量 (x:y:z:w:) 设置为:
1,0,0,0为红色,0,1,0,0为绿色,0,0,1,0为蓝色,您将获得正常外观的图片.现在,要将红色通道减半,请将inputRVector设置为0.5,0,0,0。要删除 all 红色,请将其设置为0,0,0,0。这基本上就是我使用它的方式。我确信还有其他组合可以获得其他结果,但这应该可以帮助您入门。 -
这是 Filterpedia 的 Swift 4 版本 - github.com/rhoeper/Filterpedia-Swift4 我还没有尝试过(我有自己的 Swift 4 端口),但它是尝试每个过滤器的绝佳资源。所有输入参数都显示为
UISliders,向您显示最小/最大/当前值。如果它像原始版本一样,则有六个不同的测试图像以及几十个使用 Metal 或 CIKernel(使用 GLSL)的自定义过滤器。一个警告:它只能在 iPad 上运行(您可以使用模拟器,但与任何 CoreImage 项目一样,性能很差)。 -
感谢@dfd 的链接,我首先尝试将 rgb 向量设置为 (theRedlwant,0,0,0) (0,theBluelwant,0,0) 和 (0,0,theGreenIWant ,0) 但正如你所说的 1 用于获得正常外观的图片。我的目标是丢弃所有颜色信息并使其成为单色。只保留alpha通道。它主要用于为按钮图像或徽标重新着色。
-
我会在我的 iPad 或模拟器上尝试链接。我也觉得肯定还有别的组合。
-
好的,我想我明白了。您想逐像素拍摄图像并(至少在您的示例中)更改每个 RGB 通道。例如,假设一个像素的 RGB 值为 (1.0, 0.4, 0.4) - 我不知道颜色是什么! - 你传入一个 (0.5, 0.0, 0.0) 的“col”。您希望输出为 R=1.0*0.5,G=0.4*0.0,B=0.4*0.0,产生 (0.5, 0.0, 0.0)。请记住,UIKit 使用 0-254 而 CoreImage 使用 0-1。这是一个非常简单的
CIColorKernel。如果你想要的我是正确的,请告诉我,我会编写 Swift 代码来完成它。
标签: swift image-processing cifilter