利用Metal实现散景效果
写在前面
正文
效果图概述
Metal
功能非常强大,在iOS平台大有替代Opengl ES
之势。本片博客主要介绍使用Metal
处理图片,实现一个散景效果。
morphological operations
(形态塑造)操作建立在内核上,根据相邻的值改变像素的值。
morphological operations
主要有如下两种基本的类型:
-
Dilation
(膨胀),扩展图像的明亮区域。 -
Erosion
(侵蚀),扩展图像的黑暗区域。
内核是形态操作从图像中的对应像素值中减去的1D
或2D
网格值。 每个变换像素的最终值是每次减法的最轻(对于膨胀模式)或者最暗(对于侵蚀模式)的结果。
以下公式显示扩张操作如何计算网格中心像素的值。 该操作从图像的相应像素中减去九个内核值中的每一个并返回最大值。
矩阵公式生成结构元素
static func makeStructuringElement(ofRadius radius: Int, withSides sides: Int) ->[UInt8]
方法返回一个内核,该内核填充了适合与整数格式图像一起使用的UInt8
值。 例如,要创建六边形散景效果,请调用makeStructuringElement(ofRadius:withSides :)
方法并将边数设置为6
:
例如:
var numSides = 6
let kernel = ViewController.makeStructuringElement(ofRadius: radius,
withSides: numSides)
返回时,内核包含以下值:
内核返回值膨胀模式应用
要将扩展应用于vImage
缓冲区,需要调用vImageDilate_ARGB8888
函数,传递makeStructuringElement(ofRadius:withSides :)
返回的内核:
示例如下:
let dismeter = vImagePixelCount(radius * 2) + 1
vImageMax_ARGB8888(&sourceBuffer, &destinationBuffer, nil, 0, 0, dismeter, dismeter, vImage_Flags(kvImageNoFlags))
效果图
最大化图像
vImage
提供最大化过滤器,返回内核覆盖区域中最亮的像素。 最大化过滤器使用填充了单个值的内核将扩张应用于图像。 vImage
优化了这种特殊情况 - 所有内核值都相同 - 因此它比具有统一内核的扩展函数快得多。
以下公式显示了由3 x 3 max
内核最大化的图像:
要最大化图像,需要调用vImageMax_ARGB8888
函数,方法是传递内核的高度和宽度:
vImageMax_ARGB8888(&sourceBuffer, &destinationBuffer, nil, 0, 0, dismeter, dismeter, vImage_Flags(kvImageNoFlags))
在本例子中,内核高度和宽度是相同的值。 因此,图像的明亮区域显示为大方块:
效果图项目地址:项目Github地址