Creating a UIImage from two smaller UIImages - ios

I have two instances of UIImage. How can I create a third UIImage that's just the two original images stitched together? I'd like the first image on top and the second image on the bottom such that the top image's bottom edge is flush with the bottom image's top edge.

something like this should work (I havent tested it though)
-(UIImage *)imageWithTopImage:(UIImage *)topImage bottomImage:(UIImage *)bottomImage
{
UIGraphicsBeginImageContext(CGSizeMake(topImage.size.width, topImage.size.height + bottomImage.size.height);
[topImage drawInRect:CGRectMake(0, 0, topImage.size.width, topImage.size.height)];
[bottomImage drawInRect:CGRectMake(0, topImage.size.width, bottomImage.size.width, bottomImage.size.height)];
UIImage *combinedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return combinedImage;
}

Related

UIImage how to resize bubble image with capInsets?

I have bubble like image, that I need to resize dynamically.
Example attached.
I will have dynamic text and I need to resize only straight parts of bubble. Leave down arrow on the middle
How can I do this?
Thanks
You can use method:
- (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight;
call like this:
UIImage* image = [[UIImage imageNamed:#"bubbleImageName.png"]
stretchableImageWithLeftCapWidth:15 topCapHeight:13];
Change capWidth and capHeight values
I think that resizableImageWithCapInsets: will be pretty useful for you
Example:
UIImage *image = [[UIImage imageNamed:#"buttonImage"] resizableImageWithCapInsets:UIEdgeInsetsMake(5.0,10.0,5.0,10.0)];
[self.yourButton setBackgroundImage:image forState:UIControlStateNormal];
I wrote example with button because it's a common case of using this method. Just play with caps values.
HTH!
EDIT:
Thought about this problem and wrote small example.
I understood that resizableImageWithCapInsets: can save only corners of image in case we use two dimension scale.
I see 2 ways:
Use two controls: one for balloon and one for arrow with proper images
Render image for this one control from two images
I decided to realize second one.
Pass ballonView.frame as argument here:
- (UIImage *)balloonImageWithRect:(CGRect)rect{
//create two images, ballon image with cap corners
UIImage *ballonImage = [[UIImage imageNamed:#"balloon"] resizableImageWithCapInsets:UIEdgeInsetsMake(IMAGE_CAP_INSET_TOP, IMAGE_CAP_INSET_LEFT, IMAGE_CAP_INSET_BOTTOM, IMAGE_CAP_INSET_RIGHT) resizingMode:UIImageResizingModeStretch];
UIImage *arrowImage = [UIImage imageNamed:#"arrow"];
//drawing area
CGSize newSize = rect.size;
UIGraphicsBeginImageContext(newSize);
//leave some space for arrow at the bottom
[ballonImage drawInRect:CGRectMake(0, 0, newSize.width, newSize.height - arrowImage.size.height)];
//draw arrow at the bottom
[arrowImage drawInRect:CGRectMake((newSize.width - arrowImage.size.width)/2, newSize.height - arrowImage.size.height, arrowImage.size.width, arrowImage.size.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Then we just set this image to our ballonView.
Also I leave gist with full code of that ViewController with random sizes of that balloon: https://gist.github.com/AlloyDev/7910637
Also you can use that two images:
Use UIImage.h delegate method
// use resizableImageWithCapInsets: and capInsets.
- (UIImage *)stretchableImageWithLeftCapWidth:(NSInteger)leftCapWidth topCapHeight:(NSInteger)topCapHeight;
#property(nonatomic,readonly) NSInteger leftCapWidth; // default is 0. if non-zero, horiz. stretchable. right cap is calculated as width - leftCapWidth - 1
#property(nonatomic,readonly) NSInteger topCapHeight; // default is 0. if non-zero, vert. stretchable. bottom cap is calculated as height - topCapWidth - 1
like this
UIImage *balloon = [[UIImage imageNamed:#"grey.png"] stretchableImageWithLeftCapWidth:24 topCapHeight:15];
hope this helps.
For the image in the question (assuming it's a Retina image):
[[UIImage imageNamed:#"Bubble"] resizableImageWithCapInsets:UIEdgeInsetsMake(14, 28, 14, 26) resizingMode:UIImageResizingModeStretch];
If the image you've provided in the question is a non-retina image, halve the values.
Modify the values (UIEdgeInsetsMake(top, left, bottom, right)) to suit any image you need.

how to use [UIImage resizableImageWithCapInsets:]

I'd like to stretch a image with size 170x50 and show it in an image view with size 240x140.
The original image looks like:
I want to keep the four corners and only stretch the center part. I use the following code:
UIImage *originalImg = [UIImage imageNamed:#"ImageNamed"];
UIImage *resizeImg = [originalImg resizableImageWithCapInsets:UIEdgeInsetsMake(20 ,10, 10, 10)];
self.originalImgV.image = originalImg;
self.resizedImgV.image = resizeImg;
Both originalImgV and resizedImgV are set to "aspect fill". I run it on the simulater, and the result is :
What I can't understand is: the resizedImgV has 2 arrows!
Could any one tell me why and how can I use it correctly?
Thanks
Your issue is with the values you pass to UIEdgeInsetsMake. The values are top, left, bottom, right. Due to the arrow in the top left, you need to make sure your left value is big enough to go from the left edge of the image to just to the right of the arrow.
Given the image you posted, you want something like:
UIEdgeInsetsMake(12, 32, 4, 4)
BTW - the image should only be left + right + 1 pixels wide and top + bottom + 1 pixels tall. So your image doesn't need to be nearly as big as it is.
Stretching is processed in the vertical direction and then in the horizontal direction (or vice versa). So provide top & bottom offsets considering vertical direction that should not stretch and left & right offsets for horizontal direction.
Use this function, you can change the size of UIImage using this function.
+ (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Hope this will help you.

Setting UIToolBar background image

I have an image that I would like to use as the background for a UIToolBar in an iOS 5+ app. The background image changes according to actions taken on the view. The image is larger than the UIToolBar, so the image needs to be resized as a reduction rather than increasing the size.
After review of the other questions on here, as well as other research into the issue, the resolution recommended does not work. The recommendation is as follows:
UIImage *topimg = [[UIImage imageNamed:#"headerBar-Human.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
[_headerBar setBackgroundImage:topimg forToolbarPosition:UIToolbarPositionTop barMetrics:UIBarMetricsDefault];
I have tried with different values in the UIEdgeInsetsMake call with no luck. The problem is that the image is not shown at all. The default blue toolbar background is shown.
If I remove the resizableImageWithCapInsets function the image will show, but only the portion of the image covered by the toolbar rect coordinates.
I have also tried creating a UIImageView, adding the image and adding it to the toolbar, but the results are the same.
Does anyone have any suggestions?
You can use this function to resize your backgroundImage :
- (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize
{
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
I suggest to call this function with your _headerBar.frame.size as second parameter.

Combine two images

I would like to take an image and duplicate it. Then increase it by 105% and overlay it on the original image.
What is the correct way to do this on iOS?
This is your basic code for drawing the image and then saving it as an image again:
- (UIImage *)renderImage:(UIImage *)image atSize:(CGSize)size
{
UIGraphicsBeginImageContext(size);
[image drawInRect:CGRectMake(0.0, 0.0, size.width, size.height)];
// draw anything else into the context
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Where it says "draw anything else into the context" you can draw the image at a reduced size by setting the appropriate rect to draw in. Then, call the renderImage method with whatever size you want the full image to be. You can use CGContextSetAlpha to set the transparency.

How do I "combine" two UIImageViews into one image? Like Photoshop Layer merging?

I have a drawing app where you have one UIImageView that serves as the "drawing layer." You have another UIImageView beneath it that is the "image layer," containing the image you are drawing on. I like having this separation. However, I want the user to be able to "save and email" the drawing they have made on top of the image as one unified image. How do I do this?
Your UIImageView instances must be part of a UIView hierachy so all you need to do is paint that top containing UIView into a context
UIGraphicsBeginImageContext(CGSizeMake(width, height));
[container.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *fimage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
or if that gives you trouble successively paint the two images into a context
UIGraphicsBeginImageContext(CGSizeMake(width, height));
[image1.layer renderInContext:UIGraphicsGetCurrentContext()];
[image2.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *fimage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
from there you can write the data where you choose
NSData *data = UIImagePNGRepresentation(fimage);
Pass that data into the MailComposer setup.

Resources