Get an image from two imageViews in Swift - ios

I'm developing an app where I have an area where there is an image in the background, and another image that I can move, like a sticker.
My goal is to create and save an image with the background image and the "sticker" above, using Swift. Here's my function that allows me to do what I want (my background view is called "imageView", my imageview sticker is called "jacques") :
let newSize = CGSizeMake(imageView.image!.size.width, imageView.image!.size.height)
UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0);
imageView.image!.drawInRect(CGRectMake(0,0,newSize.width,newSize.height))
let jacquesX = ((jacques.frame.origin.x - imageView.frame.origin.x) * (imageView.image?.size.width)!) / UIScreen.mainScreen().bounds.width
let jacquesY = ((jacques.frame.origin.y - imageView.frame.origin.y) * (imageView.image?.size.height)!) / UIScreen.mainScreen().bounds.height
let jacquesWidth: CGFloat = jacques.image!.size.width
let jacquesHeight: CGFloat = jacques.image!.size.height
jacques.image!.drawInRect(CGRectMake(jacquesX, jacquesY, jacquesWidth, jacquesHeight))
let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
UIImageWriteToSavedPhotosAlbum(newImage, self, "image:didFinishSavingWithError:contextInfo:", nil)
Unfortunately, my sticker isn't the right size. I think it's well placed in the image, but it's size is way too small. I don't know if my solution is the best one, i'm open to all suggestion. And I'm new, so if you have good practice to share, i'm all ears :)

You could do this in the storyboard. First you could size the picture however you want. To create a sticker effect you could just add imageView, size it to background size,and then put jacques on the storyboard, and finally resize them.

Related

Scale an Image in ImageView (Scale x,y) - IOS

I usually scale the image of an imageView in Android with the scaleX and scaleY properties.
How can I do the same in IOS? I'm really new with IOS,I'm using swift 3 and I didn't find any analog thing like that.
If you need to scale the image proportionally, the following code might work for you:
if let cgImage = imageView.image?.cgImage, let orientation = imageView.image?.imageOrientation {
imageView.image = UIImage(cgImage: cgImage, scale: newScale, orientation: orientation)
}
However, if you only want to display it with a size different than that of the original image, you should control the size of the image using the size of the UIImageView that presents it. To make sure the image scales correctly with the size of the view, take a look at the UIImageView.contentMode property: https://developer.apple.com/reference/uikit/uiview/1622619-contentmode

Best performance solution for background image of 100 UIButtons

I have a UICollectionView with approximately 100 cells with a rounded button inside each cell. 5 cells per row, so I have to scroll down and up to select the buttons.
When the buttons are selected, the background image changes. I've done this in several ways which I expose below. Maybe it is not a very demanding view, but I was wondering what is the less expensive approach in terms of performance.
One solution I found is using an extension of UIImage and setting the button.layer.cornerRadius like this:
extension UIImage {
class func imageWithColor(color: UIColor?) -> UIImage! {
let rect = CGRectMake(0.0, 0.0, 1.0, 1.0)
UIGraphicsBeginImageContextWithOptions(rect.size, false, 0)
let context = UIGraphicsGetCurrentContext();
if let color = color {
color.setFill()
}
else {
UIColor.whiteColor().setFill()
}
CGContextFillRect(context, rect);
let image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image
}
and then, setting the button image background with:
button.layer.cornerRadius = (cell.bounds.width - 8) / 2
button.clipsToBounds = true
button.setBackgroundImage(UIImage.imageWithColor(UIColor.greenColor()), forState: UIControlState.Selected)
I've heard that setting the layer.cornerRadius is pretty expensive.
Another approach would be just designing an squared image, in Photoshop or similar, with a circle in the middle and letting the rest transparent and setting it as button background.
Or another option, that I still haven't tried, I think it could be making an 1 x 1 pixels image with a color and setting the filling of the background as tile(I still haven checked the code for this one). But I think this is pretty similar to the first way.
Would you solve this questions measuring the performance with any software or just knowing more deeply the Swift language?
Try applying mask to image. It's better because you do it once for each image. This should not affect scroll performance. Only what you need is mask image. It should be square image with white background and black circle in middle. Here you can find example (obj-c). Swift:
extension UIImage {
func maskedImage(mask: UIImage) -> UIImage {
let maskImgRef = mask.CGImage
let maskRef = CGImageMaskCreate(CGImageGetWidth(maskImgRef), CGImageGetHeight(maskImgRef), CGImageGetBitsPerComponent(maskImgRef), CGImageGetBitsPerPixel(maskImgRef), CGImageGetBytesPerRow(maskImgRef), CGImageGetDataProvider(maskImgRef), nil, false)
if let maskedRef = CGImageCreateWithMask(self.CGImage, maskRef) {
let maskedIm = UIImage(CGImage: maskedRef)
UIGraphicsBeginImageContext(maskedIm.size)
maskedIm.drawInRect(CGRect(origin: CGPointZero, size: maskedIm.size))
let img = UIGraphicsGetImageFromCurrentImageContext()
return img
}
return self
}
}
UPD: code above is helpful if your images isn't monochrome. If they are monochrome you can use UIButtons with system type instead of ImageViews. Just disable userInteraction, set circled image for this buttons and manipulate tintColor.

How can I add stickers to an image in Swift?

I'm working on a Swift iOS app where I want the user to be able to place an image (a sticker such as a beard or an eyepatch) over another image.
Currently I have it working to where they can take a photo or pull an image up from their Photos and have that display in a UIImage. Obviously next is adding the sticker. I've been able to dig up zero data on this from Google or Stack. And I mean zero.
Does anyone have a general idea of how I would execute this? Specifics would help too of course.
Here's the easy way.
have a UIView as a parent, let's say stickerView
add image to stickerView
add stickers to stickerView
save a snapshot of stickerView
Here's the code to snapshot UIView,
extension UIImage {
class func imageWithView(view: UIView) -> UIImage {
UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0)
view.drawViewHierarchyInRect(view.bounds, afterScreenUpdates: true)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img
}
}
Usage
let snapshotImage = UIImage.imageWithView(stickerView)
I would suggest you to add UIImageView for sticker instead of editing image when adding sticker. And after that when save the image then you should edit the image.

Merge two imageViews into one and save iOS swift

I have 2 imageViews like below. (ScrollView has subview of imageView)
i want to take the image of each one and merged to one.
i tried using taking screenshot and crop. but when it comes to different iphone screensizes and resolutions it doesn't work well.
can any one guide me how to do this?
Why not just add them both to one UIView?
It is also possible to add a subview to your image view and extend the frame.
[secondImageView setFrame:CGRectMake(x,y + newImageHeight,width,height)];
[self.myImageView setFrame:CGRectMake(x,y,width,height + newImageHeight)];
[self.myImageView addSubview:secondImageView];
I think your way is right, also you can solve scale size problem very easily with this method.
func mergeScreenshot() {
let layer = UIApplication.sharedApplication().keyWindow.layer
let scale = UIScreen.mainScreen().scale
UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale); // reconsider size property for your screenshot
layer.renderInContext(UIGraphicsGetCurrentContext())
let screenshot = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
UIImageWriteToSavedPhotosAlbum(screenshot, nil, nil, nil)
}
But you should edit sizes again. For example if you're using autolayout you can create IBOutlet and than use it instead of layer.frame.size property which I used.
Hope it helps.

How to make UIImageView automatically resize to the size of the image loaded

I have put an UIImageView control on my view with IB.
The size of the control is just something I decided upon, pretty random size really
What I want to do is the control to resize automatically whenever I set the image property to a new image. I want it to actually resize to the size of the image.
Can it be done automatically ? without any code intervention ?
If not - what will the best approach be in this case ?
What happens today is strange. I load images into the ImageView and I see the images getting displayed properly even though the size of the ImageView is not changed. This interferes with my intention of grabbing users touches over the ImageView. The user touches the actual image, but since some parts of the image are outside ( and this is the strange part ) of the ImageView - point mapping goes crazy
Can someone think of any explanation to this ?
thanks
The size of an image has no bearing on how large the UIImageView actually is, rather the size of the UIImageView solely depends on the size given to it in Interface Builder (or that you assigned to it). Else the images would be all whacky when you use the #2x images for Retina displays for example.
If you want to fix this, you must change the frame when setting the image as well. If you're doing this now:
[imageView setImage:[UIImage imageNamed:#"myImage.jpg"]];
change it to:
UIImage img = [UIImage imageNamed:#"myImage.jpg"];
[imageView setImage:img];
imageView.frame = CGRectMake(imageView.frame.origin.x, imageView.frame.origin.y,
img.size.width, img.size.height);
This will however not change the layout of view it is contained within, you can make it change the sizes of the other views automatically under iOS 6 using Layout Constraints. If you are an Apple Developer you can watch the WWDC instruction videos, they explain how that system works quite well.
If you're fine with the view not growing, and the problem is just how the image overflows it's bounds when you change it to one that does not match the dimension of the containing view, you can set the "Clip Subviews" checkbox in Interface Builder for the image view. This will make it so that the view will not draw anything outside it's own bounding box, if you also set the scaling mode to "Aspect Fill" or "Scale To Fill", the image will always fill up the entire bounds of the containing view.
Here is the code snippet I cut and paste often, using the same method as Hampus Nilsson above -
Example
func demo(x0:CGFloat, y0:CGFloat) {
let imgView = UIImageView(image: UIImage(named: "someImg.png"));
imgView.sizeToImage();
imgView.center = CGPoint(x:x0, y:y0);
}
UIImageView Extension
extension UIImageView {
/******************************************************************************/
/** #fcn sizeToImage()
* #brief size view to image
* ##assum (image!=nil)
*/
/******************************************************************************/
func sizeToImage() {
//Grab loc
let xC = self.center.x;
let yC = self.center.y;
//Size to fit
self.frame = CGRect (x: 0, y: 0, width: (self.image?.size.width)!/2, height: (self.image?.size.height)!/2);
//Move to loc
self.center = CGPoint(x:xC, y:yC);
return;
}
A wonderful cut & paste, use if needed!
let containerView = UIView(frame: CGRect(x:0,y:0,width:320,height:500))
let imageView = UIImageView()
if let image = UIImage(named: "Image_Name_Here") {
let ratio = image.size.width / image.size.height
if containerView.frame.width > containerView.frame.height {
let newHeight = containerView.frame.width / ratio
imageView.frame.size = CGSize(width: containerView.frame.width, height: newHeight)
}
else{
let newWidth = containerView.frame.height * ratio
imageView.frame.size = CGSize(width: newWidth, height: containerView.frame.height)
}
}

Resources