How to combine/ merge 2 images into 1

51,472

Solution 1

  1. Create a subview for adding images.
  2. Add all your images in that view instead of the main view.
  3. Let the buttons and other stuff stay on the main view.
  4. 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:

enter image description here

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;
}
Share:
51,472
Desmond
Author by

Desmond

Updated on August 08, 2020

Comments

  • Desmond
    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
    Desmond over 12 years
    Hi 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
    Desmond over 12 years
    Thanks i guess this the best way :)
  • Vlad
    Vlad over 12 years
    glad it works. Not sure though what you're after? at you editing the images on runtime ? or just zoom, move and rotate?
  • Desmond
    Desmond over 12 years
    just zoom, move and rotate. then save for bumping
  • Swissdude
    Swissdude almost 12 years
    This 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
    Vlad almost 12 years
    It 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
    Alexey Voitenko almost 11 years
    hello! 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
    anders over 9 years
    This is exactly what I was looking for, thanks much!
  • Alex Zak
    Alex Zak over 8 years
    Here's a gist for the same logic in swift :) gist.github.com/A-Zak/3c38d3f83f911a25790f
  • Zaraki
    Zaraki almost 8 years
    for me the image size increases 6 to 7 times. Any way to keep the size less with same quality?