How to combine/ merge 2 images into 1

2019-01-16 05:20发布

问题:

will like to know who to do save 2 images into 1 image.

one of the photo are allow to move, rotate and zoom in/out...

i'm doing this, but it basically capture all the stuff on the screen including my buttons...

UIGraphicsBeginImageContext(self.view.bounds.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *savedImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

回答1:

  1. crate 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.


回答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;
}


回答3:

// 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;

// Swift

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


回答4:

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;
}


回答5:

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
}


回答6:

Here's a method for UIImage extension to combine multiple images:

class func combine(images: UIImage...) -> UIImage {
    var contextSize = CGSizeZero

    for image in images {
        contextSize.width = max(contextSize.width, image.size.width)
        contextSize.height = max(contextSize.height, image.size.height)
    }

    UIGraphicsBeginImageContextWithOptions(contextSize, false, UIScreen.mainScreen().scale)

    for image in images {
        let originX = (contextSize.width - image.size.width) / 2
        let originY = (contextSize.height - image.size.height) / 2

        image.drawInRect(CGRectMake(originX, originY, image.size.width, image.size.height))
    }

    let combinedImage = UIGraphicsGetImageFromCurrentImageContext()

    UIGraphicsEndImageContext()

    return combinedImage
}

Example:

UIImage.combine(image1, image2)


回答7:

Swift-3 (IOS10.3)

extension UIImage {
    func combineWith(image: UIImage) -> UIImage {
        let size = CGSize(width: self.size.width, height: self.size.height + image.size.height)
        UIGraphicsBeginImageContextWithOptions(size, false, 0.0)

        self.draw(in: CGRect(x:0 , y: 0, width: size.width, height: self.size.height))
        image.draw(in: CGRect(x: 0, y: self.size.height, width: size.width,  height: image.size.height))

        let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()

        return newImage
    }
}

Usage

let image1 = UIImage(named: "image1.jpg")
let image2 = UIImage(named: "image2.jpg")

yourImageView.image = image1?.combineWith(image: image2)


回答8:

Based on Himanshu padia's response

If you want to "dynamically" combine more images (with the same aspect ratio) into one grid in Objective-C

I have used only two for this example on even/odd slots.

Formulas for equal inline and outline border:

// psx = (x - (n+1)*bs / n)
// psy = (y - (m+1)*bs / m)

Formulas for different inline and outline border

// psx = (x - (n-1)*bs + obs / n)
// psy = (y - (m-1)*bs + obs / m)

Explanation:

  • psx, psy - piece size X and y
  • x, y - original (piece) image size
  • n, m - pieces slots in grid
  • bs - border size
  • obs - outline border size

  • Why n+1 ? Because for three pieces, you need 4 borders |*|*|*|

  • Why n-1 ? Because same as above, but excluding the first and last border !*|*|*!

Code:

UIImage *image1 = [UIImage imageNamed:@"14x9blue"];
UIImage *image2 = [UIImage imageNamed:@"14x9red"];

// grid parameters
int k =0;
int m=3,n = 3;
int i=0, j=0;

CGFloat borderSize = 20.0f;
//  equal border inline and outline
// the 1 is a multiplier for easier and more dynamic sizes
// 0*borderSize is inline border only, 1 is equal, 2 is double, etc.
CGFloat outlineBorder = 1*borderSize;

CGSize size = CGSizeMake(self.gridImageView.image.size.width, self.gridImageView.image.size.height);
CGRect gridImage = CGRectMake(0,0, size.width, size.height);


// piece size
// border inline and outline    
// psx = (x - (n-1)*bs + obs / n)
// psy = (y - (m-1)*bs + obs / m)
CGFloat pieceSizeX = (size.width - (n-1)*borderSize - 2*outlineBorder) / n;
CGFloat pieceSizeY = (size.height - (m-1)*borderSize - 2*outlineBorder) / m;




UIGraphicsBeginImageContext(size);
// semi transparent fill
[[UIColor colorWithDisplayP3Red:240 green:250 blue:0 alpha:0.5] setFill];
UIRectFill(CGRectMake(0,0, size.width, size.height));

UIImage *currentImage;
for(i=0; i<m; i++) {
    for (j=0; j<n; j++) {
        if (k++%2) {
            currentImage = image1;
        } else {
            currentImage = image2;
        }
        // 10-60 , 70-120, 130-180
        [currentImage drawInRect:CGRectMake(
                outlineBorder + (i)*borderSize + i*pieceSizeX,
                outlineBorder + (j)*borderSize + j*pieceSizeY,
                pieceSizeX,
                pieceSizeY
        )
        ];
    }
}

UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

//set finalImage to IBOulet UIImageView
self.gridImageView.image = finalImage;