如何反转 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 特定区域的颜色?的主要内容,如果未能解决你的问题,请参考以下文章

UIView.mask设置颜色

在 UIImageView 上反转颜色

悬停在链接上时如何反转整个页面的颜色

matlab中如何给特定区域填充色彩?

Python:如何从图像中切出具有特定颜色的区域(OpenCV,Numpy)

UIView背景颜色和顶部透明png