how to use [UIImage resizableImageWithCapInsets:] - ios

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.

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.

Crop an area of oversized image to what is currently showing onscreen

I have an oversized image loaded in a image view that goes out of bounds both vertically and horizontally.
The end user can scroll around the image (the oversized imageview is in a scrollview) and when they find an area that they like I would like to crop out the area of the image that is shown on the screen. (much like a screenshot but only of the imageview.image I'm then going to put that into a different Imageview.
I can't seem to work out how to accomplish the "screenshot" of the area of the image view's image that is currently showing on the screen.
You can use CGImageCreateWithImageInRect to create a subimage of the displayed image. Use contentOffset and the scrollViews bounds to create the rect from which you want to create the image.
CGRect rect = CGRectMake(scrollView.contentOffset.x, scrollView.contentOffset.y, CGRectGetWidth(scrollView.bounds), CGRectGetHeight(scrollView.bounds));
CGImageRef subImageRef = CGImageCreateWithImageInRect([originalImage CGImage], rect);
If you zoom your scrollView you will need to take the zoomLevel into account too.
I ended up using the following code to achieve what I was looking for to grab the image. Thank you to Karl for his input and a thank you to iNoob whom answer to a previous question [Located here on StackOverflow][1] I used for mine.
Just use the below code to take a "screenshot" just set anything you don't want in the image to.hidden = True; before the code to hide it from the screenshot and set them to .Hidden = FALSE; after the code to bring them back.
UIGraphicsBeginImageContextWithOptions(self.view.bounds.size, self.view.opaque, 0.0);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();

Reduce Resolution UIImage/UIImageView [duplicate]

This question already has answers here:
The simplest way to resize an UIImage?
(34 answers)
Closed 9 years ago.
I've created a UIImageView which contains an image with a high resolution. The problem is that the resolution of that image is too high to put into the imageView. The size of the imageView is 92 x 91 (so it's small). It contains an UIImage, whose resolution is too high so it looks ugly in the UIImageView.
So how can I reduce the resolution of that UIImage?
My code for the UIImageView:
UIImageView *myImageView = [[UIImageView alloc] initWithImage:[UIImage imageWithContentsOfFile:pngFilePath]];
myImageView.frame = CGRectMake(212.0, 27, 92,91);
have a look at this
https://stackoverflow.com/a/2658801
This will help you to resize your image according to your need
Add method to your code and call like this
UIImage *myImage =[UIImage imageWithContentsOfFile:pngFilePath];
UIImage *newImage =[UIImage imageWithImage:myImage scaledToSize:CGSizeMake(92,91)];
You can resize an image using this method that returns a resized image :
-(UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
// Here pass new size you need
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Hope it helps you.
try with this
myImageView.contentMode = UIViewContentModeScaleToFill;
You need to downsize the image, which will reduce the resolution, make it easier to store. I actually wrote a class (building on some stuff from SO) that does just that. It's on my github, take a look:
https://github.com/pavlovonline/UIImageResizer
the main method is
-(UIImage*)resizeImage:(UIImage*)image toSize:(CGFloat)size
so you give this method the size to which you want to downsize your image. If the height is greater than the width, it will auto-calculate the middle and give you a perfectly centered square. Same for width being greater than height. If you need an image that is not square, make your own adjustments.
so you'll get back a downsized UIImage which you can then put into your UIImageView. Save some memory too.

Core Graphics - how to crop non-transparent pixels out of a UIImage?

I have a UIImage that is reading from a transparent PNG (500px by 500px). Somewhere in the image, there is a picture that I want to crop out and save as a separate UIImage. I also want to store the X and Y coordinates based on how many transparent pixels there were on the left and top of the newly cropped rectangle.
I was able to crop an image with this code:
- (UIImage *)cropImage:(UIImage *)image atRect:(CGRect)rect
{
double scale = image.scale;
CGRect scaledRect = CGRectMake(rect.origin.x*scale,rect.origin.y*scale,rect.size.width*scale,rect.size.height*scale);
CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage], scaledRect);
UIImage *cropped = [UIImage imageWithCGImage:imageRef scale:scale orientation:image.imageOrientation];
CGImageRelease(imageRef);
return cropped;
}
Which actually cuts off the transparent pixels on the top and left :S (this would be great if I was able to crop the pixels on right and bottom too!). It then resizes the rest of the image to the rectangle I specified. Unfortunately though I need to cut a picture that is in the middle of the image and I need the size to be able to be dynamic.
Been struggling with this for several hours now. Any ideas?
To crop an image, draw it into a smaller graphics context.
For example, let's say you have a 600x600 image. And let's say that you want to crop 200 pixels off all four sides. That leaves a 200x200 rectangle.
So you would make a 200x200 graphics context, using UIGraphicsBeginImageContextWithOptions. Then you would draw the image into it using drawAtPoint:, drawing at the point (-200,-200). If you think about it, you will see that that offset causes just the 200x200 from the middle of the original to be drawn into the actual bounds of the context. Thus you have cropped the image by 200 pixels on all four sides, which is what we wanted to do.
Thus here is a generalized version, assuming that we know the amount to crop from the left, right, top, and bottom:
UIImage* original = [UIImage imageNamed:#"original.png"];
CGSize sz = [original size];
CGFloat cropLeft = ...;
CGFloat cropRight = ...;
CGFloat cropTop = ...;
CGFloat cropBottom = ...;
UIGraphicsBeginImageContextWithOptions(
CGSizeMake(sz.width - cropLeft - cropRight, sz.height - cropTop - cropBottom),
NO, 0);
[original drawAtPoint:CGPointMake(-cropLeft, -cropTop)];
UIImage* cropped = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
After that, cropped is your cropped image.

Creating a UIImage from two smaller UIImages

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

Resources