How to create gradient colour look like following image programatically.
-
I need to apply it over the image as gradient.. – user2823044 Apr 02 '14 at 12:37
-
You can use GPUIImage library from Brad Larson, it is well documented and really powerful. It also has a lot of feature on images: https://github.com/BradLarson/GPUImage – foOg Apr 02 '14 at 12:11
-
what did you try so far? – vikingosegundo Apr 02 '14 at 13:17
-
if using GPUImage, which filter should I use to implement the gradient? – Evelyn Loo Jul 02 '15 at 13:32
5 Answers
When you say "apply it over the image as a gradient", do you mean as a mask (revealing the image at the top, having it fade the image to transparent at the bottom)? If that's the case, you can apply that gradient as a mask, using CAGradientLayer
:
CAGradientLayer *gradientMask = [CAGradientLayer layer];
gradientMask.frame = self.imageView.bounds;
gradientMask.colors = @[(id)[UIColor whiteColor].CGColor,
(id)[UIColor clearColor].CGColor];
self.imageView.layer.mask = gradientMask;
The above does a simple vertical gradient (because the default is vertical, linear gradient). But you asked about startPoint
, endPoint
, and locations
. If for example, you wanted your mask applied horizontally, you would do:
gradientMask.startPoint = CGPointMake(0.0, 0.5); // start at left middle
gradientMask.endPoint = CGPointMake(1.0, 0.5); // end at right middle
If you wanted to have two gradients, one at the first 10% and another at the last 10%, you'd do:
gradientMask.colors = @[(id)[UIColor clearColor].CGColor,
(id)[UIColor whiteColor].CGColor,
(id)[UIColor whiteColor].CGColor,
(id)[UIColor clearColor].CGColor];
gradientMask.locations = @[@0.0, @0.10, @0.90, @1.0];
If you want a simple gradient by itself (not as a mask), you'd create a view
and then add the gradient layer to it:
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = view.bounds;
gradient.colors = @[(id)[UIColor whiteColor].CGColor,
(id)[UIColor blackColor].CGColor];
[view.layer addSublayer:gradient];
See the CAGradientLayer
class reference.

- 415,655
- 72
- 787
- 1,044
-
2thanks for help,bur i'm unable to understand start point,end point and locations of colors. – user2823044 Apr 03 '14 at 07:43
-
1@user2823044 I've updated my example with illustration of `startPoint`, `endPoint`, and `locations`. You don't need them given your example of a vertical gradient, but if you wanted the gradient going from left to right, you could use `startPoint` and `endPoint`. If you wanted gradient to not be evenly spaced across that range of `startPoint` and `endPoint`, you could use `locations` (which you'd only really play around with if you had more than two `colors`). – Rob Apr 03 '14 at 12:42
-
how can i draw the gradient with single color(black) with decreasing alphs from bottom to top – user2823044 Apr 03 '14 at 12:46
-
@user2823044 See last example in my answer (no `startPoint`, `endPoint` or `locations` needed), but rather than going from `whiteColor` to `blackColor`, go from `blackColor` to `clearColor`. – Rob Apr 03 '14 at 13:14
-
1Rob, I have a doubt adding a layer will affect memory or adding image as gradient is better.which has affect on memory leakage – user2823044 Apr 07 '14 at 04:09
-
2@user2823044 Well, neither "leaks". If you're worried about memory consumption, though, adding a gradient image takes more memory than a `CAGradientLayer` (and more memory than a custom `drawRect` method with Core Graphics gradient calls, too). When you load an image, don't be mislead by the small size of the PNG/JPEG file, but rather when loaded into memory, it will generally take 4 bytes per pixel (e.g. a full screen retina resolution image for 4" iPhone will take 3mb; for retina iPad that jumps to 12mb). – Rob Apr 07 '14 at 05:53
I just wrote an UIImage extension for Swift 2.0. Maybe it's of some use. You call it with an array of UIColor (any number) and a frame where the gradient should be drawn.
extension UIImage {
class func convertGradientToImage(colors: [UIColor], frame: CGRect) -> UIImage {
// start with a CAGradientLayer
let gradientLayer = CAGradientLayer()
gradientLayer.frame = frame
// add colors as CGCologRef to a new array and calculate the distances
var colorsRef = [CGColor]()
var locations = [NSNumber]()
for i in 0 ... colors.count-1 {
colorsRef.append(colors[i].CGColor as CGColorRef)
locations.append(Float(i)/Float(colors.count-1))
}
gradientLayer.colors = colorsRef
gradientLayer.locations = locations
// now build a UIImage from the gradient
UIGraphicsBeginImageContext(gradientLayer.bounds.size)
gradientLayer.renderInContext(UIGraphicsGetCurrentContext()!)
let gradientImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
// return the gradient image
return gradientImage
}
}
Call it like this:
let colors = [
UIColor.blueColor(),
UIColor.greenColor()
// and many more if you wish
]
let gradientImage = UIImage.convertGradientToImage(colors, frame: navigationBar.bounds)
and apply with:
.backgroundColor = UIColor(patternImage: gradientImage)
or
.setBackgroundImage(gradientImage, forBarMetrics: .Default)

- 2,779
- 3
- 26
- 33
-
You beautiful, beautiful man/woman/child! I had a core graphics gradient rendering setup that worked for 99% of images that I was trying to draw a gradient on top of but there was always that 1% that failed to draw the image and ended up butchering the quality of the image, making it all corrupted/grainy/pixelated. With the gradient layer it works perfectly everywhere (or so it seems). Bloody Apple... – CMash Mar 04 '16 at 15:08
CAGradientLayer *gradient = [CAGradientLayer layer];
gradient.frame = self.view.bounds;
gradient.startPoint = CGPointMake(1.0, 1.0); //Dark From bottom
gradient.endPoint = CGPointMake(1.0, 0);
gradient.colors = [NSArray arrayWithObjects:
(id)[[UIColor blackColor] CGColor],
(id)[[UIColor clearColor] CGColor], nil];
[self.view.layer insertSublayer:gradient atIndex:0];

- 170
- 2
- 9
This is the best approach, working for me as requirement
CAGradientLayer *gradientLayer = [CAGradientLayer layer];
gradientLayer.frame = yourImageView.layer.bounds;
gradientLayer.colors = [NSArray arrayWithObjects:
(id)[UIColor colorWithWhite:1.0f alpha:1.0f].CGColor,
(id)[UIColor colorWithWhite:0.0f alpha:0.9f].CGColor,
nil];
gradientLayer.locations = [NSArray arrayWithObjects:
[NSNumber numberWithFloat:0.0f],
[NSNumber numberWithFloat:1.0f],
nil];
[yourImageView.layer addSublayer:gradientLayer];

- 717
- 1
- 13
- 14
-(void) drawGradientinBounds: (CGRect) currentBounds withColors:(NSArray*) colors andPercentages:(NSArray *)percentages andGradientDirectionIsVertical:(BOOL)isGradientDirectionVertical
{
CGContextRef currentContext = UIGraphicsGetCurrentContext();
CGGradientRef glossGradient;
CGColorSpaceRef rgbColorspace;
size_t num_locations = [percentages count];
CGFloat locations[num_locations];
for(int i=0;i<num_locations;i++)
locations[i] = [[percentages objectAtIndex:i] floatValue];
int comps = [colors count]*4;
CGFloat components[comps];
for(int i = [colors count]-1;i>=0;i--)
{
comps--;
UIColor *c = [colors objectAtIndex:i];
const CGFloat *cg = CGColorGetComponents([c CGColor]);
components[comps] = cg[3];
comps--;
components[comps] = cg[2];
comps--;
components[comps] = cg[1];
comps--;
components[comps] = cg[0];
}
rgbColorspace = CGColorSpaceCreateDeviceRGB();
glossGradient = CGGradientCreateWithColorComponents(rgbColorspace, components, locations, num_locations);
CGPoint topCenter;
CGPoint endCenter;
if(isGradientDirectionVertical)
{
topCenter = CGPointMake(CGRectGetMidX(currentBounds), currentBounds.origin.y);
endCenter = CGPointMake(CGRectGetMidX(currentBounds), CGRectGetHeight(currentBounds)+currentBounds.origin.y);
}
else
{
topCenter = CGPointMake( currentBounds.origin.x,CGRectGetMidY(currentBounds));
endCenter = CGPointMake(CGRectGetWidth(currentBounds)+currentBounds.origin.x,CGRectGetMidY(currentBounds));
}
CGContextDrawLinearGradient(currentContext, glossGradient, topCenter, endCenter, 0);
CGGradientRelease(glossGradient);
CGColorSpaceRelease(rgbColorspace);
}
And the input to this method are bounds, colorArray:
[NSArray arrayWithObjects:[UIColor blackColor], [UIColor whiteColor], nil]
percentageArray:
[NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0], [NSNumber numberWithFloat:1.0], nil]