I have been gradually getting my head around filters but I can't for the life of me get this to work and there are minimal articles about this specific filter.
I have a mask (png) with a gradient between white and black and an image and I can't get it to blur an image called bg.png. The app crashes out with:
'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key inputMaskImage.'
let mask = CIImage(image: UIImage(named: "mask.png")!)
let context = CIContext()
let filter = CIFilter(name: "CIMaskedVariableBlur")
filter?.setValue(mask, forKey: kCIInputMaskImageKey)
let image = CIImage(image: UIImage(named: "bg.png")!)
filter?.setValue(image, forKey: kCIInputImageKey)
let result = filter?.outputImage!
let cgImage = context.createCGImage(result!, from:(result?.extent)!)
let outputImg = UIImage(cgImage: cgImage!)
bgImage.image = outputImg
I have been playing around with different ways of doing it but all give the same error and I assume it is to do with the mask type?... I have no idea!
If you are targeting iOS 8, the key kCIInputMaskImageKey won't work. It's only for iOS 9 or later. But the good news is you can get things to work in iOS 8 by typing in the name of the keys. I usually do this anyways. Here's a function that should work for you:
func applyMaskedVariableBlur(image:UIImage, mask:UIImage) -> UIImage {
let filter = CIFilter(name: "CIMaskedVariableBlur")
// convert UIImages to CIImages and set as input
let ciInput = CIImage(image: image)
let ciMask = CIImage(image: mask)
filter?.setValue(ciInput, forKey: "inputImage")
filter?.setValue(ciMask, forKey: "inputMask")
// get output CIImage, render as CGImage first to retain proper UIImage scale
let ciOutput = filter?.outputImage
let ciContext = CIContext()
let cgImage = ciContext.createCGImage(ciOutput!, from: (ciOutput?.extent)!)
return UIImage(cgImage: cgImage!)
}
Related
I've created one UIView and change the background image to it by using the following code
slot1_view?.backgroundColor = UIColor(patternImage: UIImage(named: "drum_cut.png")!)
It's working fine on iphone but on ipad the background image become repeated.
How can I change its contentmode to something the fill the entire UIView?
Please help!!!!
Try this code-
Repeat:
var img = UIImage(named: "bg.png")
view.backgroundColor = UIColor(patternImage: img!)
Stretched
var img = UIImage(named: "bg.png")
view.layer.contents = img?.cgImage
Hope it helps!
Try this
let backgroundImage = UIImageView(frame: UIScreen.main.bounds)
backgroundImage.image = UIImage(named: "RubberMat")
backgroundImage.contentMode = UIViewContentMode.scaleAspectFill
self.view.insertSubview(backgroundImage, at: 0)
If you're using Swift5, try this on a button click event. you might need to do some layout margin for the UIView
myView?.contentMode = UIView.ContentMode.scaleToFill
myView.layer.contents = UIImage(named:"bg.png")?.cgImage
self.view.bringSubviewToFront(myView)
Swift 5
This work fine for view background image
let backgroundImage = UIImageView(frame: UIScreen.main.bounds)
backgroundImage.image = AppImageAssets.appAssets.appBackgroundImage()
backgroundImage.contentMode = UIView.ContentMode.scaleAspectFill
self.view.insertSubview(backgroundImage, at: 0)
To play videos in my project.I have created Custom video player(i.e AVplayerLayer instead of AVPlayerViewController) for custom controls.The problem is when i try to take a screenshot of videoPlayer it returns black image.
This is the code i have used to take a screenshot
func captureScreen() -> UIImage? {
UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, UIScreen.main.scale)
view.layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
Any suggestions would be greatly helpful!
If you need to take a snapshot of a view containing an AVPlayerLayer, to use in animations/freeze states, you can also use view.snapshotView(afterScreenUpdates:).
This returns a view with a screenshot of your view.
Handy in combination with UIVisualEffectView! :)
Try this,hope it will help you...
extension UIView
{
public func getSnapshotImage() -> UIImage
{
UIGraphicsBeginImageContextWithOptions(self.bounds.size, self.isOpaque, 0)
self.drawHierarchy(in: self.bounds, afterScreenUpdates: false)
let snapshotImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return snapshotImage
}
}
Usage:
let Snap = self.VideoPlayerView.getSnapshotImage
Since you are using AVPlayer rather than AVAssetReader+AVAssetReaderTrackOutput(which can take screen shot just along with playing)
I guess this will help you.
if let item = player.currentItem {
let imageGenerator = AVAssetImageGenerator(asset: item.asset)
imageGenerator.appliesPreferredTrackTransform = true
if let cgImage = try? imageGenerator.copyCGImage(at: item.currentTime(), actualTime: nil) {
let image = UIImage(cgImage: cgImage)
}
}
TIP: You can get that item at you own way. (e. the same when you create the AVPlayer)
The assumptions just for safty which compiler indicates you. (You can forced unwrapping of course)
Is there a more efficient way to animate text shivering with typewriting all in one sklabelnode? I'm trying to achieve the effect in some games like undertale where the words appear type writer style while they are shivering at the same time.
So far I've only been able to achieve it but with such luck:
class TextEffectScene: SKScene {
var typeWriterLabel : SKLabelNode?
var shiveringText_L : SKLabelNode?
var shiveringText_O : SKLabelNode?
var shiveringText_S : SKLabelNode?
var shiveringText_E : SKLabelNode?
var shiveringText_R : SKLabelNode?
var button : SKSpriteNode?
override func sceneDidLoad() {
button = self.childNode(withName: "//button") as? SKSpriteNode
self.scaleMode = .aspectFill //Very important for ensuring that the screen sizes do not change after transitioning to other scenes
typeWriterLabel = self.childNode(withName: "//typeWriterLabel") as? SKLabelNode
shiveringText_L = self.childNode(withName: "//L") as? SKLabelNode
shiveringText_O = self.childNode(withName: "//O") as? SKLabelNode
shiveringText_S = self.childNode(withName: "//S") as? SKLabelNode
shiveringText_E = self.childNode(withName: "//E") as? SKLabelNode
shiveringText_R = self.childNode(withName: "//R") as? SKLabelNode
}
// Type writer style animation
override func didMove(to view: SKView) {
fireTyping()
shiveringText_L?.run(SKAction.repeatForever(SKAction.init(named: "shivering")!))
shiveringText_O?.run(SKAction.repeatForever(SKAction.init(named: "shivering2")!))
shiveringText_S?.run(SKAction.repeatForever(SKAction.init(named: "shivering3")!))
shiveringText_E?.run(SKAction.repeatForever(SKAction.init(named: "shivering4")!))
shiveringText_R?.run(SKAction.repeatForever(SKAction.init(named: "shivering5")!))
}
let myText = Array("You just lost the game :)".characters)
var myCounter = 0
var timer:Timer?
func fireTyping(){
typeWriterLabel?.text = ""
timer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(TextEffectScene.typeLetter), userInfo: nil, repeats: true)
}
func typeLetter(){
if myCounter < myText.count {
typeWriterLabel?.text = (typeWriterLabel?.text!)! + String(myText[myCounter])
//let randomInterval = Double((arc4random_uniform(8)+1))/20 Random typing speed
timer?.invalidate()
timer = Timer.scheduledTimer(timeInterval: 0.2, target: self, selector: #selector(TextEffectScene.typeLetter), userInfo: nil, repeats: false)
} else {
timer?.invalidate() // stop the timer
}
myCounter += 1
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
if let location = touch?.location(in: self) {
if (button?.contains(location))! {
print("doggoSceneLoaded")
let transition = SKTransition.fade(withDuration: 0.5)
let newScene = SKScene(fileNamed: "GameScene") as! GameScene
self.view?.presentScene(newScene, transition: transition)
}
}
}
}
As you can see, I had to animate each individual label node in a word "loser".
To create this effect:
For those who may be interested to Swift 4 I've realized a gitHub project around this special request called SKAdvancedLabelNode.
You can find here all sources.
Usage:
// horizontal alignment : left
var advLabel = SKAdvancedLabelNode(fontNamed:"Optima-ExtraBlack")
advLabel.name = "advLabel"
advLabel.text = labelTxt
advLabel.fontSize = 20.0
advLabel.fontColor = .green
advLabel.horizontalAlignmentMode = .left
addChild(self.advLabel)
advLabel.position = CGPoint(x:frame.width / 2.5, y:frame.height*0.70)
advLabel.sequentiallyBouncingZoom(delay: 0.3,infinite: true)
Output:
something i have a lot of experience with... There is no way to do this properly outside of what you are already doing. My solution (for a text game) was to use NSAttributedString alongside CoreAnimation which allows you to have crazy good animations over UILabels... Then adding the UILabels in over top of SpriteKit.
I was working on a better SKLabel subclass, but ultimately gave up on it after I realized that there was no way to get the kerning right without a lot more work.
It is possible to use an SKSpriteNode and have a view as a texture, then you would just update the texture every frame, but this requires even more timing / resources.
The best way to do this is in the SK Editor how you have been doing it. If you need a lot of animated text, then you need to use UIKit and NSAttributedString alongside CoreAnimation for fancy things.
This is a huge, massive oversight IMO and is a considerable drawback to SpriteKit. SKLabelNode SUCKS.
As I said in a comment, you can subclass from an SKNode and use it to generate your labels for each characters. You then store the labels in an array for future reference.
I've thrown something together quickly and it works pretty well. I had to play a little bit with positionning so it looks decent, because spaces were a bit too small. Also horizontal alignement of each label has to be .left or else, it will be all crooked.
Anyway, it'S super easy to use! Go give it a try!
Here is a link to the gist I just created.
https://gist.github.com/sonoblaise/e3e1c04b57940a37bb9e6d9929ccce27
I have just changed my code to Swift 3 from swift 2.3. The following code is working fine with swift 2.3 but there is no effect with swift 3.
I want to develop a customise text editor. And let user to select text and change its color. For that i am using this code.
let selectedRange = textView.selectedRange
let currentAttr = textView.textStorage.attributes(at: selectedRange.location, effectiveRange: nil)
var attrName = NSForegroundColorAttributeName
if !isForeGround{
attrName = NSBackgroundColorAttributeName
}
if currentAttr[attrName] == nil || currentAttr[attrName] as! UIColor != selectedUIColor{
let dict = [attrName:selectedUIColor]
let currentFont = currentAttr[NSFontAttributeName]
let fontDescriptor = (currentFont! as AnyObject).fontDescriptor
let updatedFont = UIFont(descriptor: fontDescriptor!, size: 0.0)
let dict2 = [NSFontAttributeName: updatedFont]
textView.textStorage.beginEditing()
if currentAttr.count>0{
textView.textStorage.addAttributes(dict, range: selectedRange)
}else{
textView.textStorage.setAttributes(dict, range: selectedRange)
}
textView.textStorage.addAttributes(dict2, range: selectedRange)
textView.textStorage.endEditing()
}
Runs successfully but there is no effect on text color.
This worked for me.
First you need to catch your selected text, with:
let selectedText = textView.selectedRange
Then, you create the attribute:
let myAttribute = [ NSForegroundColorAttributeName: selectedUIColor]
And lastly:
textView.textStorage.addAttributes(myAttribute, range: selectedText)
This must be in an Action called by any sender
Hope it works also for you!
Regards
Selected text can be changed with
self.textView.tintColor = .red
I am using swift 3. When I hit a specific string while going through a for loop of iterated geojson data (jsonObj[i]) I need it to call the right image file. I am able to return the right pass type and load my markers in the map correctly. I just can't seem to figure out how to get the app to load the right color per marker type.
I have tried a switch statement but with no luck. I have looked at the if statement documentation among many other stack overflow posts and tutorials.
var pass : String?
var brown = UIImage(named: "brown.png")
var purple = UIImage(named: "purple.png")
var green = UIImage(named: "green.png")
var image : UIImage?
The block of code below is in the for loop. So each record that is iterated through loads that into a marker as a title and subtitle. With this code it reads the first marker color "purple" and loads all points with the purple marker instead of selecting based on pass1, pass2 that is returned.
var pass = jsonObj[i]["properties"]["Pass"]
print("propertiesPassString: ", pass)
if pass == "pass1" {
print("Pass1!")
image = purple
}
else if pass == "pass2" {
print("Pass2")
image = brown
}
else if pass == "" {
print("Pass3")
image = green
}
Here is the func that loads the marker, not sure if this is needed but it applies or loads the "image" or custom marker/variable in each iteration of the for loop. This is largely copy and pasted from mapbox ios sdk
func mapView(_ mapView: MGLMapView, annotationCanShowCallout annotation: MGLAnnotation) -> Bool {
// Always try to show a callout when an annotation is tapped.
return true
}
func mapView(_ mapView: MGLMapView, imageFor annotation: MGLAnnotation) -> MGLAnnotationImage? {
// Try to reuse the existing ‘point’ annotation image, if it exists.
var annotationImage = mapView.dequeueReusableAnnotationImage(withIdentifier: "point")
if annotationImage == nil {
print("annotationImage")
image = image?.withAlignmentRectInsets(UIEdgeInsets(top: 0, left: 0, bottom: (image?.size.height)!/2, right: 0))
// Initialize the ‘point’ annotation image with the UIImage we just loaded.
annotationImage = MGLAnnotationImage(image: image!, reuseIdentifier: "point")
}
//image = nil
return annotationImage!
}
If you have any advice/suggestions for a newer programmer in swift 3 I would certainly appreciate it. I've been stuck on this for several days now. I am still learning how to utilize stack overflow as well so please let me know if there is a better way to go about posting this question, I am open to constructive critiques.