27

I'm facing the following problem : I have to merge two images A and B to create a new image C as a result of the merging.
I already know how to merge two images but in this case my goal is a little bit different.
I would like that image A will be the background for Image B.
For instance if image A size is 500x500 and image B size is 460x460 I would like that image C (the image result of the merging) will be 500x500, with image B (460x460) centered in it.

Thanks in advance for any help or suggestion

vikingosegundo
  • 52,040
  • 14
  • 137
  • 178
oiledCode
  • 8,589
  • 6
  • 43
  • 59

7 Answers7

88

This is what I've done in my app, but without using UIImageView:

UIImage *bottomImage = [UIImage imageNamed:@"bottom.png"]; //background image
UIImage *image       = [UIImage imageNamed:@"top.png"]; //foreground image

CGSize newSize = CGSizeMake(width, height);
UIGraphicsBeginImageContext( newSize );

// Use existing opacity as is
[bottomImage drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];

// Apply supplied opacity if applicable
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height) blendMode:kCGBlendModeNormal alpha:0.8];

UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

If the image already has opacity, you do not need to set it (as in bottomImage) otherwise you can set it (as with image).

After this UIImage is created then you can embed it in your UIImageView

UPDATE: Thanks to Ahmet AkkoK - for Swift (2.2) users blend mode macro has changed. CGBlendMode .kCGBlendModeNormal is replaced with CGBlendMode.Normal

Srikar Appalaraju
  • 71,928
  • 54
  • 216
  • 264
13

Hey i got multiple images add same background with different foreground This is my code

UIImage *bottomImage = [UIImage imageNamed:@"photo 2.JPG"]; //background image
UIImage *image       = [UIImage imageNamed:@"photo 3.JPG"]; //foreground image
UIImage *image1      = [UIImage imageNamed:@"photo 4.JPG"]; //foreground image
UIImage *image2      = [UIImage imageNamed:@"photo 5.JPG"]; //foreground image

CGSize newSize = CGSizeMake(320, 480);
UIGraphicsBeginImageContext( newSize );

// Use existing opacity as is
[bottomImage drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];

// Apply supplied opacity if applicable
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height) blendMode:kCGBlendModeNormal alpha:0.4];
[image1 drawInRect:CGRectMake(0,0,newSize.width,newSize.height) blendMode:kCGBlendModeNormal alpha:0.3];
[image2 drawInRect:CGRectMake(0,0,newSize.width,newSize.height) blendMode:kCGBlendModeNormal alpha:0.2];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

resultView = [[UIImageView alloc] initWithImage:newImage];
resultView.frame = CGRectMake(0, 0,320,460);
[self.view addSubview:resultView];
USK
  • 499
  • 1
  • 4
  • 9
7

Swift version

Copy/Paste to Playground

var bottomImage:UIImage = UIImage(named:"avatar_4.png") //background image

enter image description here

var imageTop:UIImage  = UIImage(named:"group_4.png")    //top image

enter image description here

var newSize = CGSizeMake(bottomImage.size.width, bottomImage.size.height)
UIGraphicsBeginImageContext( newSize )
    
bottomImage.drawInRect(CGRectMake(0,0,newSize.width,newSize.height))

// decrease top image to 36x36 
imageTop.drawInRect(CGRectMake(18,18,36,36), blendMode:kCGBlendModeNormal, alpha:1.0)

var newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()
var imageData = UIImagePNGRepresentation(newImage)

enter image description here


To load images from playground:

  • Open playground file and create there folder Resources
  • copy images to this folder

enter image description here

Community
  • 1
  • 1
Maxim Shoustin
  • 77,483
  • 27
  • 203
  • 225
4

Just made quick paste function for those of you who wanted to use Srikar Appal answer. (if in case background & foreground images are of different sizes)

- (UIImage *) mergeImages:(NSString *)bgImageFileName foreGround:(NSString *)fgImageFileName  {
    UIImage *bottomImage = [UIImage imageNamed:bgImageFileName]; //background image
    UIImage *image       = [UIImage imageNamed:fgImageFileName]; //foreground image

    CGSize newSize = CGSizeMake(bottomImage.size.width, bottomImage.size.height);
    UIGraphicsBeginImageContext(newSize);

    // Use existing opacity as is
    [bottomImage drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];

    // Apply supplied opacity if applicable
    // Change xPos, yPos if applicable
    [image drawInRect:CGRectMake(11,11,image.size.width,image.size.height) blendMode:kCGBlendModeNormal alpha:1.0];

    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();
    return newImage;
}
Community
  • 1
  • 1
Thiru
  • 1,380
  • 13
  • 21
2

in Swift:

let bottomImage = UIImage(named: "Bottom_Image.png")
    let frontImage = UIImage (named: "Front_Image.png")
    let size = CGSize(width: 67, height: 55)
    UIGraphicsBeginImageContext(size)
    let areaSize = CGRect(x: 0, y: 0, width: size.width, height: size.height)
    let frontImageSize = CGRect(x: 14, y: 3, width: 40, height: 40)
    bottomImage!.drawInRect(areaSize, blendMode: CGBlendMode.Normal, alpha:  1.0)
    frontImage!.drawInRect(frontImageSize, blendMode: CGBlendMode.Normal, alpha: 1.0)

    let newImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
Dara Tith
  • 518
  • 7
  • 21
0

Thanks @Srikar Appal for iOS soultion.

For anyone who is looking for merge in OS X:

- (NSImage *) mergeImages:(NSString *)bgImageFileName foreGround:(NSString *)fgImageFileName {
    NSImage *bottomImage = [NSImage imageNamed:bgImageFileName];
    NSImage *overlayedImage = [NSImage imageNamed:fgImageFileName];

    NSSize newSize = NSMakeSize(bottomImage.size.width, bottomImage.size.height);
    NSSize overlaySize = NSMakeSize(newSize.width/2, newSize.height/2); //change the size according to your requirements

    NSImage *newImage = [[NSImage alloc] initWithSize:newSize];

    [newImage lockFocus];

    [bottomImage drawInRect:NSMakeRect(0, 0, newSize.width, newSize.height)];
    [overlayedImage drawInRect:NSMakeRect(newSize.width-overlaySize.width, 0, overlaySize.width, overlaySize.height)]; //set the position as required

    [newImage unlockFocus];

    return newImage;
}
bikram990
  • 1,085
  • 1
  • 14
  • 36
0

You can go with another trick as described below:

  1. Add first image to a imageView.
  2. Add second image to another imageView.
  3. Add both the above imageViews in a single main imageView and access the combined image by property of imageView : mainImageView.image

Have a look at the code below :

    CGRect rect= investmentDetailTblView.frame;
    int rows = investmentDetailArray.count;

    CGFloat heightFinal = 5;
    CGRect frame1;

    for (int i=0; i<rows; i++)
    {
         frame1 = [investmentDetailTblView rectForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]];
        CGFloat height = frame1.size.height;

        heightFinal = heightFinal + height;
    }
    rect.size.height = heightFinal;

    investmentDetailTblView.frame=rect;

    UIImageView *imageViewTable = [[UIImageView alloc] init];

    [imageViewTable setFrame:CGRectMake(0, 0, frame1.size.width, heightFinal)];


    [investmentDetailTblView reloadData];

    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)])
        UIGraphicsBeginImageContextWithOptions(investmentDetailTblView.bounds.size, NO, [UIScreen mainScreen].scale);
    else
        UIGraphicsBeginImageContext(investmentDetailTblView.bounds.size);

    [investmentDetailTblView.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    imageViewTable.image = image; //Adding the table image to the image view.


    CGRect frame=CGRectMake(0, heightFinal+5, investmentDetailTblView.frame.size.width, 20) ;
    UIView *footerView=[DataStore kkrLogoView];

    footerView.frame=frame;

    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)])
        UIGraphicsBeginImageContextWithOptions(footerView.frame.size, NO, [UIScreen mainScreen].scale);
    else
        UIGraphicsBeginImageContext(footerView.frame.size);

    [footerView.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *kkrLogoImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

    UIImageView *imageViewFooter = [[UIImageView alloc] init];
    [imageViewFooter setFrame:CGRectMake(0, heightFinal, footerView.frame.size.width, footerView.frame.size.height)];
    imageViewFooter.image = kkrLogoImage; //Adding the footer image to the image view.


    UIImageView *mainImageView = [[UIImageView alloc] init];
    [mainImageView setFrame:CGRectMake(0, 0, frame1.size.width, (heightFinal+footerView.frame.size.height))];

    [mainImageView addSubview:imageViewTable];
    [mainImageView addSubview:imageViewFooter];

    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)])
        UIGraphicsBeginImageContextWithOptions(mainImageView.frame.size, NO, [UIScreen mainScreen].scale);
    else
        UIGraphicsBeginImageContext(mainImageView.frame.size);

    [mainImageView.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
CherryDT
  • 25,571
  • 5
  • 49
  • 74