merging images from two imageviews into a single image in iOS - ios

I have two imageviews view1 and view2 having image1 and image2 respectively. view1 is bigger than view2.
It is oriented such that view2 is located inside view1. view2 is draggable as well.
How could i write a code to merge these two images in imageviews to a single image?

You can merge two images using UIGraphicsBeginImageContext. Here is a small function written with Swift 2.1.1 which takes two images and creates a single image.
func mergeImages (forgroundImage : UIImage, backgroundImage : UIImage) {
let bottomImage = forgroundImage
let topImage = backgroundImage
let size = backgroundImage.size
UIGraphicsBeginImageContext(size)
let areaSize = CGRect(x: 0, y: 0, width: size.width, height: size.height)
bottomImage.drawInRect(areaSize)
topImage.drawInRect(areaSize, blendMode: .Normal, alpha: 1.0)
let newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()
resultImageView.image = newImage
UIGraphicsEndImageContext()
}
You can call it like
mergeImages(yourImageViewOne.image!, backgroundImage: yourImageViewTwo.image!) // Call to mege images
And here is a link for further exploring.

Related

Merge and edit 2 UIImage

I was looking around to find a solution but I didn’t.
Actually I have a block of code that merge 2 image in one.
It’s like I take a photo and the apply a .png on it.
But I would like to let the user move the top image in order to choose the position before save the image
Thanks for any possible help to how I could do it
Here is my func:
func mergeFrame(bottomImage: UIImage, topImage: UIImage) -> UIImage{
let size = CGSize(width: bottomImage.size.width, height: bottomImage.size.height)
UIGraphicsBeginImageContext(size)
let areaSize = CGRect(x: 0, y: 0, width: size.width, height: size.height)
bottomImage.draw(in: areaSize)
topImage.draw(in: areaSize, blendMode: .normal, alpha: 0.8)
let newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return newImage
}
If you need to move the top image, the topImage should have a flexible drawing area.
topImage.draw(in: topArea, blendMode: .normal, alpha: 0.8)
Then use an UIPanGesture to change the topAread.origin base on the gesture.translation during State.Changed.
In State.End of the gesture, call posted mergeFrame(::) to get the composed image.
Hope you got it.

Frame and Image in specific aspect Ratio

I created empty gray UIImage, using below code
let size = CGSize(width: 212, height: 332)
UIGraphicsBeginImageContextWithOptions(size, true, 0)
UIColor.gray.setFill()
UIRectFill(CGRect(x: 0, y: 0, width: size.width, height: size.height))
let backgroundImage2: UIImage? = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
It shows output as
Now I need to put UIImage on specific area in this UIImage. as shown in below Image. Say top, left, right should be 30 pixels, and bottom more than that, say 200 pixels. maintaining inner image aspect ratio.
Use two image views (either UIImageView or GLKView), making the "image" a subview of the "gray background" view. After positioning the "image" correctly, merge the two images into one.
Here's an extension to UIView that I use:
extension UIView {
public func createImage() -> UIImage {
UIGraphicsBeginImageContextWithOptions(
CGSize(width: self.frame.width, height: self.frame.height), true, 1)
self.layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
}

Draw image of viewcontroller by UIGraphicsBeginImageContextWithOptions giving not completely loaded one

I am making a image collage app.
After collage the image, I'm trying to draw a output image from ViewController and upload to a site.
UIGraphicsBeginImageContextWithOptions(self.viewDFrame.bounds.size, NO, 0.0f);
[self.viewDFrame.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Sometime it can output a completely loaded viewcontroller but mostly it output not completely loaded one like this - with frame only.
This is actual output image and preview image that i wanted to get
I am using this code to generate single image. Swift 3.0 version
UIGraphicsBeginImageContextWithOptions(CGRect("Frame To get in context"), false, 0.0);
self.view.drawHierarchy(in: CGRect( "Frame Of View" ), afterScreenUpdates: true)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
If you have any container view where you add frame and images.
self.viewContainer.drawHierarchy(in: CGRect( "Frame Of container view" ), afterScreenUpdates: true)
If you want to render image without showing view on screen and frame sizes are fix then refer this question link.
How to merge two UIImages?
var bottomImage = UIImage(named: "bottom.png")
var topImage = UIImage(named: "top.png")
var size = CGSize(width: 300, height: 300)
UIGraphicsBeginImageContext(size)
let areaSize = CGRect(x: 0, y: 0, width: size.width, height: size.height)
bottomImage!.drawInRect(areaSize)
topImage!.drawInRect(areaSize, blendMode: kCGBlendModeNormal, alpha: 0.8)
var newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
I finally find out that i set Image using requestImageForAsset, this method is asynchronous so that the the renderInContext not wait for the image to be loaded. I set options.synchronous = YES; for PHImageRequestOptions and the image is loaded before rendering.

How apply and move a UIImageView layered above another UIImageView Swift3

i read here many guides how to create a new image merging two existing ones, using the UIGraphics and the layer.render methods for the two UIImageViews, and finally i can create an then save my new image. The problem is that i can't understand how to put the second UIImageView where i want, at the bottom for example. I 'll post now a image of an merged image and the function that my code run making this possible.
Captured merged photo
And here's my code that do the trick:
extension UIImage {
class func imageWithWatermark(image1: UIImageView, image2: UIImageView) -> UIImage {
UIGraphicsBeginImageContextWithOptions(image1.bounds.size, false, 0.0)
let frame = image1.frame
image2.frame = CGRect(x: 0, y: frame.size.height * 0.80, width: frame.size.width, height: frame.size.height * 0.20 )
image1.layer.render(in: UIGraphicsGetCurrentContext()!)
image2.layer.render(in: UIGraphicsGetCurrentContext()!)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img!
}
}
And then my func that saves the merged image:
func addWatermark() {
let newImage = UIImage.imageWithWatermark(image1: cameraPreview, image2: provaImage)
UIImageWriteToSavedPhotosAlbum(newImage, nil,nil,nil)
}
You can use this function which merge two images and the second will be replaces on bottom
func mergeTwoImageSeconInBottom(backgroundImage: UIImage, imageOnBottom: UIImage) -> UIImage {
let size = YOUR_CG_SIZE
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
backgroundImage.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
imageOnBottom.draw(at: CGPoint(x: (size.width - imageOnBottom.size.width) / 2, y: size.height - imageOnBottom.size.height))
let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return newImage
}

Rendering image with textview

I am placing a textview on a image. With following code:
var previewImageView=UIImageView()
self.previewImageView.frame = CGRect(x:0, y:0, width:UIScreen.mainScreen().bounds.width, height:UIScreen.mainScreen().bounds.height)
self.view.addSubview(self.previewImageView)
textField = UITextView(frame: CGRect(x: 0, y: self.view.bounds.height/2 - 50, width: self.view.bounds.width, height: 36))
textField.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.6)
self.view.addSubview(textField)
It works well. But I want to render this image with textview. Then I will save it to gallery.
How can I do this?
Edit:
I tried following code but it is only rendering image not textview:
//Setup the image context using the passed image.
UIGraphicsBeginImageContext(inImage.size)
//Put the image into a rectangle as large as the original image.
inImage.drawInRect(CGRectMake(0, 0, inImage.size.width, inImage.size.height))
// Creating a point within the space that is as bit as the image.
var rect: CGRect = CGRectMake(atPoint.x, atPoint.y, inImage.size.width, inImage.size.height)
//Now Draw the text into an image.
drawText.drawRect(rect)
// Create a new image out of the images we have created
var newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()
// End the context now that we have the image we need
UIGraphicsEndImageContext()
//And pass it back up to the caller.
return newImage
You can render whole view into an UIImage using CGGraphicsContext. Here is an example of the code:
func imageWithView(view: UIView!) -> UIImage! {
UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0)
view.layer.renderInContext(UIGraphicsGetCurrentContext())
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}
When you pass scale = 0.0 it will take a scale of your screen.
An example of usage:
let image = imageWithView(view)
Code to save image:
UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil);
More information about UIGraphicsContext and image saving can be found here.
Update:
If you want to render only specific views, then you should use CALayer, renderInContext. When you use renderInContext it does not know views.frame and draws at (0:0) in coordinate system, so you should use CGContextTranslateCTM to move coordinate system.
To render only these two views you can do:
UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, 0.0)
let context = UIGraphicsGetCurrentContext()
CGContextTranslateCTM(context, previewImageView.frame.origin.x, previewImageView.frame.origin.y)
previewImageView.layer.renderInContext(context)
CGContextTranslateCTM(context, textField.frame.origin.x - previewImageView.frame.origin.x, textField.frame.origin.y - previewImageView.frame.origin.y)
textField.layer.renderInContext(context)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
Please set opaque true/false as you need. When I was testing in playground I was using not opaque views.
Update 2:
Code which should work in all scenarios:
func imageFromViews(views: [UIView]!, contextSize: CGSize!) -> UIImage {
UIGraphicsBeginImageContextWithOptions(contextSize, false, 0.0)
let context = UIGraphicsGetCurrentContext()
for view in views {
CGContextTranslateCTM(context, view.frame.origin.x, view.frame.origin.y)
view.layer.renderInContext(UIGraphicsGetCurrentContext())
CGContextTranslateCTM(context, -view.frame.origin.x, -view.frame.origin.y)
}
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image
}

Resources