如何反转 UIView 特定区域的颜色?
Posted
技术标签:
【中文标题】如何反转 UIView 特定区域的颜色?【英文标题】:How to invert colors of a specific area of a UIView? 【发布时间】:2016-11-23 10:17:53 【问题描述】:模糊视图的一部分很容易,请记住,如果后面的视图内容发生变化,模糊也会实时变化。
我的问题
如何做一个反色效果,你可以把它放在一个视图上,后面的内容就会有反色
如何添加可以知道后面像素平均颜色的效果?
一般来说,如何访问像素并对其进行操作? 我的问题不是关于 UIImageView,而是一般地询问 UIView..
有一些库可以做类似的事情,但它们太慢了,而且运行起来不像 blur 那样流畅!
谢谢。
【问题讨论】:
查看这个项目github.com/freshking/BKFilterView 这个库太慢了:( 阅读已经完成此任务的库中的代码,并使用该代码了解如何构建自己的过滤器。 【参考方案1】:如果您知道如何编写 CIColorKernel,您将拥有所需的一切。
Core Image 有几个模糊滤镜,所有这些滤镜都使用 GPU,这将为您提供所需的性能。
CIAreaAverage 将为您提供指定矩形区域的平均颜色。
Core Image Filters
这里是关于您可以编写的最简单的 CIColorKernel。它交换图像中每个像素的红色和绿色值(注意“grba”而不是“rgba”):
kernel vec4 swapRedAndGreenAmount(__sample s)
return s.grba;
要将其放入 CIColorKernel,只需使用以下代码行:
let swapKernel = CIKernel(string:
"kernel vec4 swapRedAndGreenAmount(__sample s) " +
"return s.grba;" +
""
@tww003 有很好的代码将视图层转换为 UIImage。假设你调用你的镜像 myUiImage,来执行这个 swapKernel,你可以:
let myInputCi = CIImage(image: myUiImage)
let myOutputCi = swapKernel.apply(withExtent: myInputCi, arguments: myInputCi)
Let myNewImage = UIImage(ciImage: myOutputCi)
就是这样。您可以做更多事情(包括使用 CoreGraphics 等),但这是一个好的开始。
最后一点,您可以链接各个过滤器(包括手写颜色、扭曲和通用内核)。如果你愿意,你可以将你的颜色平均值链接到带有模糊的底层视图上,并做任何你想要的反转作为单个过滤器/效果。
【讨论】:
【参考方案2】:我认为我不能完全回答您的问题,但也许我可以为您指明正确的方向。
Apple has some documentation on accessing the pixels data from CGImages,当然这首先需要你有一个可以使用的图像。幸运的是,您可以像这样从 UIView 创建图像:
UIGraphicsBeginImageContext(view.frame.size)
view.layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
从您创建的这张图片中,您将能够按照自己的意愿操作像素数据。它可能不是解决问题的最干净的方法,但也许值得探索。
不幸的是,我提供的链接是用 Objective-C 编写的,并且已经有几年的历史了,但也许你可以弄清楚如何充分利用它。
【讨论】:
【参考方案3】:1st 我会推荐你扩展 UIImageView 来达到这个目的。 ref
好的ref乔
你必须重写drawRect
方法
import UIKit
@IBDesignable class PortholeView: UIView
@IBInspectable var innerCornerRadius: CGFloat = 10.0
@IBInspectable var inset: CGFloat = 20.0
@IBInspectable var fillColor: UIColor = UIColor.grayColor()
@IBInspectable var strokeWidth: CGFloat = 5.0
@IBInspectable var strokeColor: UIColor = UIColor.blackColor()
override func drawRect(rect: CGRect)
super.drawRect(rect:rect)
// Prep constants
let roundRectWidth = rect.width - (2 * inset)
let roundRectHeight = rect.height - (2 * inset)
// Use EvenOdd rule to subtract portalRect from outerFill
// (See https://***.com/questions/14141081/uiview-drawrect-draw-the-inverted-pixels-make-a-hole-a-window-negative-space)
let outterFill = UIBezierPath(rect: rect)
let portalRect = CGRectMake(
rect.origin.x + inset,
rect.origin.y + inset,
roundRectWidth,
roundRectHeight)
fillColor.setFill()
let portal = UIBezierPath(roundedRect: portalRect, cornerRadius: innerCornerRadius)
outterFill.appendPath(portal)
outterFill.usesEvenOddFillRule = true
outterFill.fill()
strokeColor.setStroke()
portal.lineWidth = strokeWidth
portal.stroke()
你的答案是here
【讨论】:
以上是关于如何反转 UIView 特定区域的颜色?的主要内容,如果未能解决你的问题,请参考以下文章