图片是由许多像素组成的,每个像素都有r,g,b,a4个值。如果对像素的这些值进行改变,就会改变像素的颜色或透明度。
对整个图片的像素进行有选择的改变就能改变整个图片的现实效果(图片滤镜)
首先要确定,rgba值的数据格式是UInt8,不能随意和Int值进行计算,因此在一些求平均值的情况要先将rgba用Int()将这些值转换为int再计算。
源码地址:https://github.com/lsvih/ImageProcessor
首先读取图片
1 let image = UIImage (named: "sample" )
运行结果:
upload successful
写一个滤镜,用于在遍历像素时去掉照片中所有的红色
1 2 3 4 func removeRed (var pixel : Pixel ) ->Pixel { pixel.red = 0 return pixel }
上述函数的作用为将每个读取到的像素的red值设为0之后再返回。
测试一下这个滤镜:
1 2 3 4 5 6 7 8 9 10 11 func testRemoveRedFilter (image : UIImage ) -> UIImage { var thisImage = RGBAImage (image: image)! for y in 0 ..< thisImage.height { for x in 0 ..< thisImage.width { let sub = y * thisImage.width + x let pixel = thisImage.pixels[sub] thisImage.pixels[sub] = removeRed(pixel) } } return thisImage.toUIImage()! }
上述函数作用为遍历图片中的每一个像素,应用上面取出红色的函数后,将像素返回图片。最终得到了如下图片:
upload successful
根据这个原理,可以进行各种滤镜的编写。
1、去除指定颜色
1 2 3 4 5 6 7 8 9 10 func removeColor (var pixel :Pixel ,conf :Int ) -> Pixel { if (conf == 0 ){ pixel.red = 0 }else if (conf == 1 ){ pixel.green = 0 }else if (conf == 2 ){ pixel.blue = 0 } return pixel }
传值0为去除红色,1为去除绿色,2为去除蓝色
运行结果如下
upload successful
2、灰度图
1 2 3 4 5 6 7 func grayScale (var pixel :Pixel ,conf :Int )->Pixel { let gray = UInt8 ((Int (pixel.red)+ Int (pixel.green)+ Int (pixel.blue))/ conf) pixel.red = gray pixel.green = gray pixel.blue = gray return pixel }
conf可以控制图片灰度,通常为3.对每个像素把他们的rgb值求平均值,这个像素就变成相应的灰色了。
运行结果如下
upload successful
3、更改透明度
像素rgba中的a值即为透明度,改变a值照片的透明度将发生变化
1 2 3 4 func transparentFilter (var pixel :Pixel ,opacity :Int )->Pixel { pixel.alpha = UInt8 (opacity) return pixel }
由于a为UInt8,因此需要转换。输入的opacity为透明度,从0-255
效果如下
upload successful
4、黑白照片
定义一个阀值,rgb平均值超过这个阀值的为白否则为黑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 func blackAndWhite (var pixel :Pixel ,conf :Int )->Pixel { if (conf== 1 ){ let avg = UInt8 ((Int (pixel.red)+ Int (pixel.green)+ Int (pixel.blue))/ 3 ) if (avg> 100 ){ pixel.red = 255 pixel.green = 255 pixel.blue = 255 }else { pixel.red = 0 pixel.green = 0 pixel.blue = 0 } }else { let avg = UInt8 ((Int (pixel.red)+ Int (pixel.green)+ Int (pixel.blue))/ 3 ) if (avg< 100 ){ pixel.red = 255 pixel.green = 255 pixel.blue = 255 }else { pixel.red = 0 pixel.green = 0 pixel.blue = 0 } } return pixel }
传值conf为0时生成黑白图片,如果为1则反色
效果如下
upload successful
5、反相
用255减去rgb值即为反相效果
1 2 3 4 5 6 func inverseColor (var pixel :Pixel ,conf :Int )->Pixel { pixel.red = min (max (UInt8 (conf) - pixel.red,0 ),255 ) pixel.green = min (max (UInt8 (conf) - pixel.green,0 ),255 ) pixel.blue = min (max (UInt8 (conf) - pixel.blue,0 ),255 ) return pixel }
要对减法得到的值进行约束防止出现负数。
效果如下
upload successful