swift - 如何构造 5x5 矩阵以在 Swift 中应用为颜色矩阵?
问题描述
我需要一些帮助再次将我的 Android 应用程序转换为 iOS...
正如我在其他帖子中提到的,该应用程序是关于图像处理的,它基于 ColorMatrix。问题是 Swift 只支持(据我所知......)4x4 矩阵,而对于亮度或对比度,我在 Android 中使用 5x5 矩阵。
在 Android 中,这些是我的矩阵:
亮度:
float[] brightMatrix = {
1f, 0f, 0f, 0f, 32f,
0f, 1f, 0f, 0f, 32f,
0f, 0f, 1f, 0f, 32f,
0f, 0f, 0f, 1f, 0f,
0f, 0f, 0f, 0f, 1f};
对比:
float[] contMatrix = {
1.190f, 0f, 0f, 0f, -12.065f,
0f, 1.190f, 0f, 0f, -12.065f,
0f, 0f, 1.190f, 0f, -12.065f,
0f, 0f, 0f, 1f, 0f,
0f, 0f, 0f, 0f, 1f};
但我真的不知道如何在 Swift 中获得相同的结果......
在亮度的情况下,我尝试使用此代码除以 32/255 来获得值 0.12549:
func zoeFilter() -> UIImage? {
let inImage = CIImage (image: self)
dynamic let brightFactor = CIFilter (name: "CIColorControls")
brightFactor?.setValue(inImage, forKey: kCIInputImageKey)
brightFactor?.setValue(0.12549, forKey: kCIInputBrightnessKey)
let brightImage = brightFactor?.outputImage
let cgImage = CIContext().createCGImage(brightImage!, from: brightImage!.extent)
return UIImage (cgImage: cgImage!)
}
但是结果完全不一样……在iOS中就像一团白雾……
谈到对比度,我找到了下一个代码,但我不可能contFactor?.setValue(1, forKey: kCIInputContrastKey)
只知道 1 等于中性就将 Android 矩阵转换为一个值:
func chiaFilter() -> UIImage? {
let inImage = CIImage (image: self)
dynamic let contFactor = CIFilter (name: "CIColorControls")
contFactor?.setValue(inImage, forKey: kCIInputImageKey)
contFactor?.setValue(1, forKey: kCIInputContrastKey)
let contImage = contFactor?.outputImage
let cgImage = CIContext().createCGImage(contImage!, from: contImage!.extent)
return UIImage (cgImage: cgImage!)
}
另一方面,更改曝光很容易,因为 Android 中的矩阵如下:
float[] expMatrix = {
1.3f, 0f, 0f, 0f, 0f,
0f, 1.3f, 0f, 0f, 0f,
0f, 0f, 1.3f, 0f, 0f,
0f, 0f, 0f, 1f, 0f,
0f, 0f, 0f, 0f, 1f};
所以在 Swift 中,我可以使用下面的代码得到完全相同的结果:
func liaFilter() -> UIImage? {
let inImage = CIImage (image: self)
dynamic let expoMatrix = CIFilter (name: "CIColorMatrix")
expoMatrix?.setDefaults()
expoMatrix?.setValue(inImage, forKey: kCIInputImageKey)
expoMatrix?.setValue(CIVector (x: 1.3, y: 0, z: 0, w: 0), forKey: "inputRVector")
expoMatrix?.setValue(CIVector (x: 0, y: 1.3, z: 0, w: 0), forKey: "inputGVector")
expoMatrix?.setValue(CIVector (x: 0, y: 0, z: 1.3, w: 0), forKey: "inputBVector")
expoMatrix?.setValue(CIVector (x: 0, y: 0, z: 0, w: 1), forKey: "inputAVector")
let expoImage = expoMatrix?.outputImage
let cgImage = CIContext().createCGImage(expoImage!, from: expoImage!.extent)
return UIImage (cgImage: cgImage!)
}
太困惑了……我知道……但如果有人能知道如何解决 Android 和 iOS 之间的这些问题,那就太好了。
提前致谢!
弗兰克回答后的版本
这是在使用 Android 应用过滤器之后:
float[] brightMatrix = {
1f, 0f, 0f, 0f, 32f,
0f, 1f, 0f, 0f, 32f,
0f, 0f, 1f, 0f, 32f,
0f, 0f, 0f, 1f, 0f,
0f, 0f, 0f, 0f, 1f};
这是使用 iOS 应用过滤器的同一张图片:
brightMatrix?.setValue(CIVector (x: 1, y: 0, z: 0, w: 0), forKey: "inputRVector")
brightMatrix?.setValue(CIVector (x: 0, y: 1, z: 0, w: 0), forKey: "inputGVector")
brightMatrix?.setValue(CIVector (x: 0, y: 0, z: 1, w: 0), forKey: "inputBVector")
brightMatrix?.setValue(CIVector (x: 0, y: 0, z: 0, w: 1), forKey: "inputAVector")
brightMatrix?.setValue(CIVector (x: 32.0/255.0, y: 32.0/255.0, z: 32.0/255.0, w: 0), forKey: "inputBiasVector")
弗兰克提议后的最终解决方案
func zoeFilter() -> UIImage? {
let inImage = CIImage (image: self)
dynamic let SRGBMatrix = CIFilter (name: "CILinearToSRGBToneCurve")
dynamic let brightMatrix = CIFilter (name: "CIColorMatrix")
dynamic let linearMatrix = CIFilter (name: "CISRGBToneCurveToLinear")
SRGBMatrix?.setValue(inImage, forKey: kCIInputImageKey)
let SRGBImage = SRGBMatrix?.outputImage
brightMatrix?.setDefaults()
brightMatrix?.setValue(SRGBImage, forKey: kCIInputImageKey)
brightMatrix?.setValue(CIVector (x: 1, y: 0, z: 0, w: 0), forKey: "inputRVector")
brightMatrix?.setValue(CIVector (x: 0, y: 1, z: 0, w: 0), forKey: "inputGVector")
brightMatrix?.setValue(CIVector (x: 0, y: 0, z: 1, w: 0), forKey: "inputBVector")
brightMatrix?.setValue(CIVector (x: 0, y: 0, z: 0, w: 1), forKey: "inputAVector")
brightMatrix?.setValue(CIVector (x: 32.0/255.0, y: 32.0/255.0, z: 32.0/255.0, w: 0), forKey: "inputBiasVector")
let brightImage = brightMatrix?.outputImage
linearMatrix?.setDefaults()
linearMatrix?.setValue(brightImage, forKey: kCIInputImageKey)
let linearImage = linearMatrix?.outputImage
let cgImage = CIContext().createCGImage(linearImage!, from: linearImage!.extent)
return UIImage (cgImage: cgImage!)
}
解决方案
您应该能够通过像这样设置过滤器的inputBiasVector
参数来使用亮度和对比度矩阵:CIColorMatrix
// the first 4 should actually be the default, so you probably don't need to set them explicitly
brightMatrix?.setValue(CIVector(x: 1, y: 0, z: 0, w: 0), forKey: "inputRVector")
brightMatrix?.setValue(CIVector(x: 0, y: 1, z: 0, w: 0), forKey: "inputGVector")
brightMatrix?.setValue(CIVector(x: 0, y: 0, z: 1, w: 0), forKey: "inputBVector")
brightMatrix?.setValue(CIVector(x: 0, y: 0, z: 0, w: 1), forKey: "inputAVector")
brightMatrix?.setValue(CIVector(x: 32.0/255.0, y: 32.0/255.0, z: 32.0/255.0, w: 0), forKey: "inputBiasVector")
不过,很奇怪,您不能使用CIColorControls
过滤器来达到同样的效果。也许您可以发布示例图像。
推荐阅读
- html - Django - 在基本模板中显示警报消息
- javascript - 你如何使用 Webpack 和 Babel 进行编译?
- javascript - 如何让控制台打印出名称,记住名称变量不是恒定的?
- python - 尝试使用 Python PDFMINER 从 PDF 中提取文本时出错
- python - 如何在网站上抓取地图以获取存储在弹出窗口中的信息?
- java - Jackson多态树状结构反序列化
- java - Java/Android - ECDH 加密 - 从字符串创建 ECPublicKey
- javascript - 如何清除使用新 ES6 方法创建的间隔 (setInterval)?
- flutter - Rzorpay 没有对 gpay 交易进行任何回电:flutter
- django - 如何让 nginx 在新后端从旧后端检查身份验证状态?