Как инвертировать цвета определенной области UIView?
Легко размыть часть представления, имея в виду, что при изменении содержимого заметок размытие также меняется в реальном времени.
![]()
Мои вопросы
-
Как сделать инвертированный эффект, и вы можете поместить его над представлением, а содержимое позади будет иметь инвертированные цвета.
-
Как добавить эффект, который будет знать средний цвет пикселей позади?
В общем, Как получить доступ к пикселям и манипулировать ими?
Мой вопрос не о UIImageView, спрашивая о UIView вообще.
есть библиотеки, которые делают что-то подобное, но они настолько медленны и не работают так гладко, как размытие!
Спасибо.
Ответы
Ответ 1
Если вы знаете, как закодировать CIColorKernel, вы получите то, что вам нужно.
-
В Core Image есть несколько фильтров размытия, которые используют графический процессор, который даст вам необходимую производительность.
-
CIAreaAverage даст вам средний цвет для указанной прямоугольной области.
Основные фильтры изображений
Вот про простейшее 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 и т.д.), Но это хорошее начало.
В последней заметке вы можете связать отдельные фильтры (включая рукописный цвет, warp и общие ядра). Если вы хотите, вы можете связать свой средний цвет по основному виду с размытием и сделать любую инверсию, которую вы хотите, в качестве одного фильтра/эффекта.
Ответ 2
Я не думаю, что могу полностью ответить на ваш вопрос, но, возможно, я могу указать вам в правильном направлении.
У Apple есть документация по доступу к данным пикселей из CGImages, но, конечно, для этого требуется, чтобы у вас было изображение, с которым можно работать в первое место. К счастью, вы можете создать образ из UIView следующим образом:
UIGraphicsBeginImageContext(view.frame.size)
view.layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
Из этого изображения, которое вы создали, вы сможете управлять данными пикселей, как вы хотите. Возможно, это не самый чистый способ решить вашу проблему, но, возможно, это что-то стоит изучить.
К сожалению, ссылка, которую я предоставил, написана в Objective-C и ей несколько лет, но, возможно, вы можете понять, как ее использовать.
Ответ 3
В первую очередь я рекомендую вам расширить UIImageView для этой цели. ref
Хорошо ref от Joe
Вы должны переопределить метод 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/info/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()
}
}
Ваш ответ здесь