UIImageView image aspect ratio is messed up after redrawing it to create a round mask - ios

My app sends a GET request to google to attain certain user information. One piece of crucial returned data is a users picture which is placed inside a UIImageView that is always exactly (100, 100) then redrawn to create a round mask for this imageView. These pictures come from different sources and thus always have different aspect ratios. Some have a smaller width compared to their height, sometimes it's vice-versa. This results in the image looking compressed. I've tried things such as the following (none of them worked):
_personImage.layer.masksToBounds = YES;
_personImage.layer.borderWidth = 0;
_personImage.contentMode = UIViewContentModeScaleAspectFit;
_personImage.clipsToBounds = YES;
Here is the code I use to redraw my images (it was attained from user fnc12 as the third answer in Making a UIImage to a circle form):
/** Returns a redrawn image that had a circular mask created for the inputted image. */
-(UIImage *)roundedRectImageFromImage:(UIImage *)image size:(CGSize)imageSize withCornerRadius:(float)cornerRadius
{
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0.0); //<== Notice 0.0 as third scale parameter. It is important because default draw scale ≠ 1.0. Try 1.0 - it will draw an ugly image...
CGRect bounds = (CGRect){CGPointZero, imageSize};
[[UIBezierPath bezierPathWithRoundedRect:bounds cornerRadius:cornerRadius] addClip];
[image drawInRect:bounds];
UIImage *finalImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return finalImage;
}
This method is always called like so:
[_personImage setImage:[self roundedRectImageFromImage:image size:CGSizeMake(_personImage.frame.size.width, _personImage.frame.size.height) withCornerRadius:_personImage.frame.size.width/2]];
So I end up having a perfectly round image but the image it self isn't right aspect-wise. Please help.
P.S. Here's how images look when their width is roughly 70% that of their height before the redrawing of the image to create a round mask:

Hello dear friend there!
Here is my version that works:
Code in ViewController:
[self.profilePhotoImageView setContentMode:UIViewContentModeCenter];
[self.profilePhotoImageView setContentMode:UIViewContentModeScaleAspectFill];
[CALayer roundView:self.profilePhotoImageView];
roundView function in My CALayer+Additions class:
+(void)roundView:(UIView*)view{
CALayer *viewLayer = view.layer;
[viewLayer setCornerRadius:view.frame.size.width/2];
[viewLayer setBorderWidth:0];
[viewLayer setMasksToBounds:YES];
}
May be you should try to change your way to create rounded ImageView using my version that create rounded ImageView by modifying ImageView's view layer . Hope it helps.

To maintain aspect ratio of UIImageView, after setting image use following line of code.
[_personImage setContentMode:UIViewContentModeScaleAspectFill];
For detailed description follow reference link:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIImageView_Class/

Related

How to create shadow effect on UIImage bounds

I have a UIImageView in which I have a UIImage obviously. I want to create a shadow effect only on the UIImage. My problem is that I cannot get the CGRect of the UIImage inside the UIImageView so I can apply the shadow effect on it by using the following method.
[mImageView.layer.shadowColor = [UIColor grayColor].CGColor;
mImageView.layer.shadowOffset = CGSizeMake(0.0f, 0.0f);
mImageView.layer.shadowOpacity = 0.9f;
mImageView.layer.masksToBounds = NO;
CGRect imageFrame = mImageView.frame;
UIEdgeInsets shadowInsets = UIEdgeInsetsMake(0, 0, -1.5f, 0);
UIBezierPath *shadowPath = [UIBezierPath bezierPathWithRect:UIEdgeInsetsInsetRect(imageFrame, shadowInsets)];
mImageView.layer.shadowPath = shadowPath.CGPath;
Please consider the image attached for this problem.
The problem is critical too because the UIImage can be an image of a rigid dimension because it is a cropped image as you can see in the picture attached.
The UIImageView’s bound is equal to the view’s bound here. So when applying the effect using the method above, it creates a UIBezierPath on the whole UIImageView, not only to the UIImage. As in the method, I cannot get the exact CGRect of the UIImage.
Any solution? What am I missing?
cropped image
UIImage is always rectangular, so is UIImageView. I believe you want to put shadow only around the jagged border of the cropped area right? If that is the case, you cannot use this method. You need to use CoreGraphics or others, to get the effect you want. For example, you can create a copy of this image in memory, blackened it, and blur it and paste it behind your image to create a shadowy effect.

Merge two images in swift

I am showing users on a map view with custom markers. Each marker will contain the user's image, like in the image below:
There might be multiple users displayed as markers on the map. I get the data of users and their images through an API. The image which I receive from the API is just a rectangular image. But I have to show that image very similar to the above shown image. So I thought of two solution.
Get the marker image from the API itself that can be easily displayed as an image on the map.
I have the outer ellipse as an image. I can place a round image in that ellipse and create a new image. That can further be used as a marker. But for this I'll have to merge two photos. I am able to merge them. But the users image is always rectangle. I am not able to make it round.
Can any one help me with a better solution or just complete my solution?
The first option will be the easiest. If you re going with the second option then here's something:
-(UIImage *)makeRoundedImage:(UIImage *) image
radius: (float) radius {
CALayer *imageLayer = [CALayer layer];
imageLayer.backgroundColor = [UIColor whiteColor].CGColor;
imageLayer.frame = CGRectMake(0, 0, image.size.width, image.size.height);
imageLayer.contents = (id) image.CGImage;
imageLayer.masksToBounds = YES;
imageLayer.cornerRadius = radius;
UIGraphicsBeginImageContext(image.size);
[imageLayer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *roundedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return roundedImage;
}
This will create a round UIImage with a white background. Just use the resulting UIImage as the marker icon.
This won't answer you question completely, but to rounder the imageView use this(This code is in objective C and the "profilePic" is an example UIImageView):
profilePic.layer.cornerRadius = profilePic.frame.size.width / 2;

Implement Blur over parts of view

How can I implement the image below pragmatically - meaning the digits can change at runtime or even be replaced with a movie?
Just add a blurred UIView on top of your thing.
For example...make a UIImage of your desired view size, blur it using CIFilter and then add it to your view .It should achieve the desired effect.
This is generally the same question and is answered by quite a few methods.. Anyway I would propose 1 more:
Get the image from UIView
+ (UIImage *)imageFromLayer:(CALayer *)layer {
UIGraphicsBeginImageContext([layer frame].size);
[layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *outputImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return outputImage;
}
rather yet play around a bit with this to get the desired part of the view as the image. Now create a new view and add to it image views (with the image you get from layer). Then move the centers of the image views to achieve gaussian algorithm and take the image from this layer again and place it back on the original view.
Moving the center should be defined by radius fragment (I'd start with .5f) and resample range.
for(int i=1; i<resampleCount; i++) {
view1.center = CGPointMake(view1.center.x + radiusFragment*i, view1.center.y);
view2.center = CGPointMake(view2.center.x - radiusFragment*i, view2.center.y);
view3.center = CGPointMake(view3.center.x, view3.center.y + radiusFragment*i);
view4.center = CGPointMake(view4.center.x, view4.center.y - radiusFragment*i);
//add the subviews
}
//get the image from view
All the subviews need to have alpha set to 1.0f/(resampleCount*4)
This method might not be the fastest but it would be extremely easy to implement and if you can pimp the radius and resample range to minimum fragments it should do pretty well.
use a UIView whith white background and decrease the alpha property
blurView.backgroundColor=[UIColor colorWithRed:255 green:255 blue:255 alpha:0.3]

Crop UIImage from a transformed UIImageView

I am letting the user capture an image from the camera or picking one from the library.
This image I display in an UIImageView.
The user can now scale and position the image within a bounding box, exactly like you would do using the UIImagePickerController when allowsEditing is set to YES.
When the user is satisfied with the result and taps Done I would like to produce a cropped UIImage.
The problem arises when using CGImageCreateWithImageInRect as this does not take the scaling into account. The transform is applied to the imageView like this:
CGAffineTransform transform = CGAffineTransformScale(self.imageView.transform, newScale, newScale);
[self.imageView setTransform:transform];
Using a gestureRecognizer.
I assume what is happening is; the UIImageView is scaled and moved, it then applies the UIViewContentModeScaleAspectFit to the UIImage is holds and when I ask it to crop the image, it does exactly that - whit no regards to the scaling positioning. The reason I think this, is that if I don't scale or move the image but just tap Done straight away the cropping works.
I crop the image like this:
- (UIImage *)cropImage:(UIImage*) img toRect:(CGRect)rect {
CGFloat scale = [[UIScreen mainScreen] scale];
if (scale>1.0) {
rect = CGRectMake(rect.origin.x*scale , rect.origin.y*scale, rect.size.width*scale, rect.size.height*scale);
}
CGImageRef imageRef = CGImageCreateWithImageInRect([img CGImage], rect);
UIImage *result = [UIImage imageWithCGImage:imageRef scale:self.imageView.image.scale orientation:self.imageView.image.imageOrientation];
// UIImage *result = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
return result;
}
Passing in a cropRect from a view that is a subView of my main view (the square overlay box, like in UIImagePickerController). Main UIView has a UIImageView that gets scaled and a UIView that displays the crop rectangle.
How can I get the "what you see is what you get" cropping and which factors must I take into account. Or maybe suggestions if I should implemented the hierarchy or scaling differently.
Try a simple trick. Apple has got samples on its site to show how to zoom into a photo using code. Once done zooming, using graphic context take the frame size of the bounding view, and take the image with that. Eg Uiview contains scroll view which has the zoomed image. So the scrollview zooms and so does your image, now take the frame size of your bounding UIview, and create an image context out of it and then save that as a new image. Tell me if that makes sense.
Cheers :)

Can I bake / flatten an UIImageView including its layer with rounded corners and masksToBounds

I'm trying to flatten some images I get from a server down to 40 x 40 thumbnails, so I can save them in /Library/Caches and use those instead with UITableViewCell's UIImage.
So far, I know how bake / flatten an image like so:
UIImage *newThumbnail = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:imageURL]]];
UIGraphicsBeginImageContext(CGSizeMake(40, 40));
[newThumbnail drawInRect:CGRectMake(0, 0, 40, 40)];
newThumbnail = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[UIImagePNGRepresentation(newThumbnail) writeToFile:imageCachePath atomically:YES];
I'd also like to include rounded corners in the flattened image. But right now, I create the rounded corners by manipulating the layer of the UIImageView that hosts the UIIMage. Like so:
imageView.layer.cornerRadius = 7.0;
imageView.layer.masksToBounds = YES;
imageView.layer.borderColor = [UIColor blackColor].CGColor;
imageView.layer.borderWidth = 1.0;
So how do I include the above layer modifications into the whole UIGraphicsBeginImageContext mechanism? Or is there any better way of doing it?
Option (1), which involves more learning and more work, but is more flexible:
Take a look through the CGContextRef docs.
Figure how to draw a rounded corner path. (There's a bunch of sample code floating around the internets using the CTM.)
To simulate cornerRadius and masksToBounds, use that path to set a clipping path before drawing your image.
To simulate the borderColor plus borderWidth, set an appropriate stroke color and width and then stroke that path.
Option (2):
Try rendering your UIImageView.layer into your context with renderInContext:.

Resources