Core Image 还允许开发您自己的自定义图像过滤器。所谓的自定义内核 (CIKernel) 是用 OpenGL 着色语言 (GLSL) 方言编写的小程序,用于在 GPU 上运行自定义过滤器。
Photoshop 是封闭源代码,不清楚他们使用的是什么算法,但 GIMP 具有色彩平衡功能并且是开源的。
可以在这里找到实现:
https://github.com/GNOME/gimp/blob/master/app/operations/gimpoperationcolorbalance.c
现在我们需要将其翻译成 GLSL。
幸运的是,一位澳大利亚开发人员已经这样做了,请参阅 https://gist.github.com/liovch/3168961#file-gistfile1-m-L4
要快速测试这是否给出了预期的结果,可以使用 Apple 的一个很酷的实用程序,称为 Quartz Composer。
您可以从 Apple 的开发者网站下载它,它隐藏在 Additional Tools for Xcode 9.3.dmg 中。
您选择“图像过滤器”作为模板,删除输入和输出图像旁边的所有节点。从库中添加“核心图像过滤器”。然后选择过滤器并按 CMD-2。你现在应该看到一个带有代码编辑器的检查器,它显示了一个简单的通用核心映像内核例程 (CIKernel)。
由于我们只需要访问相应的源像素而不是整个图像,因此我们可以使用更具体的 CIColorKernel 而不是 CIKernel 函数。
额外的参数可以添加到内核函数中。
鉴于上述 gist 文件中的代码本身基于 GIMP 的色彩平衡例程,因此可以复制帮助函数 RGBToL、RGBToHSL、HueToRGB、HSLToRGB。然后是实际的 CIColorKernel 函数,这里我们只是修改了函数签名和返回值:
/* based on GIMP's color balance routine */
kernel vec4 balanceFilter(__sample textureColor,
float redShift,
float greenShift,
float blueShift) {
lowp float lightness = RGBToL(textureColor.rgb);
lowp vec3 shift = vec3(redShift, greenShift, blueShift);
const lowp float a = 0.25;
const lowp float b = 0.333;
const lowp float scale = 0.7;
lowp vec3 midtones = (clamp((lightness - b) / a + 0.5, 0.0, 1.0) * clamp ((lightness + b - 1.0) / -a + 0.5, 0.0, 1.0) * scale) * shift;
lowp vec3 newColor = textureColor.rgb + midtones;
newColor = clamp(newColor, 0.0, 1.0);
lowp vec3 newHSL = RGBToHSL(newColor);
lowp float oldLum = RGBToL(textureColor.rgb);
textureColor.rgb = HSLToRGB(vec3(newHSL.x, newHSL.y, oldLum));
return textureColor;
}
输入代码后会自动编译。然后,您可以在 Composer 中连接节点,请参见屏幕截图。
选择过滤器节点后,您可以使用 CMD-1 切换到输入检查器。 Composer 自动生成带有 redShift、greenShift 和 blueShift 参数的 UI,例如
如果您为 greenShift 输入 -0.64,您会看到以下结果:
一些补充说明:
- 源代码来自 GIMP。如果你想使用它,请阅读 GIMP 的许可证
- GIMP 的结果可能与 Photoshop 大不相同,我不知道,但可能仍然是自己实验的一个很好的起点
- 显然,GIST 的实现仅适用于中间色调,但通过 GIMP 源代码的链接,应该可以轻松扩展阴影和高光
- 要在您的 iOS 应用程序中使用内核,您必须将内核代码包装在一个字符串中并将其提供给 CIColorKernel 构造函数