create UIImage programmatically for show marker on google map? - ios

In my app i integrated Google map sdk for iOS. iwant to show marker with sequence number on it.like
The number of marker will be decided at run time so i can not simply put an mage for each marker, somehow i have to create it programmatically. I'v an image without sequence on it. my idea is to create an image using that image and write number on it while creating it. But don't know how.
Any help would be appreciated.

Thanks to #knshn for giving me the link in comment. here is my solution
-(UIImage *)getImage :(UIImage *)icon stop:(NSString *)stopNumber color:(UIColor *)color
{
// create label
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, icon.size.width,icon.size.height)];
[label setText:stopNumber];
[label setTextColor:color];
[label setFont:[UIFont boldSystemFontOfSize:11]];
label.textAlignment = NSTextAlignmentCenter;
// use UIGraphicsBeginImageContext() to draw them on top of each other
//start drawing
UIGraphicsBeginImageContext(icon.size);
//draw image
[icon drawInRect:CGRectMake(0, 0, icon.size.width, icon.size.height)];
//draw label
[label drawTextInRect:CGRectMake((icon.size.width - label.frame.size.width)/2, -5, label.frame.size.width, label.frame.size.height)];
//get the final image
UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resultImage;
}
Use in Swift
func getImage(_ icon: UIImage?, stop stopNumber: String?, color: UIColor?) -> UIImage? {
// create label
let label = UILabel(frame: CGRect(x: 0, y: 0, width: icon?.size.width ?? 0.0, height: icon?.size.height ?? 0.0))
label.text = stopNumber
label.textColor = color
label.font = FontFamily.Metropolis.semiBold.font(size: 15)
label.textAlignment = .center
//start drawing
UIGraphicsBeginImageContext(icon?.size ?? CGSize.zero)
//draw image
icon?.draw(in: CGRect(x: 0, y: 0, width: icon?.size.width ?? 0.0, height: icon?.size.height ?? 0.0))
//draw label
label.drawText(in: CGRect(x: ((icon?.size.width ?? 0.0) - label.frame.size.width) / 2, y: -3, width: label.frame.size.width, height: label.frame.size.height))
//get the final image
let resultImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return resultImage
}

Related

google maps iOS SDK: custom icons to be used as markers

The Android API has a very convenient class for this, IconGenerator. Using the IconGenerator in my Android app, I can easily make a marker that:
is a simple rectangle with the color of my choosing.
resizes to hold text of any length.
is NOT an info window - I'd like the marker itself to contain the text as shown in the image below from the android version.
// Android - problem solved with IconGenerator
IconGenerator iconGenerator = new IconGenerator(context);
iconGenerator.setStyle(IconGenerator.STYLE_GREEN); // or any other color
Bitmap iconBitmap = iconGenerator.makeIcon(myString);
Marker m = new MarkerOptions().icon(BitmapDescriptorFactory.fromBitmap(iconBitmap))
.position(myLatLng);
map.addMarker(m); // map is a com.google.android.gms.maps.GoogleMap
Is there a way to do something as simple as this in iOS using Swift?
There has been a recent release of the iOS api that allows "marker customization", but I don't see how to apply it to this use case.
// iOS (Swift) - I don't know how to create the icon as in code above
let marker = GMSMarker(position: myLatLng)
marker.icon = // How can I set to a rectangle with color/text of my choosing?
marker.map = map // map is a GMSMapView
Here is what I have done
let marker = GMSMarker()
// I have taken a pin image which is a custom image
let markerImage = UIImage(named: "mapMarker")!.withRenderingMode(.alwaysTemplate)
//creating a marker view
let markerView = UIImageView(image: markerImage)
//changing the tint color of the image
markerView.tintColor = UIColor.red
marker.position = CLLocationCoordinate2D(latitude: 28.7041, longitude: 77.1025)
marker.iconView = markerView
marker.title = "New Delhi"
marker.snippet = "India"
marker.map = mapView
//comment this line if you don't wish to put a callout bubble
mapView.selectedMarker = marker
The output is
And my marker image was
You can change your color as per your need. Also if you want something in rectange, you can just create a simple small rectangular image and use it like I did above and change the color of your need.
Or if you want a rectangle with text within it, you can just create a small UIView with some label and then convert that UIView in UIImage and can do the same thing.
//function to convert the given UIView into a UIImage
func imageWithView(view:UIView) -> UIImage {
UIGraphicsBeginImageContextWithOptions(view.bounds.size, false, 0.0)
view.layer.render(in: UIGraphicsGetCurrentContext()!)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
Hope it helps!!
Here is what i have done for solving the same issue, that you are facing.
I have added below image in my image assets,
Now i added below method in my code:
-(UIImage*)drawText:(NSString*)text inImage:(UIImage*)image
{
UIFont *font = [UIFont boldSystemFontOfSize:11];
CGSize size = image.size;
UIGraphicsBeginImageContextWithOptions(size, NO, 0.0f);
[image drawInRect:CGRectMake(0, 0, size.width, size.height)];
CGRect rect = CGRectMake(0, 0, image.size.width, image.size.height);
NSMutableParagraphStyle *paragraphStyle = [[NSParagraphStyle defaultParagraphStyle] mutableCopy];
paragraphStyle.alignment = NSTextAlignmentCenter;
NSDictionary *attributes = #{
NSFontAttributeName : font,
NSParagraphStyleAttributeName : paragraphStyle,
NSForegroundColorAttributeName : [UIColor redColor]
};
CGSize textSize = [text sizeWithAttributes:attributes];
CGRect textRect = CGRectMake((rect.size.width-textSize.width)/2, (rect.size.height-textSize.height)/2 - 2, textSize.width, textSize.height);
[text drawInRect:CGRectIntegral(textRect) withAttributes:attributes];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Now, I called this method, while assigning icon to GMSMarker, like this:
marker.icon = [self drawText:#"$33.6" inImage:[UIImage imageNamed:#"icon-marker"]];
It will generate the image icon like below:
Here, I kept the background Image size fixed, as i needed. You can still customize it to adjust it according to text size, as well as multiple lines.
UPDATE
Updated code in Swift:
func drawText(text:NSString, inImage:UIImage) -> UIImage? {
let font = UIFont.systemFont(ofSize: 11)
let size = inImage.size
//UIGraphicsBeginImageContext(size)
let scale = UIScreen.main.scale
UIGraphicsBeginImageContextWithOptions(inImage.size, false, scale)
inImage.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
let style : NSMutableParagraphStyle = NSMutableParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle
style.alignment = .center
let attributes:NSDictionary = [ NSAttributedString.Key.font : font, NSAttributedString.Key.paragraphStyle : style, NSAttributedString.Key.foregroundColor : UIColor.black ]
let textSize = text.size(withAttributes: attributes as? [NSAttributedString.Key : Any])
let rect = CGRect(x: 0, y: 0, width: inImage.size.width, height: inImage.size.height)
let textRect = CGRect(x: (rect.size.width - textSize.width)/2, y: (rect.size.height - textSize.height)/2 - 2, width: textSize.width, height: textSize.height)
text.draw(in: textRect.integral, withAttributes: attributes as? [NSAttributedString.Key : Any])
let resultImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return resultImage
}
You can simply add a custom view as marker in Google Map.
let marker = GMSMarker(position: coordinate)
marker.iconView = view // Your Custom view here
You can use imageView (for containing that orange color box) and label (for text) above it
I tried to rewrite Mehul Thakkar answer to Swift 3. Hope it will work for you. But it really easier to make custom view as Dari said.
func drawText(text:NSString, inImage:UIImage) -> UIImage? {
let font = UIFont.systemFont(ofSize: 11)
let size = inImage.size
UIGraphicsBeginImageContext(size)
inImage.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
let style : NSMutableParagraphStyle = NSMutableParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle
style.alignment = .center
let attributes:NSDictionary = [ NSFontAttributeName : font, NSParagraphStyleAttributeName : style, NSForegroundColorAttributeName : UIColor.red ]
let textSize = text.size(attributes: attributes as? [String : Any])
let rect = CGRect(x: 0, y: 0, width: inImage.size.width, height: inImage.size.height)
let textRect = CGRect(x: (rect.size.width - textSize.width)/2, y: (rect.size.height - textSize.height)/2 - 2, width: textSize.width, height: textSize.height)
text.draw(in: textRect.integral, withAttributes: attributes as? [String : Any])
let resultImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return resultImage
}
Here a Swift 5 version of Eridana's Swift conversion of Mehul Thakkar's answer.
func drawTextT(text:NSString, inImage:UIImage) -> UIImage? {
let font = UIFont.systemFont(ofSize: 11)
let size = inImage.size
UIGraphicsBeginImageContext(size)
inImage.draw(in: CGRect(x: 0, y: 0, width: size.width, height: size.height))
let style : NSMutableParagraphStyle = NSMutableParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle
style.alignment = .center
let attributes:NSDictionary = [ NSAttributedString.Key.font : font, NSAttributedString.Key.paragraphStyle : style, NSAttributedString.Key.foregroundColor : UIColor.red ]
//let textSize = text.size(attributes: attributes as? [String : Any])
let textSize = text.size(withAttributes: attributes as? [NSAttributedString.Key : Any] )
let rect = CGRect(x: 0, y: 0, width: inImage.size.width, height: inImage.size.height)
let textRect = CGRect(x: (rect.size.width - textSize.width)/2, y: (rect.size.height - textSize.height)/2 - 2, width: textSize.width, height: textSize.height)
text.draw(in: textRect.integral, withAttributes: attributes as? [NSAttributedString.Key : Any] )
let resultImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return resultImage
}
Simplest way to achieve if you have just 1 image :
marker.icon = #imageLiteral(resourceName: "fault_marker")
1) In latest XCode write marker.icon = "imageLiteral".
2) Double click the dummy image icon appeared just now.
3) select desired image.
//func to get Image view
// Url String :- Your image coming from server
//image :- Background image
func drawImageWithProfilePic(urlString:String, image: UIImage) -> UIImageView {
let imgView = UIImageView(image: image)
imgView.frame = CGRect(x: 0, y: 0, width: 90, height: 90)
let picImgView = UIImageView()
picImgView.sd_setImage(with:URL(string: urlString))
picImgView.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
imgView.addSubview(picImgView)
picImgView.center.x = imgView.center.x
picImgView.center.y = imgView.center.y-10
picImgView.layer.cornerRadius = picImgView.frame.width/2
picImgView.clipsToBounds = true
imgView.setNeedsLayout()
picImgView.setNeedsLayout()
// let newImage = imageWithView(view: imgView)
// return newImage
return imgView
}
//SHOW ON MAP
let marker = GMSMarker()
marker.position = CLLocationCoordinate2D(latitude: Double(lat)!, longitude: Double(long)!)
marker.iconView = self.drawImageWithProfilePic(urlString:getProviderImage,image: UIImage.init(named: "red")!)
Simple and easiest way to change icon. just replace these 3 icon (default marker.png) to your icon (1x,2x,3x).
In Google Cluster there was a problem with marker (icon) change.

how to place a scrolling image behind a stationary image in Swift

I am trying to port an artificial horizon app I wrote for a PC in c# to swift. It has a bezel image which does not move and behind it is a horizon image which can move up and down behind the bezel. The "window" part of the bezel is yellow so in c# I just made the yellow opaque.
In swift I stated with the horizon inside of a UIScrollView but I'm not sure how to get that to work with a second image that should not scroll.
Not all that up to speed on this swift stuff, can someone point me in the right direction?
let view: UIView = UIView.init(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
let scrollView = UIScrollView.init(frame: view.bounds)
view.addSubview(scrollView)
let backImage: UIImage = fromColor(UIColor.redColor(), size: CGSize(width: 1000, height: 1000))
let backImageView: UIImageView = UIImageView.init(image: backImage)
scrollView.addSubview(backImageView)
scrollView.contentSize = CGSize.init(width: backImage.size.width, height: backImage.size.height)
let frontImage: UIImage = fromColor(UIColor.blueColor(), size: CGSize(width: 100, height: 100))
let layer: CALayer = CALayer.init()
layer.frame = CGRect.init(x: view.center.x - 50, y: view.center.y - 50, width: 100, height: 100)
layer.contents = frontImage.CGImage
view.layer.addSublayer(layer)
func fromColor(color: UIColor, size: CGSize) -> UIImage {
let rect = CGRect(x: 0, y: 0, width: size.width, height: size.height)
UIGraphicsBeginImageContext(rect.size)
let context = UIGraphicsGetCurrentContext()
CGContextSetFillColorWithColor(context, color.CGColor)
CGContextFillRect(context, rect)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img
}
fromColor is a helper method.
Result of the code

How to get left padding on UITextField leftView image?

I am setting up a UIImageView as a leftView on a UITextField like so:
UIImageView *envelopeView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.height*.1, self.height*.1)];
envelopeView.image = [UIImage imageNamed:#"envelope.png"];
envelopeView.contentMode = UIViewContentModeScaleAspectFit;
envelopeView.bounds = CGRectInset(envelopeView.frame, 15, 10);
self.emailAddress.leftView = envelopeView;
self.emailAddress.leftViewMode = UITextFieldViewModeAlways;
which gets me the following:
As you can see the left size of the image goes right up to the left edge of the button even though I tried to set an inset. How can I move this envelope in so that it's got padding on all sides?
Update: I tried the proposed answer of changing the UIImageView frame like so, but the envelope is still lined up on the left side at the border of the UITextField:
CGFloat padding = 20;
UIImageView *envelopeView = [[UIImageView alloc] initWithFrame:CGRectMake(3*padding, padding, self.height*.1-padding, self.height*.1-padding)];
For Swift 3 Users
Here is what worked for me:
extension UITextField {
/// set icon of 20x20 with left padding of 8px
func setLeftIcon(_ icon: UIImage) {
let padding = 8
let size = 20
let outerView = UIView(frame: CGRect(x: 0, y: 0, width: size+padding, height: size) )
let iconView = UIImageView(frame: CGRect(x: padding, y: 0, width: size, height: size))
iconView.image = icon
outerView.addSubview(iconView)
leftView = outerView
leftViewMode = .always
}
}
test:
txOrigin.setLeftIcon(icon_location)
result:
For Swift 4.2 +
You can use this extension:
extension UITextField {
func leftImage(_ image: UIImage?, imageWidth: CGFloat, padding: CGFloat) {
let imageView = UIImageView(image: image)
imageView.frame = CGRect(x: padding, y: 0, width: imageWidth, height: frame.height)
imageView.contentMode = .center
let containerView = UIView(frame: CGRect(x: 0, y: 0, width: imageWidth + 2 * padding, height: frame.height))
containerView.addSubview(imageView)
leftView = containerView
leftViewMode = .always
}
}
you can simply try this:
UIImageView *envelopeView = [[UIImageView alloc] initWithFrame:CGRectMake(20, 0, 30, 30)];
envelopeView.image = [UIImage imageNamed:#"comment-128.png"];
envelopeView.contentMode = UIViewContentModeScaleAspectFit;
UIView *test= [[UIView alloc]initWithFrame:CGRectMake(20, 0, 30, 30)];
[test addSubview:envelopeView];
[self.textField.leftView setFrame:envelopeView.frame];
self.textField.leftView =test;
self.textField.leftViewMode = UITextFieldViewModeAlways;
You can use this. Change your frame according to your need.
NSTextAttachment* placeholderImageTextAttachment = [[NSTextAttachment alloc] init];
placeholderImageTextAttachment.image = [UIImage imageNamed:#"Search"];
placeholderImageTextAttachment.bounds = CGRectMake(0, -2, 16, 16);
NSMutableAttributedString* placeholderImageString = [[NSAttributedString attributedStringWithAttachment:placeholderImageTextAttachment] mutableCopy];
NSMutableAttributedString* placeholderString = [[NSMutableAttributedString alloc] initWithString:NSLocalizedString(#" Search", nil)];
[placeholderImageString appendAttributedString:placeholderString];
_txtFieldSearch.attributedPlaceholder = placeholderImageString;
_txtFieldSearch.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;

Add text on custom marker on google map for ios

Am trying to put marker with Textview .Is there any posibility to add text over marker on google map in ios.
Like This
You must make a view, where you must create an imageView (with your marker image) and Label (with your text) and take a screenshot of that view, and set as icon to your GMSMarker.
Something like this:
- (void)foo
{
GMSMarker *marker = [GMSMarker new];
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0,0,60,60)];
UIImageView *pinImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"myPin"]];
UILabel *label = [UILabel new];
label.text = #"1";
//label.font = ...;
[label sizeToFit];
[view addSubview:pinImageView];
[view addSubview:label];
//i.e. customize view to get what you need
UIImage *markerIcon = [self imageFromView:view];
marker.icon = markerIcon;
marker.map = self.mapView;
}
- (UIImage *)imageFromView:(UIView *) view
{
if ([[UIScreen mainScreen] respondsToSelector:#selector(scale)]) {
UIGraphicsBeginImageContextWithOptions(view.frame.size, NO, [[UIScreen mainScreen] scale]);
} else {
UIGraphicsBeginImageContext(view.frame.size);
}
[view.layer renderInContext: UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
If you want to display something like this , then just follow these steps. It is very simple, You can use this method.
-(UIImage *)createImage:(NSUInteger)count{ //count is the integer that has to be shown on the marker
UIColor *color = [UIColor redColor]; // select needed color
NSString *string = [NSString stringWithFormat:#"%lu",(unsigned long)count]; // the string to colorize
NSDictionary *attrs = #{ NSForegroundColorAttributeName : color };
NSAttributedString *attrStr = [[NSAttributedString alloc] initWithString:string attributes:attrs]; // add Font according to your need
UIImage *image = [UIImage imageNamed:#"ic_marker_orange"]; // The image on which text has to be added
UIGraphicsBeginImageContext(image.size);
[image drawInRect:CGRectMake(0,0,image.size.width,image.size.height)];
CGRect rect = CGRectMake(20,5, image.size.width, image.size.height);// change the frame of your text from here
[[UIColor whiteColor] set];
[attrStr drawInRect:rect];
UIImage *markerImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return markerImage;}
and when you set marker to the map then just set
GMSMarker *marker = [[GMSMarker alloc] init];
marker.icon = [self createImage:[model.strFriendCount integerValue]]; // pass any integer to the method.
Here is the Swift 5 version of Kunal's answer:
//count is the integer that has to be shown on the marker
func createImage(_ count: Int) -> UIImage {
let color = UIColor.red
// select needed color
let string = "\(UInt(count))"
// the string to colorize
let attrs: [NSAttributedString.Key: Any] = [.foregroundColor: color]
let attrStr = NSAttributedString(string: string, attributes: attrs)
// add Font according to your need
let image = UIImage(named: "ic_marker_orange")!
// The image on which text has to be added
UIGraphicsBeginImageContext(image.size)
image.draw(in: CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(image.size.width), height: CGFloat(image.size.height)))
let rect = CGRect(x: CGFloat(20), y: CGFloat(5), width: CGFloat(image.size.width), height: CGFloat(image.size.height))
attrStr.draw(in: rect)
let markerImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return markerImage
}
Hope this helps someone else.
func createImage(_ count: Int) -> UIImage? {
let string = String(count)
let paragraphStyle = NSMutableParagraphStyle()
let font = UIFont.systemFont(ofSize: 9.5)
paragraphStyle.alignment = .center
let attributes: [NSAttributedString.Key: Any] = [
.font : font,
.foregroundColor: UIColor.black,
.paragraphStyle: paragraphStyle
]
let attrStr = NSAttributedString(string: string, attributes: attributes)
let image = self.imageWithImage(image: UIImage(named: "pin_online.png")!, scaledToSize: CGSize(width: 50.0, height: 60.0))
UIGraphicsBeginImageContext(image.size)
UIGraphicsBeginImageContextWithOptions(image.size, false, 0.0)
image.draw(in: CGRect(x: 0, y: 0, width: CGFloat(image.size.width), height: CGFloat(image.size.height)))
let rect = CGRect(x: 14.7, y: CGFloat(3), width: CGFloat(image.size.width), height: CGFloat(image.size.height))
attrStr.draw(in: rect)
let markerImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return markerImage
}

UIGraphicsBeginImageContextWithOptions not capturing shadows / gradients

THE PROBLEM
I'm using UIGraphicsBeginImageContextWithOptions to save a screenshot into a UIImage. While this works, the resulting UIImage is missing any shadows and gradients.
How do I get it to also screenshot the layer stuff?
TEST CODE SHOWING THE PROBLEM
#import "ViewController.h"
#import <QuartzCore/QuartzCore.h>
#implementation ViewController
- (void)viewDidLoad {
//super
[super viewDidLoad];
//background
self.view.backgroundColor = [UIColor whiteColor];
//container
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(10, 10, 300, 200)];
container.backgroundColor = [UIColor blackColor];
[self.view addSubview:container];
//circle
UIView *circle = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 10, 10)];
circle.backgroundColor = [UIColor whiteColor];
circle.layer.cornerRadius = 5;
circle.layer.shadowColor = [UIColor redColor].CGColor;
circle.layer.shadowOffset = CGSizeZero;
circle.layer.shadowOpacity = 1;
circle.layer.shadowRadius = 10;
circle.layer.shadowPath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(-10, -10, 30, 30)].CGPath;
[container addSubview:circle];
//screenshot
UIGraphicsBeginImageContextWithOptions(container.bounds.size, container.opaque, 0.0);
[container.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *screenshot = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//image view
UIImageView *iv = [[UIImageView alloc] initWithFrame:CGRectMake(10, 568-200-20-10, 300, 200)];
iv.image = screenshot;
[self.view addSubview:iv];
}
#end
SIMULATOR SCREENSHOT SHOWING THE PROBLEM
The top area is the original view. The bottom area is a UIImageView with the screenshot.
In this line ,
UIGraphicsBeginImageContextWithOptions(container.bounds.size, container.opaque, 0.0);
put NO instead of container.opaque
Use this method ,
- (UIImage *)imageOfView:(UIView *)view
{
if ([[UIScreen mainScreen] respondsToSelector:#selector(scale)]) {
UIGraphicsBeginImageContextWithOptions(view.bounds.size, NO, 0.0);
} else {
UIGraphicsBeginImageContext(view.bounds.size);
}
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage * img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
For drop shadow on an Image:
public func generateShadow(for image: UIImage, shadowOffset: CGSize,blur: CGFloat, shadowColor: CGColor ) -> UIImage? {
let size = CGSize(width: image.size.width + blur, height:
image.size.height + blur)
return MediaPickerFramework.generateImage(CGSize(width: size.width, height: size.width), contextGenerator: { size, context in
context.clear(CGRect(origin: CGPoint(), size: size))
context.setShadow(offset: shadowOffset,
blur: blur,
color: shadowColor)
let center = CGPoint(x: size.width / 2, y: size.height / 2)
let imageOrigin = CGPoint(x: center.x - (image.size.width / 2), y: center.y - (image.size.height / 2))
context.draw(image.cgImage!,
in: CGRect(x: imageOrigin.x, y: imageOrigin.y, width: image.size.width, height: image.size.height),
byTiling:false)
})
}
and for draw Gradient on an image, you can use the below function
func generateGradientTintedImage(image: UIImage?, colors: [UIColor]) -> UIImage? {
guard let image = image else {
return nil
}
let imageSize = image.size
UIGraphicsBeginImageContextWithOptions(imageSize, false, image.scale)
if let context = UIGraphicsGetCurrentContext() {
let imageRect = CGRect(origin: CGPoint(), size: imageSize)
context.saveGState()
context.translateBy(x: imageRect.midX, y: imageRect.midY)
context.scaleBy(x: 1.0, y: -1.0)
context.translateBy(x: -imageRect.midX, y: -imageRect.midY)
context.clip(to: imageRect, mask: image.cgImage!)
let gradientColors = colors.map { $0.cgColor } as CFArray
let delta: CGFloat = 1.0 / (CGFloat(colors.count) - 1.0)
var locations: [CGFloat] = []
for i in 0 ..< colors.count {
locations.append(delta * CGFloat(i))
}
let colorSpace = CGColorSpaceCreateDeviceRGB()
let gradient = CGGradient(colorsSpace: colorSpace, colors: gradientColors, locations: &locations)!
context.drawLinearGradient(gradient, start: CGPoint(x: 0.0, y: imageRect.height), end: CGPoint(x: 0.0, y: 0.0), options: CGGradientDrawingOptions())
context.restoreGState()
}
let tintedImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return tintedImage
}

Resources