如何反转UIView特定区域的颜色?

时间:2016-11-23 10:17:53

标签: ios swift uiview

很容易模糊视图的一部分,请记住,如果后面的视图内容发生变化,模糊也会实时变化。

我的问题

  1. 如何制作反转效果,可以将其放在视图上,背后的内容会反转颜色

  2. 如何添加能够知道背后像素的平均颜色的效果?

  3. 一般来说,如何访问像素并操纵它们? 我的问题不是关于UIImageView,一般询问UIView ..

    有些库可以做类似的事情,但是它们非常慢,并且运行不像模糊那样平滑!

    感谢。

3 个答案:

答案 0 :(得分:8)

如果您知道如何编写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等),但这是一个好的开始。

最后一点,您可以链接各个过滤器(包括手写颜色,扭曲和一般内核)。如果需要,您可以使用模糊链接基础视图上的颜色平均值,并将您希望的任何类型的反转作为单个过滤器/效果进行链接。

答案 1 :(得分:1)

我认为我不能完全回答你的问题,但也许我可以指出你正确的方向。

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编写的,已经有几年了,但也许你可以弄清楚如何充分利用它。

答案 2 :(得分:0)

第一,我将建议您为此目的扩展UIImageView。 ref

Joe的好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://stackoverflow.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