GPUImagePoissonBlendFilter produces weird result - swift

I am trying to use GPUImage (Objective-C) pod in order to blend two images with GPUImagePoissonBlendFilter in Swift project.
The result is kinda weird and I don't understand how to fix it.
Sample project:
Back image
Front image
Result image
What is going on in code:
Load Back image into backImage
Load Front image into frontImage
Blend images with GPUImagePoissonBlendFilter
Result put to imageView
class ViewController: UIViewController {
private let imageView: UIImageView = {
let image = UIImage(named: "back")
let imageView = UIImageView(image: image)
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.layer.borderWidth = 1
imageView.layer.borderColor = UIColor.green.cgColor
return imageView
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.black
view.addSubview(imageView)
NSLayoutConstraint.activate([
imageView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 10),
imageView.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor)
])
guard let backImage = imageView.image else { return }
guard let frontImage = UIImage(named: "front") else { return }
let backImageSource = GPUImagePicture(image: backImage)
let frontImageSource = GPUImagePicture(image: frontImage)
let poisionFilter = GPUImagePoissonBlendFilter()
poisionFilter.mix = 0.9
poisionFilter.numIterations = 100
backImageSource?.addTarget(poisionFilter, atTextureLocation: 0)
frontImageSource?.addTarget(poisionFilter)
backImageSource?.processImage()
frontImageSource?.processImage()
poisionFilter.useNextFrameForImageCapture()
let filterResult = poisionFilter.imageFromCurrentFramebuffer()
imageView.image = filterResult
}}
Can anyone point what I am doing wrong here ?
Thanks in advance !

Related

Scroll view paging content size doesn't work with iphone 5s ios 12

I have an horizontal paging scroll view with 3 images.
This is the code in my viewDidLoad:
for index in 0..<images.count {
frame.origin.x = scrollView.frame.size.width * CGFloat(index)
frame.size = scrollView.frame.size
let UrlImage = NSURL(string: images[index] as! String)
let dataImage = NSData(contentsOf: UrlImage! as URL)
if dataImage != nil {
let imgView = UIImageView(frame: frame)
imgView.image = UIImage(data: dataImage! as Data)
imgView.contentMode = .scaleAspectFit
self.scrollView.backgroundColor = .lightGray
self.scrollView.addSubview(imgView)
}
}
scrollView.contentSize = CGSize(width: (scrollView.frame.size.width * CGFloat(images.count)), height: scrollView.frame.size.height)
scrollView.delegate = self
and this is the result:
If i try with last iphone devices it works properly. But if i try with iphone 5s with ios12, content size doesn't work and this is the result:
How can i fix this? I'v been trying for 3 days
I'm assuming you have code to handle the page control and scroll delegate(s)...
Here's a very simple example of using a UIStackView to hold the 3 image views:
class ViewController: UIViewController {
let scrollView = UIScrollView()
let stack = UIStackView()
let pageControl = UIPageControl()
override func viewDidLoad() {
super.viewDidLoad()
// scroll view properties
scrollView.backgroundColor = .gray
scrollView.isPagingEnabled = true
// stack view properties
stack.axis = .horizontal
stack.alignment = .fill
stack.distribution = .fillEqually
stack.spacing = 0
// page control properties
pageControl.backgroundColor = .white
pageControl.pageIndicatorTintColor = .darkGray
pageControl.currentPageIndicatorTintColor = .blue
// we're going to use constraints
scrollView.translatesAutoresizingMaskIntoConstraints = false
stack.translatesAutoresizingMaskIntoConstraints = false
pageControl.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(stack)
view.addSubview(scrollView)
view.addSubview(pageControl)
// respect safe area
let g = view.layoutMarginsGuide
NSLayoutConstraint.activate([
// scroll view constrained Top / Leading / Trailing
scrollView.topAnchor.constraint(equalTo: g.topAnchor),
scrollView.leadingAnchor.constraint(equalTo: g.leadingAnchor),
scrollView.trailingAnchor.constraint(equalTo: g.trailingAnchor),
// scroll view height = 1/2 of view height
scrollView.heightAnchor.constraint(equalTo: g.heightAnchor, multiplier: 0.5),
// stack view constrained Top / Bottom / Leading / Trailing of scroll view
stack.topAnchor.constraint(equalTo: scrollView.topAnchor),
stack.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
stack.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
stack.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
// stack view height == scroll view height
stack.heightAnchor.constraint(equalTo: scrollView.heightAnchor),
// page control centered horizontally just below the scroll view
pageControl.topAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 4.0),
pageControl.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor),
])
// add three image views to the stack view
for _ in 1...3 {
let v = UIImageView()
v.backgroundColor = .lightGray
v.contentMode = .scaleAspectFit
stack.addArrangedSubview(v)
}
// stack distribution is set to .fillEqually, so we only need to set the
// width constraint on the first image view
// unwrap it
if let v = stack.arrangedSubviews.first {
// stack view has 8-pts on each side
v.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
}
pageControl.numberOfPages = 3
// set delegates...
// implement page control funcs...
// etc...
// start image retrieval process
downloadImages()
}
func downloadImages() -> Void {
// get 3 "placeholder" images
// 400x300 400x400 300x400
let urls: [String] = [
"https://via.placeholder.com/400x300.png/FF0000/FFF",
"https://via.placeholder.com/400x400.png/00AA00/FFF",
"https://via.placeholder.com/300x400.png/0000FF/FFF",
]
for (v, urlString) in zip(stack.arrangedSubviews, urls) {
if let imgView = v as? UIImageView, let url = URL(string: urlString) {
imgView.load(url: url)
}
}
}
}
// async download image url from: https://www.hackingwithswift.com/example-code/uikit/how-to-load-a-remote-image-url-into-uiimageview
extension UIImageView {
func load(url: URL) {
DispatchQueue.global().async { [weak self] in
if let data = try? Data(contentsOf: url) {
if let image = UIImage(data: data) {
DispatchQueue.main.async {
self?.image = image
}
}
}
}
}
}

Can't set size for UIImageView

I have a UIImageView, I'm trying to give it a fixed size, but it won't work, the size of the UIImageView just won't change.
this is my UIImageView:
private let profileImg: UIImageView = {
let img = UIImageView(image: UIImage(named: "profileplaceholder"))
img.contentMode = .scaleAspectFill
img.layer.borderWidth = 1.0
img.layer.borderColor = UIColor.appPurple.cgColor
img.layer.cornerRadius = img.frame.width / 2
img.clipsToBounds = true
img.frame.size.width = 80
img.frame.size.height = 80
return img
}()
I added the image to a UIStackView like that:
private lazy var mStack: UIStackView = {
let stack = UIStackView(arrangedSubviews: [self.profileImg, self.nickname, self.unfollowBtn])
stack.translatesAutoresizingMaskIntoConstraints = false
stack.distribution = .fill
stack.axis = .horizontal
stack.spacing = 1.0
return stack
}()
StackView will resize it's elements. You should give it constraint for fixed size:
private let profileImg: UIImageView = {
...
img.translatesAutoresizingMaskIntoConstraints = false
img.heightAnchor.constraint(equalToConstant: 80).isActive = true
img.widthAnchor.constraint(equalToConstant: 80).isActive = true
...
}()

Images not being rounded in UIStackView

I'm trying to round several images and add them in a stack view, for some reason it's not working. Basically, I have an array with all UIImage names and assign them to a UIImageView. When I try to make a circle out of the image, it's not working :
var navStackView : UIStackView = {
let stack = UIStackView()
stack.axis = .horizontal
stack.alignment = .center
stack.distribution = .fillEqually
// stack.spacing = -10
stack.translatesAutoresizingMaskIntoConstraints = false
return stack
}()
var images = ["1", "2", "3", "4"]
override func viewDidLoad() {
super.viewDidLoad()
let navController = navigationController!
navController.navigationBar.addSubview(navStackView)
// x, y, w, h
navStackView.leadingAnchor.constraint(equalTo: navController.navigationBar.leadingAnchor).isActive = true
navStackView.trailingAnchor.constraint(equalTo: navController.navigationBar.trailingAnchor).isActive = true
navStackView.topAnchor.constraint(equalTo: navController.navigationBar.topAnchor).isActive = true
navStackView.bottomAnchor.constraint(equalTo: navController.navigationBar.bottomAnchor).isActive = true
for image in images {
let imageView = UIImageView()
imageView.image = UIImage(named: image)
imageView.layer.cornerRadius = imageView.frame.height / 2
imageView.clipsToBounds = true
imageView.layer.masksToBounds = false
imageView.contentMode = .scaleAspectFit
// imageView.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
navStackView.addArrangedSubview(imageView)
navStackView.layoutIfNeeded()
}
navigationItem.titleView = navStackView
}
You can try
var once = true
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if once {
navStackView.subviews.forEach { $0.layer.cornerRadius = $0.frame.height / 2 }
once = false
}
}

AddGesture different in Swift 3?

I have no idea why my code isn't working :
let profileImageView: UIImageView = {
let image = UIImageView()
image.image = UIImage(named: "gameofthrones_splash")
image.translatesAutoresizingMaskIntoConstraints = false
image.contentMode = .scaleAspectFill
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleSelectProfileImageView))
image.addGestureRecognizer(tapGesture)
image.isUserInteractionEnabled = true
return image
}()
This imageView is loaded in the ViewDidLoad (I can see it)
func handleSelectProfileImageView() {
print("123")
}
But nothing get returned in the console when I'm tapping on it ! WTF?
It's in the target. This works when place in the viewDidLoad():
profileImageView.frame = CGRect(x: 60, y: 60, width: 70, height: 70)
view.addSubview(profileImageView)
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleSelectProfileImageView))
profileImageView.addGestureRecognizer(tapGesture)
The target is "self", which is the UIViewController (not the UIImageView). In most cases (I'm sure there are outliers) you want to record a gesture in a view, but work with the gesture in a view controller.
Okay the solution was quite simple actually. You have to make it a lazy var instead of a let.
lazy var profileImageView: UIImageView = {
let image = UIImageView()
image.image = UIImage(named: "gameofthrones_splash")
image.translatesAutoresizingMaskIntoConstraints = false
image.contentMode = .scaleAspectFill
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleSelectProfileImageView))
image.addGestureRecognizer(tapGesture)
image.isUserInteractionEnabled = true
return image
}()
Swift 3.0:
There was some error I removed it -
Put this code in viewdidLoad
override func viewDidLoad() {
super.viewDidLoad()
var profileImageView:UIImageView {
var image = UIImageView()
image.backgroundColor = UIColor.red;
image.frame = CGRect(x: 0, y: 0, width: 44, height: 44)
image.translatesAutoresizingMaskIntoConstraints = false
image.contentMode = .scaleAspectFill
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleSelectProfileImageView))
image.addGestureRecognizer(tapGesture)
image.isUserInteractionEnabled = true
return image
}
view.addSubview(profileImageView);
// Do any additional setup after loading the view.
}
func handleSelectProfileImageView() {
print("123")
}
Just to test I removed the image, you can add it. But it's working fine.
I fixed this issue using an UIButton ->
let profileImageView: UIButton = {
let iv = UIButton()
let image = UIImage(named: "r2d2")
iv.setImage(image, for: .normal)
iv.translatesAutoresizingMaskIntoConstraints = false
iv.addTarget(self, action: #selector(selectProfileImage), for: .touchUpInside)
iv.isUserInteractionEnabled = true
return iv
}()
#objc func selectProfileImage(){
print("Hello")
}

Nested Stack Views: Child Stack View is not inside its parent stack view when attaching it programmatically

I'm trying to implement nested stack views in which one stack view is inside another stack view. I've based my code here. My current code is here below.
#IBOutlet weak var verticalStackView: UIStackView!
let blueImageView = UIImageView()
blueImageView.backgroundColor = UIColor.blueColor()
blueImageView.image = UIImage(named: "just some image")
blueImageView.snp_makeConstraints { (make) in
make.height.width.equalTo(34)
}
let greenImageView = UIImageView()
greenImageView.backgroundColor = UIColor.greenColor()
greenImageView.image = UIImage(named: "just some image")
// This is just from SnapKit
greenImageView.snp_makeConstraints { (make) in
make.height.width.equalTo(34)
}
let stackView = UIStackView()
stackView.axis = UILayoutConstraintAxis.Horizontal
stackView.distribution = UIStackViewDistribution.EqualSpacing
stackView.alignment = UIStackViewAlignment.Center
stackView.spacing = 16.0
stackView.addArrangedSubview(blueImageView)
stackView.addArrangedSubview(greenImageView)
stackView.translatesAutoresizingMaskIntoConstraints = false;
// This is just from SnapKit
verticalStackView.snp_makeConstraints { (make) in
make.height.equalTo(70)
}
verticalStackView.addSubview(stackView)
When I tried running it looks this way.
As you can see, the sub stack view stackView is below the parent stack view (verticalStackView) in the hierarchy. But the positioning is off.
I'm quite new with Swift, AutoLayout and StackViews. Anyone that can help point out what I'm missing here?
Thanks!
So I've figured out the solution after some reading..
#IBOutlet weak var verticalStackView: UIStackView!
let blueImageView = UIImageView()
blueImageView.backgroundColor = UIColor.blueColor()
blueImageView.image = UIImage(named: "buttonFollowCheckGreen")
blueImageView.snp_makeConstraints { (make) in
make.height.width.equalTo(34)
}
let greenImageView = UIImageView()
greenImageView.backgroundColor = UIColor.greenColor()
greenImageView.image = UIImage(named: "buttonFollowCheckGreen")
greenImageView.snp_makeConstraints { (make) in
make.height.width.equalTo(34)
}
let firstLineStackView = UIStackView()
firstLineStackView.axis = UILayoutConstraintAxis.Horizontal
firstLineStackView.distribution = UIStackViewDistribution.Fill
firstLineStackView.alignment = UIStackViewAlignment.Center
firstLineStackView.spacing = 8.0
firstLineStackView.addArrangedSubview(blueImageView)
firstLineStackView.addArrangedSubview(greenImageView)
firstLineStackView.translatesAutoresizingMaskIntoConstraints = false;
let redImageView = UIImageView()
redImageView.backgroundColor = UIColor.redColor()
redImageView.image = UIImage(named: "buttonFollowCheckGreen")
redImageView.snp_makeConstraints { (make) in
make.height.width.equalTo(34)
}
verticalStackView.addArrangedSubview(firstLineStackView)
I just had to use addArrangedSubview instead of addSubview and let Auto layout do the rest. Just to fix the positioning and size of the image views, I've also modified the alignment of the verticalStackView from fill to leading.
greenImageView.heightAnchor.constraint(equalToConstant: 34).isActive = true
greenImageView.widthAnchor.constraint(equalToConstant: 34).isActive = true
and it will be solved