Comment inverser les colors d'une zone spécifique d'un UIView?

Il est facile de rendre floue une partie de la vue, en gardant à l'esprit que si le contenu des vues est modifié, le flou change aussi en time réel.

Mes questions

  1. Comment faire un effet inversé, et vous pouvez le mettre sur une vue et le contenu derrière aurait des colors inversées

  2. Comment append un effet qui connaîtrait la couleur moyenne des pixels derrière?

En général, Comment accéder aux pixels et les manipuler? Ma question ne concerne pas UIImageView, mais pose des questions sur UIView en général.

il y a des bibliothèques qui font quelque chose de similaire, mais elles sont si lentes et ne fonctionnent pas aussi bien que le flou!

Merci.

Si vous savez coder un CIColorKernel, vous aurez ce dont vous avez besoin.

  • Core Image a plusieurs filters de flou, qui utilisent tous le GPU, ce qui vous donnera les performances dont vous avez besoin.

  • CIAreaAverage vous donnera la couleur moyenne pour une zone rectangular spécifiée.

Filtres d'image de base

Voici le CIColorKernel le plus simple que vous pouvez écrire. Il échange la valeur rouge et verte pour chaque pixel d'une image (notez le "grba" au lieu de "rgba"):

kernel vec4 swapRedAndGreenAmount(__sample s) { return s.grba; } 

Pour mettre ceci dans un CIColorKernel, utilisez simplement cette ligne de code:

 let swapKernel = CIKernel(ssortingng: "kernel vec4 swapRedAndGreenAmount(__sample s) {" + "return s.grba;" + "}" 

@ tww003 a un bon code pour convertir la couche d'une vue en UIImage. En supposant que vous appelez votre image myUiImage, pour exécuter ce swapKernel, vous pouvez:

 let myInputCi = CIImage(image: myUiImage) let myOutputCi = swapKernel.apply(withExtent: myInputCi, arguments: myInputCi) Let myNewImage = UIImage(ciImage: myOutputCi) 

C'est à peu près ça. Vous pouvez en faire beaucoup plus (y compris en utilisant CoreGraphics, etc.) mais c'est un bon début.

Une dernière note, vous pouvez enstringr des filters individuels (y compris la couleur manuscrite, warp, et les kernelx généraux). Si vous le souhaitez, vous pouvez enstringr votre moyenne de couleur sur la vue sous-jacente avec un flou et effectuer le type d'inversion souhaité en tant que filter / effet unique.

Je ne pense pas pouvoir répondre entièrement à votre question, mais je peux peut-être vous orienter dans la bonne direction.

Apple a quelques documents sur l'access aux données de pixels à partir de CGImages , mais bien sûr cela nécessite que vous ayez une image pour travailler en premier lieu. Heureusement, vous pouvez créer une image à partir d'un UIView comme ceci:

  UIGraphicsBeginImageContext(view.frame.size) view.layer.render(in: UIGraphicsGetCurrentContext()!) let image = UIGraphicsGetImageFromCurrentImageContext() UIGraphicsEndImageContext() 

À partir de cette image que vous avez créée, vous serez en mesure de manipuler datatables de pixels comme vous le souhaitez. Ce n'est peut-être pas la façon la plus propre de résoudre votre problème, mais c'est peut-être quelque chose qui mérite d'être étudié.

Malheureusement, le lien que j'ai fourni est écrit en Objective-C et a quelques années, mais peut-être que vous pouvez comprendre comment en faire un bon usage.

Je vous recommand d'étendre UIImageView à cette fin. ref

Bonne reference par Joe

Vous devez replace la méthode 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() } } 

Votre réponse est ici