Я пытаюсь написать вспомогательную функцию, которая применяет цветовую маску к данному изображению. Моя функция должна установить все непрозрачные пиксели изображения одного цвета.
Вот что у меня есть:
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)
EDIT
Запуск Filterpedia дает мне тот же результат. Мое понимание фильтра CIColorMatrix может быть неправильным. документация гласит:
Этот фильтр выполняет умножение матрицы следующим образом, чтобы преобразовать
цветовой вектор:
- s.r = точка (s, redVector)
- s.g = точка (s, greenVector)
- s.b = точка (с, blueVector)
- s.a = точка (с, alphaVector)
- s = s + смещение
Затем, допустим, я выбрасываю все данные RGB с (0,0,0,0) вектором, а затем передаю (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
}