How to create shadow effect on UIImage bounds - ios

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.

Related

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;

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

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/

Making the Background Image of a UIView on Aspect Fit

I'm working on a sort of drawing app using objective-c, and for one of my UIViews, I want there to be a background image to it. However, I want this background image on the actual UIView, not a separate UIImageView. I did that using this:
self.tempDrawImage.image = [UIImage imageNamed:#"image.jpg"];
In this code, tempDrawImage is a UIImageView I made programmatically, and after initializing it, I wrote this later in the code so that the drawings would appear on top of the image. I don't know if this is helpful, but I thought I'd include it anyway just in case it does help.
- (UIImageView *)tempDrawImage
{
if(!_tempDrawImage) _tempDrawImage = [UIImageView new];
return _tempDrawImage;
}
- (void)drawRect:(CGRect)rect
{
UIGraphicsGetCurrentContext();
[self.tempDrawImage.image drawInRect:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
}
Now, I'm struggling to make the image that I set to image.jpg in the beginning aspect fit. How could I do that?
Try this
self.tempDrawImage.contentMode = UIViewContentModeScaleAspectFit;
You can use UIViewContentModeScaleAspectFit
self.tempDrawImage.contentMode = UIViewContentModeScaleAspectFit;

Mask arbitrarily sized UIImageView with resizable UIImage mask

Current code:
self.backgroundImageView.image = [self.message imageOfSize:self.message.size]; // Random image, random size
UIImage *rightBubbleBackground = [[UIImage imageNamed:#"BubbleRight"]
resizableImageWithCapInsets:BubbleRightCapInsets
resizingMode:UIImageResizingModeStretch];
CALayer *mask = [CALayer layer];
mask.contents = (id)[rightBubbleBackground CGImage];
mask.frame = self.backgroundImageView.layer.frame;
self.backgroundImageView.layer.mask = mask;
self.backgroundImageView.layer.masksToBounds = YES;
This does not work properly. Though the mask is applied, the rightBubbleBackground does not resize correctly to fit self.backgroundImageView, even though it has resizing cap insets (BubbleRightCapInsets) set.
Original Image:
Mask image (rightBubbleBackground):
Result:
I found this answer but it only works for symmetrical images. Maybe I could modify that answer for my use.
I was wrong. That answer can be modified to work for asymmetrical images. I worked on that answer a bit and solved my own problem.
The following code made my cap insets work for the mask layer:
mask.contentsCenter =
CGRectMake(BubbleRightCapInsets.left/rightBubbleBackground.size.width,
BubbleRightCapInsets.top/rightBubbleBackground.size.height,
1.0/rightBubbleBackground.size.width,
1.0/rightBubbleBackground.size.height);
Result:
I had (part of) the same problem - i.e. the pixelated layer contents. For me it was solved by setting the contentsScale value on the CALayer - for some reason the default scale on CALayers is always 1.0, even on Retina devices.
i.e.
layer.contentsScale = [UIScreen mainScreen].scale;
Also, if you're drawing a shape using CAShapeLayer and wondering its edges look a little jagged on retina devices, try:
shapeLayer.rasterizationScale = [UIScreen mainScreen].scale;
shapeLayer.shouldRasterize = YES;

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