I'm loading an UIImage into a UIImageView and setting the dimensions of the image to be the same as of the UIImageView which was created in storyboard and is 60x60 by default. Code-wisely, everything works, the debug says that the dimensions of image and imageView are both 60px, however looking at the simulator, you can obviously see a rectangle rather than a box. Where is the problem?
Image loading code:
- (void)viewWillAppear:(BOOL)animated
{
NSString *userImageURL = [NSString stringWithFormat:#"https://graph.facebook.com/TheOfficialKanyeWest/picture?"];
NSData* data = [NSData dataWithContentsOfURL:[NSURL URLWithString:userImageURL]];
UIImage* profilePic = [UIImage imageWithData:data];
profilePic = [self imageWithImage:profilePic scaledToSize:profilePictureImageView.frame.size];
[profilePictureImageView setImage:profilePic];
//[profilePictureImageView sizeToFit];
NSLog(#"\n\nView:\nWidth: %f\nHeight: %f\n\nImage:\nWidth: %f\nHeight: %f\n", profilePictureImageView.frame.size.width, profilePictureImageView.frame.size.height, profilePic.size.width, profilePic.size.height);
}
Custom function for resizing image:
- (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize {
//UIGraphicsBeginImageContext(newSize);
// In next line, pass 0.0 to use the current device's pixel scaling factor (and thus account for Retina resolution).
// Pass 1.0 to force exact pixel size.
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Also, the debug I put in the ViewDidAppear gives me:
View:
Width: 60.000000
Height: 60.000000
Image:
Width: 60.000000
Height: 60.000000
Edit:
Forgot to add screenshot
Solution
The code was absolutely fine. I failed to notice that my automatic constraints were causing the imageView to resize to the odd rectangular shape. I added my constraints manually and now it works well.
Pin width and height constraints of the imageView to 60 and 60 in story board don't use automatic constraints.
I have tried your code, in coding its absolutely right, but in storyboard there is any mistakes in autolayouts..
Move the code from viewWillAppear to viewDidAppear. In viewWillAppear your UIImageView is not set to its final frame.
Try your code in
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
// put your code to here to set frame and size of imageview.
}
Related
I am trying to take a screenshot of my UIImageView and a UILabel that is on top of that.
What I have so far grabs the UIImage in the ImageView and then renders the overlay on it but the positioning of the UILabel is all wrong. I am setting the size of the capture to the actual image size(which isn't what i want).
I just want to be able to take a screenshot exactly how it appears on the screen.
CGSize imageSize = self.imageFromOtherView.size;
// define the size and grab a UIImage from it
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
[self.imageFromOtherView drawInRect:CGRectMake(0, 0, imageSize.width, imageSize.height)];
[self.socialLabel.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *capturedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Create a UIView to hold both the UIImageView and UILabel. Then pass this container view through this code. I have my view as a property called viewForPhoto so when the code is called it only captures that view. You can tweak it so that it receives a view. This will return the UIImage that you want.
- (UIImage *)imageByRenderingView
{
UIGraphicsBeginImageContextWithOptions(self.viewForPhotoView.bounds.size, NO, 0.0);
[self.viewForPhotoView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resultingImage;
}
Add both those views to a common container view, and then call - (BOOL)drawViewHierarchyInRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates on the view to render it in a context.
I have a large image (1920*1080), and a smaller UIImageView (320*568) that scaled to full screen size in the story board.
Now I want to display this large image full screen size, but fit to the UIImageView.
I have tried all the content mode, but they are all not working. Every time it just shows the top left part of the image full screen sized.
[self.imageView setFrame:self.view.bounds];
[self.imageView setContentMode:UIViewContentModeScaleAspectFit] ;
[self.imageView setImage:image] ;
[self.view insertSubview:_imageView aboveSubview:_previewView] ;
So what might be wrong in my case? could that be a Xcode story board configuration error ?
thanks.
If you are seeing only the image top corner in your ImageView, then the possible reasons are: Your ImageView frame is out of screen size OR Content Mode is not set. In your code you are setting the frame as the bounds of the superview. If your are using Auto-layout, check the auto-layout are set properly. If this is ok, then try setting UIImageView ContentMode before setting the frame.
// Setting the content mode.
self.imageView.contentMode = UIViewContentModeScaleAspectFit;
// Now set the frame.
[self.imageView setFrame:self.view.bounds];
Other solution is you can downscale your image to fit your ImageView. For that you can use the following function:
- (UIImage *)scaleImage:(UIImage *)orginalImage
{
float widthFactor = photoImageView.frame.size.width / orginalImage.size.width;
CGSize destinationSize = CGSizeMake(orginalImage.size.width * widthFactor,orginalImage.size.height * widthFactor);
UIGraphicsBeginImageContext(destinationSize);
[orginalImage drawInRect:CGRectMake(0,0,destinationSize.width,destinationSize.height)];
UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
photoImageView.image = scaledImage;
return scaledImage;
}
There is a problem that CIImage does somehow not respect contentMode (at least on some devices / iOS versions). Convert CIImage to a CGImage to make this work.
Swift 3 code:
func convertCIImageToCGImage(inputImage: CIImage) -> CGImage?
{
let context = CIContext(options: nil)
if let cgImage = context.createCGImage(inputImage, from: inputImage.extent)
{
return cgImage
}
return nil
}
Try this
[self.imageView setFrame:self.view.bounds];
self.imageView.contentMode = UIViewContentModeScaleAspectFit;
self.imageView.clipsToBounds = YES;
[self.imageView setImage:image] ;
[self.view insertSubview:_imageView aboveSubview:_previewView] ;
Working fine .. :)
In my case, i solved this removing some constraints that resize the imageview that i set by error.
Check your imageview constraints, try removing all of them
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.
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.
What I'm doing is creating filling in a view's background with an image returned from a UIImagePickerController. The image fills fine in portrait mode; however, the image will repeat when filled as background in landscape mode, but I have no idea why this is occuring. This is a private method I use to resize my image.
+ (UIImage *)imageWithImage:(UIImage *)image scaledToSize:(CGSize)newSize landscape:(BOOL)landscape {
UIGraphicsBeginImageContextWithOptions(newSize, NO, 0.0);
[image drawInRect:CGRectMake(0, 0, newSize.width, newSize.height)];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
When this method is called the newsize parameter is equal to the views bounds size (self.view.bounds.size). The size is accessed after the view's transformation to landscape, but the image doesn't properly.
This is the code that is called right after getting an image from the UIImagePickerController.
-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
if (image.size.width > image.size.height) {
self.view.transform = CGAffineTransformRotate(self.view.transform, M_PI_2);
self.composition.landscapemode = YES;
} else {
self.composition.landscapemode = NO;
}
self.composition.image = [NewCompositionViewController imageWithImage:image scaledToSize:self.view.bounds.size landscape:self.composition.landscapemode];
self.view.backgroundColor = [UIColor colorWithPatternImage:self.composition.image];
[self dismissViewControllerAnimated:YES completion:nil];
}
[UIColor colorWithPatternImage:] is meant for tiling images, so it's behaving as it should.
I would recommend creating a UIImageView with screen-sized frame, setting an image to it, and adding it as subview:
UIImageView *backgroundImage = [[UIImageView alloc] initWithFrame:self.view.frame];
[backgroundImage setImage:self.composition.image];
// choose best mode that works for you
[backgroundImage setContentMode:UIViewContentModeScaleAspectFill];
[self.view insertSubview:backgroundImage atIndex:0];
//OR
[self.view addSubview:backgroundImage];
[self.view sendSubviewToBack:backgroundImage];
once it's added, you can rotate it and experiment with autoresizing masks to make sure it's displayed properly for all orientations. Exact method would depend on if you are using auto-layout or not.
UIViewContentModeScaleAspectFill may be more appropriate here than UIViewContentModeScaleAspectFit since the image is filling a background view. AspectFit will maintain the image's aspect ratio and make the entire image fit in the space, which may leave portions of the view transparent. AspectFill also maintains aspect ratio, but will fill the entire view and clip any portions of the image that don't match the view bounds.
I've been able to apply an "aspect fit" UIImage to a UIView background by combining a few AVFoundation and UIKit APIs. Here's one example:
UIImage *image = [UIImage imageWithContentsOfFile:self.desiredBackgroundImageFilePathString];
UIGraphicsBeginImageContext(self.drawingImage.frame.size);
[image drawInRect:AVMakeRectWithAspectRatioInsideRect(image.size, self.drawingImage.bounds)];
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
self.drawingImage.backgroundColor = [UIColor colorWithPatternImage:image];
This flows through a few simple, but important steps:
Generate a UIImage from a file (or whatever).
Define the context of the image (the desired UIView for the background) with UIGraphicsBeginImageContext().
Use drawInRect in combination with AVMakeRectWithAspectRatioInsideRect to scale the image. Provide AVMakeRect...() with the image's .size and the bounds of the target UIView.
Apply the resized image to the desired image context.
Apply your now-resized image to the .backgroundColor of the target UIView using colorWithPatternImage.
I'm able to swap out images with both landscape and portrait aspect ratios without alignment or clipping issues using this code.