Merge two images in swift - ios

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;

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.

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/

iOS: Adding an outline/stroke to an image context with a transparent background

The images that goes through here are PNGs of different shapes with a transparent background. In addition to merging them (which works fine), I'd like to give the new image a couple of pixels thick outline. But I can't seem to manage that.
(So just to clarify, I'm after an outline around the actual shapes in the context, not a rectangle around the entire image.)
+ (UIImage *)mergeBackgroundImage:(UIImage *)backgroundImage withOverlayingImage:(UIImage *)overlayImage{
UIGraphicsBeginImageContextWithOptions(backgroundImage.size, NO, backgroundImage.scale);
[backgroundImage drawInRect:CGRectMake(0, 0, backgroundImage.size.width, backgroundImage.size.height)];
[overlayImage drawInRect:CGRectMake(backgroundImage.size.width - overlayImage.size.width, backgroundImage.size.height - overlayImage.size.height, overlayImage.size.width, overlayImage.size.height)];
//Add stroke.
UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return result;
}
Thanks for your time!
Markus
If you make a CALayer who's backing is set to a CGImage of your image, you can then use it as a masking layer for your layer that requires an outline1. And once you've done that, you can render your layer into another context, and then get another UIImage from that.
// edit: Something like what's describe in this answer.

Can we draw a line graph using core plot or any other graph library with my requirement?

My requirements:
1) I need to draw a graph with date as xAxis and tracking result value as yAxis in which I need multiple points indicated for a day for different-2 time tracking and a scatter graph that is drawn on the basis of the average for that particular day as in iMoodJournal App.
2) I need to export the graph to image or customised pdf in which I need the full graph not only the graph that is displayed on the screen means I need the hidden part as scroll also in the image.
I am succeeded to export to image as the graph is displaying on screen.
Thanks in advance
Although this might not cater to all your requirements, but I would recommend LineGraph which serves first point.
Once you have the graph in a view, you can create memory bitmap and save it as UIImage.
EDIT:
Use below code to convert UIView to UIImage.
#import <QuartzCore/QuartzCore.h>
+ (UIImage *) imageWithView:(UIView *)view
{
UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.opaque, 0.0);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
This is possible with Core Plot.
There are many examples of line plots (scatter plots) in the example apps included with Core Plot. It has many options to customize the appearance of the graph.
To make a graph larger than the screen, don't add it to a hosting view. Size the graph layer as big as you need and set up the plot space to show all of the data. Use the -imageOfLayer method to create an image of the graph or -dataForPDFRepresentationOfLayer to create a PDF.
We can use the following code to take screen shot of the part of the graph which is not visible:
- (IBAction) renderScrollViewToImage
{
UIImage* image = nil;
UIGraphicsBeginImageContext(_scrollView.contentSize);
{
CGPoint savedContentOffset = _scrollView.contentOffset;
CGRect savedFrame = _scrollView.frame;
_scrollView.contentOffset = CGPointZero;
_scrollView.frame = CGRectMake(0, 0, _scrollView.contentSize.width, _scrollView.contentSize.height);
[_scrollView.layer renderInContext: UIGraphicsGetCurrentContext()];
image = UIGraphicsGetImageFromCurrentImageContext();
_scrollView.contentOffset = savedContentOffset;
_scrollView.frame = savedFrame;
}
UIGraphicsEndImageContext();
if (image != nil) {
[UIImagePNGRepresentation(image) writeToFile: #"/tmp/test.png" atomically: YES];
system("open /tmp/test.png");
}
}

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