How to combine/ merge 2 images into 1
Solution 1
- Create a subview for adding images.
- Add all your images in that view instead of the main view.
- Let the buttons and other stuff stay on the main view.
- Render only the view with images in the bitmap context instead of the main view like you are doing right now.
Solution 2
You can create graphics context and draw both images in it. You'll get an image result from both your source images combined.
- (UIImage*)imageByCombiningImage:(UIImage*)firstImage withImage:(UIImage*)secondImage {
UIImage *image = nil;
CGSize newImageSize = CGSizeMake(MAX(firstImage.size.width, secondImage.size.width), MAX(firstImage.size.height, secondImage.size.height));
if (UIGraphicsBeginImageContextWithOptions != NULL) {
UIGraphicsBeginImageContextWithOptions(newImageSize, NO, [[UIScreen mainScreen] scale]);
} else {
UIGraphicsBeginImageContext(newImageSize);
}
[firstImage drawAtPoint:CGPointMake(roundf((newImageSize.width-firstImage.size.width)/2),
roundf((newImageSize.height-firstImage.size.height)/2))];
[secondImage drawAtPoint:CGPointMake(roundf((newImageSize.width-secondImage.size.width)/2),
roundf((newImageSize.height-secondImage.size.height)/2))];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
Solution 3
Swift 4.2
let topImage = UIImage(named: "image1.png")
let bottomImage = UIImage(named: "image2.png")
let size = CGSize(width: topImage!.size.width, height: topImage!.size.height + bottomImage!.size.height)
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
topImage!.draw(in: CGRect(x: 0, y: 0, width: size.width, height: topImage!.size.height))
bottomImage!.draw(in: CGRect(x: 0, y: topImage!.size.height, width: size.width, height: bottomImage!.size.height))
let newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
//set finalImage to IBOulet UIImageView
mergeImage.image = newImage
Objective-C
UIImage *image1 = [UIImage imageNamed:@"image1.png"];
UIImage *image2 = [UIImage imageNamed:@"image2.png"];
CGSize size = CGSizeMake(image1.size.width, image1.size.height + image2.size.height);
UIGraphicsBeginImageContext(size);
[image1 drawInRect:CGRectMake(0,0,size.width, image1.size.height)];
[image2 drawInRect:CGRectMake(0,image1.size.height,size.width, image2.size.height)];
UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//set finalImage to IBOulet UIImageView
imageView.image = finalImage;
Solution 4
Swift 3
In this example the frontImage is being drawn inside the other image using a insetBy of 20% margin.
The background image must be drawn before and then the front image in sequence.
I used this to place a "Play" icon image in front a video frame image inside a UIImageView like below:
Usage:
self.image = self.mergedImageWith(frontImage: UIImage.init(named: "play.png"), backgroundImage: UIImage.init(named: "backgroundImage.png")))
Method:
func mergedImageWith(frontImage:UIImage?, backgroundImage: UIImage?) -> UIImage{
if (backgroundImage == nil) {
return frontImage!
}
let size = self.frame.size
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
backgroundImage?.draw(in: CGRect.init(x: 0, y: 0, width: size.width, height: size.height))
frontImage?.draw(in: CGRect.init(x: 0, y: 0, width: size.width, height: size.height).insetBy(dx: size.width * 0.2, dy: size.height * 0.2))
let newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return newImage
}
Solution 5
You can use this method, which is very dynamic and you can specify the starting position of the second image and total size of the image.
-(UIImage *) addImageToImage:(UIImage *)img withImage2:(UIImage *)img2 andRect:(CGRect)cropRect withImageWidth:(int) width
{
CGSize size = CGSizeMake(width,40);
UIGraphicsBeginImageContext(size);
CGPoint pointImg1 = CGPointMake(0,0);
[img drawAtPoint:pointImg1];
CGPoint pointImg2 = cropRect.origin;
[img2 drawAtPoint: pointImg2];
UIImage* result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return result;
}
Desmond
Updated on August 08, 2020Comments
-
Desmond almost 4 years
I would like to know what to do to save 2 images into 1 image.
One of the photos can be moved, rotated and zoomed in/out...
I'm doing this, but it basically captures all the stuff on the screen including my buttons...
UIGraphicsBeginImageContext(self.view.bounds.size); [self.view.layer renderInContext:UIGraphicsGetCurrentContext()]; UIImage *savedImg = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();
-
Desmond over 12 yearsHi Vlad, Thanks for the code. it works, but is does not save any movement or rotation i edited. Also it save in the picture's aspect ratio. any suggestion ?
-
Desmond over 12 yearsThanks i guess this the best way :)
-
Vlad over 12 yearsglad it works. Not sure though what you're after? at you editing the images on runtime ? or just zoom, move and rotate?
-
Desmond over 12 yearsjust zoom, move and rotate. then save for bumping
-
Swissdude almost 12 yearsThis function fails when the two images have the same size (then MAX(first-width, second-width) results in 0; Also, the drawAtPoint functions seem to be borked. I had to exchange them with this: [firstImage drawAtPoint:CGPointMake(0,0)]; [secondImage drawAtPoint:CGPointMake(0, firstImage.size.height)]; This only works if the two images have the same width!
-
Vlad almost 12 yearsIt will not fail, it will draw both images starting {0, 0}, overlapped. Coordinates are relative to the container view (ex: image inside imageView).
-
Alexey Voitenko almost 11 yearshello! this great code helped me very much. But I'm not sure its really necessary to use roundf() function. It may cause to round error. Maybe not error exactly but unexpected result.
-
anders over 9 yearsThis is exactly what I was looking for, thanks much!
-
Alex Zak over 8 yearsHere's a gist for the same logic in swift :) gist.github.com/A-Zak/3c38d3f83f911a25790f
-
Zaraki almost 8 yearsfor me the image size increases 6 to 7 times. Any way to keep the size less with same quality?