How fill MKCircleRenderer with blur color - ios

I have implemented custom implementation of MKCircleRenderer.I need to have a circle with attached color. I can fill it with specific color. But how can add blur effect?
Here is my code:
- (void)fillPath:(CGPathRef)path inContext:(CGContextRef)context_{
if(!distance)
return;
#synchronized (self) {
if(!image){
rect = CGPathGetBoundingBox(path);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextAddPath(context, path);
CGContextSetBlendMode (context, kCGBlendModePlusDarker);
CGContextClip(context);
CGFloat gradientLocations[2] = {0, 1.0f};
UIColor* color = [UIColor colorWithHTMLString:#"#27B255"];
const CGFloat* components = CGColorGetComponents(color.CGColor);
CGFloat gradientColors[8] = {components[0], components[1], components[2], 0.3, components[0], components[1], components[2], 0.3};
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, gradientColors, gradientLocations, 2);
CGColorSpaceRelease(colorSpace);
CGPoint gradientCenter = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect));
CGFloat gradientRadius = MIN(rect.size.width, rect.size.height) / 2;
CGContextDrawRadialGradient(context, gradient, gradientCenter, 0, gradientCenter, gradientRadius, kCGGradientDrawsAfterEndLocation);
CGGradientRelease(gradient);
if(distance.accuracy > 0){
CGFloat k = (CGFloat)(rect.size.width/(2*(distance.distance + distance.accuracy)));
CGFloat radius = (distance.distance - distance.accuracy) * k;
if(radius > 0){
CGContextSetFillColorWithColor(context, [UIColor clearColor].CGColor);
CGContextSetBlendMode(context, kCGBlendModeClear);
CGContextAddArc(context, CGRectGetMidX(rect), CGRectGetMidY(rect), radius, 0, 2 * M_PI, 0);
CGContextDrawPath(context, kCGPathFill);
CGContextSetBlendMode(context, kCGBlendModeNormal);
}
}
image = UIGraphicsGetImageFromCurrentImageContext();
image = [UIImageEffects imageByApplyingBlurToImage:image withRadius:1 tintColor:nil saturationDeltaFactor:1.0 maskImage:nil];
UIGraphicsEndImageContext();
}
}
CGContextDrawImage(context_, rect, image.CGImage);
}
I use UIImageEffects classes from Apple, but no result that I expect. Could you provide any other varian how to do this?

Related

Why is Core Graphics drawing this outline?

For some reason Core Graphics is drawing an extra outline around my path. Here is some sample code.
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextClearRect(context, rect);
CGContextSaveGState(context);
float startRadius = 71.0;
float startAngle = 135, endAngle = 405;
endAngle = startAngle + (endAngle - startAngle)*drawValue;
int clockwise = 0;
if(isTargetFiller) {
if(drawValue < 0.0)
clockwise = 1;
startAngle = 270;
endAngle = 405;
endAngle = startAngle + (endAngle - startAngle)*drawValue;
}
CGPoint center = CGPointMake(75, 75);
CGContextMoveToPoint(context, center.x, center.y);
CGContextAddArc(context, center.x, center.y, startRadius, DEG_2_RAD(startAngle),
DEG_2_RAD(endAngle), clockwise);
CGContextClosePath(context);
CGContextClip(context);
UIImage *bigImage = [UIImage imageNamed:#"CTracker_Full.png"];
CGPoint topLeftOffset = CGPointMake(
(self.bounds.size.width - bigImage.size.width) / 2,
(self.bounds.size.height - bigImage.size.height) / 2);
[bigImage drawAtPoint: topLeftOffset blendMode:kCGBlendModeNormal alpha:1.0];
CGContextSetBlendMode (context, kCGBlendModeMultiply);
float green = 1.0;
float red = 0.0;
if(value > 0.5) {
green = 1.0 - (value - 0.5) / 0.5;
red = (value - 0.5) / 0.5;
}
UIColor *tintColor = [UIColor colorWithRed:red green:green blue:0.0 alpha:1.0];
CGContextSetFillColor(context, CGColorGetComponents(tintColor.CGColor));
CGContextFillRect(context, rect);
CGContextSetBlendMode(context, kCGBlendModeDestinationIn);
[bigImage drawAtPoint:topLeftOffset blendMode:kCGBlendModeDestinationIn
alpha:1.0];
Here is what it is currently drawing:
As you can see, there is an outline around the actual shape that leads to the center of the image.
Figured it out myself right after posting this. Hopefully this will help someone else.
Changed the last little bit of code to:
UIColor *tintColor = [UIColor colorWithRed:red green:green blue:0.0 alpha:1.0];
CGContextSetFillColor(context, CGColorGetComponents(tintColor.CGColor));
CGContextFillRect(context, rect);
CGContextRestoreGState(context);
CGContextSaveGState(context);
CGContextSetBlendMode(context, kCGBlendModeDestinationIn);
[bigImage drawAtPoint:topLeftOffset blendMode:kCGBlendModeDestinationIn alpha:1.0];

Memory issues with Core Graphics

I draw a table "by hand", by using primitives of Core Graphics.
The view is re-draw when I click a button.
The problem is that when I profile the code in Instruments, the VM Regions keep increase, while Heap and Anonymous VM oscillate (and I would expect it).
And the details about CoreAnimation:
An excerpt of my drawRect:
- (void)drawRect:(CGRect)rect
{
// Drawing code
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect paperRect = CGRectMake(self.bounds.origin.x+hourLabelSize+self.marginX,
10 +self.cellBorder ,
self.bounds.size.width,
self.cellHeight * 48
);
// custom shadow
drawLinearGradient(context, paperRect, whiteColor.CGColor, lightGrayColor.CGColor);
CGContextSaveGState(context);
CGFloat outerMargin = 5.0f;
CGFloat eventSize;
// Draw table
CGRect hourRect;
CGRect outerRect;
CGMutablePathRef outerPath;
CGRect strokeRect;
CGRect rowRect;
for (int j=0; j < 7;j++)
{
for (int i=0; i < numberOfRows; i++)
{
// Odd index means we are in the half of an hour
if ( (i%2) == 0)
{
[hour setString:[NSString stringWithFormat:#"%d:00",(int)floor(i/2)]];
// Draw box around hours //
if (j == 0 && i >0)
{
CGContextSaveGState(context);
hourRect = CGRectMake(5, i*cellHeight-5, hourLabelSize, 28);
outerRect = CGRectInset(hourRect, outerMargin, outerMargin);
outerPath = newRoundedRectForRect(outerRect, 6.0);
CGContextAddPath(context, outerPath);
CFRelease(outerPath); // <--- This solve the leak!!
// Draw gradient
strokeRect = CGRectInset(hourRect, 5.0, 5.0);
CGContextSetStrokeColorWithColor(context, boxColor.CGColor);
CGContextSetLineWidth(context, 1.0);
CGContextStrokeRect(context, strokeRect);
drawLinearGradient(context, strokeRect, whiteColor.CGColor, lightGrayColor.CGColor);
CGContextRestoreGState(context);
}
}
else
{
[hour setString:[NSString stringWithFormat:#"%d:30",(int)floor(i/2)]];
}
// Draw hours
if (j == 0 && i > 0)
[hour drawInRect:CGRectMake(0, i*cellHeight, hourLabelSize+10, 26) withFont:font lineBreakMode:NSLineBreakByClipping alignment:NSTextAlignmentCenter];
// Draw row
CGContextBeginPath(context);
CGContextSetStrokeColorWithColor(context, boxColor.CGColor);
CGContextSetLineWidth(context, self.cellBorder);
rowRect = CGRectMake(j*cellWidth + hourLabelSize +self. marginX - self.cellBorder/2, i*cellHeight+10 + self.cellBorder / 2, cellWidth , cellHeight);
CGContextStrokeRect(context, rowRect);
} //
CGContextFlush(context);
CGContextRestoreGState(context);
The first thing I do not understand is why I see VM:CoreAnimation. CoreGraphics is part of Core Animation?
Secondly, what I shall watch as syntoms of bad allocation: VM Regions, XCode measurements or Head and Anonymous?
Regards!
[EDIT]
The createRoundedRect is as follows
CGMutablePathRef newRoundedRectForRect(CGRect rect, CGFloat radius)
{
CGMutablePathRef path = CGPathCreateMutable();
CGPathMoveToPoint(path, NULL, CGRectGetMidX(rect), CGRectGetMinY(rect));
CGPathAddArcToPoint(path, NULL, CGRectGetMaxX(rect), CGRectGetMinY(rect), CGRectGetMaxX(rect), CGRectGetMaxY(rect), radius);
CGPathAddArcToPoint(path, NULL, CGRectGetMaxX(rect), CGRectGetMaxY(rect), CGRectGetMinX(rect), CGRectGetMaxY(rect), radius);
CGPathAddArcToPoint(path, NULL, CGRectGetMinX(rect), CGRectGetMaxY(rect), CGRectGetMinX(rect), CGRectGetMinY(rect), radius);
CGPathAddArcToPoint(path, NULL, CGRectGetMinX(rect), CGRectGetMinY(rect), CGRectGetMaxX(rect), CGRectGetMinY(rect), radius);
CGPathCloseSubpath(path);
return path;
}:
and the drawLineGradient.m :
void drawLinearGradient(CGContextRef context, CGRect rect, CGColorRef startColor, CGColorRef endColor)
{
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGFloat locations[] = { 0.0, 1.0 };
NSArray *colors = #[(__bridge id) startColor, (__bridge id) endColor];
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef) colors, locations);
CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));
CGContextSaveGState(context);
CGContextAddRect(context, rect);
CGContextClip(context);
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
CGContextRestoreGState(context);
CGGradientRelease(gradient);
CGColorSpaceRelease(colorSpace);
colors = nil;
}
The reason you see core animation is because all iOS views are layer-backed views.
The reason for your leak is that you release the path.
ARC does not manage Core Foundation objects.

How to remove corners for round rect bezier path

I am programming first time using Core Graphics, so don't have much idea that how exactly can I solve the problem.
I am drawing rounded rect bezier path along with gradient and stroke as background view for UITableviewCells. Everything has gone fine, except the extra black corners as shown in figure.
I haven't got any idea why they are showing and exactly what they are. Please can anyone help me? Thanks..
Code for creating cell
#import "CustomCellBackground.h"
.
.
.
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
cell.backgroundView = [[CustomCellBackground alloc] init];
cell.selectedBackgroundView = [[CustomCellBackground alloc]init];
}
// Configure the cell.
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.textLabel.textColor = [UIColor whiteColor];
cell.textLabel.backgroundColor = [UIColor clearColor];
return cell;
}
In CustomCellBackground.m
- (void)drawRect:(CGRect)rect
{
// Drawing code
CGContextRef context = UIGraphicsGetCurrentContext();
CGPathRef path = [[UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:10.0] CGPath];
CGContextAddPath(context, path);
CGContextClip(context);
//CGContextSetLineJoin(context, kCGLineJoinRound);
drawLinearGradientWithFourColors(context, self.bounds);
CGContextSaveGState(context);
CGContextSetStrokeColorWithColor(context,[UIColor whiteColor].CGColor);
CGContextSetLineWidth(context, 1.0);
CGContextAddPath(context, path);
CGContextStrokePath(context);
CGContextRestoreGState(context);
}
void drawLinearGradientWithFourColors(CGContextRef context, CGRect rect)
{
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGFloat locations[] = {0.0, 0.2, 0.5, 1.0};
CGFloat colors[16] = {
85/255.0, 85/255.0, 85/255.0, 1.0,
45/255.0, 45/255.0, 45/255.0, 1.0,
22/255.0, 22/255.0, 22/255.0, 1.0,
0, 0, 0, 1.0
};
CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, colors, locations, 4);
CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));
CGContextSaveGState(context);
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
CGContextRestoreGState(context);
CGGradientRelease(gradient);
CGColorSpaceRelease(colorSpace);
}
When you init your view , setOpaque parameter for layer of the view and view.
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setOpaque:NO];
[self.layer setOpaque:NO];
}
return self;
}
I googled it and pasted the code below. For more info refer link:
Use below code:
typedef enum {
CustomCellBackgroundViewPositionTop,
CustomCellBackgroundViewPositionMiddle,
CustomCellBackgroundViewPositionBottom,
CustomCellBackgroundViewPositionSingle
} CustomCellBackgroundViewPosition;
#interface CustomCellBackgroundView : UIView {
UIColor *borderColor;
UIColor *fillColor;
CustomCellBackgroundViewPosition position;
}
#property(nonatomic, retain) UIColor *borderColor, *fillColor;
#property(nonatomic) CustomCellBackgroundViewPosition position;
#end
- (void)drawRect:(CGRect)rect {
// Drawing code
CGContextRef c = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(c, [fillColor CGColor]);
CGContextSetStrokeColorWithColor(c, [borderColor CGColor]);
if (position == CustomCellBackgroundViewPositionTop) {
CGContextFillRect(c, CGRectMake(0.0f, rect.size.height - 10.0f, rect.size.width, 10.0f));
CGContextBeginPath(c);
CGContextMoveToPoint(c, 0.0f, rect.size.height - 10.0f);
CGContextAddLineToPoint(c, 0.0f, rect.size.height);
CGContextAddLineToPoint(c, rect.size.width, rect.size.height);
CGContextAddLineToPoint(c, rect.size.width, rect.size.height - 10.0f);
CGContextStrokePath(c);
CGContextClipToRect(c, CGRectMake(0.0f, 0.0f, rect.size.width, rect.size.height - 10.0f));
} else if (position == CustomCellBackgroundViewPositionBottom) {
CGContextFillRect(c, CGRectMake(0.0f, 0.0f, rect.size.width, 10.0f));
CGContextBeginPath(c);
CGContextMoveToPoint(c, 0.0f, 10.0f);
CGContextAddLineToPoint(c, 0.0f, 0.0f);
CGContextStrokePath(c);
CGContextBeginPath(c);
CGContextMoveToPoint(c, rect.size.width, 0.0f);
CGContextAddLineToPoint(c, rect.size.width, 10.0f);
CGContextStrokePath(c);
CGContextClipToRect(c, CGRectMake(0.0f, 10.0f, rect.size.width, rect.size.height));
} else if (position == CustomCellBackgroundViewPositionMiddle) {
CGContextFillRect(c, rect);
CGContextBeginPath(c);
CGContextMoveToPoint(c, 0.0f, 0.0f);
CGContextAddLineToPoint(c, 0.0f, rect.size.height);
CGContextAddLineToPoint(c, rect.size.width, rect.size.height);
CGContextAddLineToPoint(c, rect.size.width, 0.0f);
CGContextStrokePath(c);
return; // no need to bother drawing rounded corners, so we return
}
// At this point the clip rect is set to only draw the appropriate
// corners, so we fill and stroke a rounded rect taking the entire rect
CGContextBeginPath(c);
addRoundedRectToPath(c, rect, 10.0f, 10.0f);
CGContextFillPath(c);
CGContextSetLineWidth(c, 1);
CGContextBeginPath(c);
addRoundedRectToPath(c, rect, 10.0f, 10.0f);
CGContextStrokePath(c);
}
static void addRoundedRectToPath(CGContextRef context, CGRect rect,
float ovalWidth,float ovalHeight)
{
float fw, fh;
if (ovalWidth == 0 || ovalHeight == 0) {// 1
CGContextAddRect(context, rect);
return;
}
CGContextSaveGState(context);// 2
CGContextTranslateCTM (context, CGRectGetMinX(rect),// 3
CGRectGetMinY(rect));
CGContextScaleCTM (context, ovalWidth, ovalHeight);// 4
fw = CGRectGetWidth (rect) / ovalWidth;// 5
fh = CGRectGetHeight (rect) / ovalHeight;// 6
CGContextMoveToPoint(context, fw, fh/2); // 7
CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1);// 8
CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1);// 9
CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1);// 10
CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1); // 11
CGContextClosePath(context);// 12
CGContextRestoreGState(context);// 13
}

Recreate selected UITabBarItem border

I want to recreate a tab bar but I stumbled on this problem. As you can see in the images below my current (right image) selected tab bar item is a lot less crisp or sharper than the one from the UITabBar. Notice the small 1 point border around the icon in the left (which I don't know how to do) as well as the gradient inside the icon which is a lot noticeable in mine. I already thought of Core Graphics and Core Images Filters as possible approaches but can't seem to get that effect. I found an older thread which is part of what I want but the answer doesn't seem to work for me and requires a manual loop through the pixels of the image (which I don't know if it is to be desired). Can someone help me?
This is the code I'm currently using which, btw, you're welcome to correct some mistakes if you see any because I'm starting with Core Graphics:
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGContextSaveGState(context);
{
/* Adjust for different coordinate systems from UIKit and Core Graphics and center the image */
CGContextTranslateCTM(context, self.bounds.size.width/2.0 - self.image.size.width/2.0, self.bounds.size.height - self.bounds.size.height/2.0 + self.image.size.height/2.0);
CGContextScaleCTM(context, 1.0f, -1.0f);
CGRect rect = CGRectMake(0, 0, self.image.size.width, self.image.size.height);
/* Add a drop shadow */
UIColor *dropShadowColor = [UIColor colorWithRed:0.0f green:0.0f blue:0.0f alpha:0.8f];
CGContextSetShadowWithColor(context, CGSizeMake(0, 1), 5, dropShadowColor.CGColor);
/* Draw the original image */
CGContextDrawImage(context, rect, self.image.CGImage);
/* Clip to the original image, so that we only draw the shadows on the
inside of the image but nothing outside. */
CGContextClipToMask(context, rect, self.image.CGImage);
if(self.isSelected){
/* draw background image */
CGImageRef background = [UIImage imageNamed:#"UITabBarBlueGradient"].CGImage;
CGContextDrawImage(context, rect, background);
}
else{
/* draw background color to unselected items */
CGColorRef backgroundColor = [UIColor colorWithRed:95/255.0 green:95/255.0 blue:95/255.0 alpha:1].CGColor;
CGContextSetFillColorWithColor(context, backgroundColor);
CGContextFillRect(context, rect);
/* location of the gradient's colors */
CGFloat locations[] = { 0.0, 1.0 };
NSArray *colors = [NSArray arrayWithObjects:(id)[UIColor colorWithRed:1 green:1 blue:1 alpha:0].CGColor, (id)[UIColor colorWithRed:1 green:1 blue:1 alpha:0.6].CGColor, nil];
/* create the gradient with colors and locations */
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace,(__bridge CFArrayRef) colors, locations);
{
/* start and end points of the gradient */
CGPoint startPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMinY(rect));
CGPoint endPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMaxY(rect));
/* draw gradient */
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);
}
CGGradientRelease(gradient);
}
}
CGContextRestoreGState(context);
CGColorSpaceRelease(colorSpace);
}
I'm working on this too, an optimization you can probably make is instead of rendering the UIImage each time drawrect is called you can save off the UIImage objects in an ivar and just update a UIImageView.image property to display them.
I'm generating my image with the "shine" like this:
(plus_icon.png is a 30 x 30 image with a 4 px wide cross occupying the entire thing in black on a transparent background: which renders like in imageView 2 and 4 like this:
-(UIImage *)tabBarImage{
UIGraphicsBeginImageContext(CGSizeMake(60, 60));
UIImage *image = [UIImage imageNamed:#"plus_icon"];
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(ctx, [[UIColor clearColor] CGColor]);
CGContextFillRect(ctx, CGRectMake(0, 0, 60, 60));
CGRect imageRect = CGRectMake(15, 15, 30, 30);
CGContextDrawImage(ctx, imageRect, [image CGImage]);
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
-(UIImage *)sourceImage{
UIGraphicsBeginImageContext(CGSizeMake(60.0, 60.0));
CGContextRef context = UIGraphicsGetCurrentContext();
size_t num_locations = 2;
CGFloat locations[2] = { 0.3, 1.0 };
CGFloat components[8] = {NC(72), NC(122), NC(229), 1.0, NC(110), NC(202), NC(255), 1.0 };
CGColorSpaceRef cspace;
CGGradientRef gradient;
cspace = CGColorSpaceCreateDeviceRGB();
gradient = CGGradientCreateWithColorComponents (cspace, components, locations, num_locations);
CGPoint sPoint = CGPointMake(0.0, 15.0);
CGPoint ePoint = CGPointMake(0.0, 45.0);
CGContextDrawLinearGradient (context, gradient, sPoint, ePoint, kCGGradientDrawsBeforeStartLocation| kCGGradientDrawsAfterEndLocation);
CGGradientRelease(gradient);
CGColorSpaceRelease(cspace);
[self addShineToContext:context];
UIImage * image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
-(void)addShineToContext:(CGContextRef) context{
CGContextSaveGState(context);
size_t num_locations = 2;
CGFloat locations[2] = { 0.3, 0.7};
CGFloat components[8] = {1.0, 1.0, 1.0, 0.8, 1.0, 1.0, 1.0, 0.0};//{0.82, 0.82, 0.82, 0.4, 0.92, 0.92, 0.92, .8 };
CGColorSpaceRef cspace;
CGGradientRef gradient;
cspace = CGColorSpaceCreateDeviceRGB();
gradient = CGGradientCreateWithColorComponents (cspace, components, locations, num_locations);
CGPoint sPoint = CGPointMake(25.0f, 15.0);
CGPoint ePoint = CGPointMake(35.0f, 44.0f);
[self addShineClip:context];
CGContextDrawLinearGradient(context, gradient, sPoint, ePoint, kCGGradientDrawsBeforeStartLocation);
// CGContextSetFillColorWithColor(context, [[UIColor redColor] CGColor]);
// CGContextFillRect(context, CGRectMake(15,15, 30, 30));
CGColorSpaceRelease(cspace);
CGGradientRelease(gradient);
CGContextRestoreGState(context);
}
-(void)addShineClip:(CGContextRef)context{
CGContextMoveToPoint(context, 15, 35);
CGContextAddQuadCurveToPoint(context, 25, 30, 45, 28);
CGContextAddLineToPoint(context, 45, 15);
CGContextAddLineToPoint(context, 15, 15);
CGContextClosePath(context);
CGContextClip(context);
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.imageView1.image = [self compositeOverSlate:[self drawTabBarOverSourceWithBlend:kCGBlendModeSourceIn]];
self.imageView2.image = [self compositeOverSlate:[self drawTabBarOverSourceWithBlend:kCGBlendModeDestinationIn]];
self.imageView3.image = [self compositeOverSlate:[self drawTabBarOverSourceWithBlend:kCGBlendModeSourceAtop]];
self.imageView4.image = [self compositeOverSlate:[self drawTabBarOverSourceWithBlend:kCGBlendModeDestinationAtop]];
}
-(UIImage *)compositeOverSlate:(UIImage *)image{
UIGraphicsBeginImageContext(image.size);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGRect imageRect = CGRectMake(0, 0, 0, 0);
imageRect.size = image.size;
CGContextSetFillColorWithColor(ctx, [[UIColor darkGrayColor] CGColor]);
CGContextFillRect(ctx, imageRect);
CGContextSetShadow(ctx, CGSizeMake(-1.0, 2.0), .5);
CGContextDrawImage(ctx, imageRect, [image CGImage]);
UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return result;
}
-(UIImage *)drawTabBarOverSourceWithBlend:(CGBlendMode)blendMode{
UIGraphicsBeginImageContext(CGSizeMake(60,60));
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextDrawImage(ctx, CGRectMake(0, 0, 60.0, 60.0), [[self sourceImage] CGImage]);
CGContextSetBlendMode(ctx, blendMode);
CGContextDrawImage(ctx, CGRectMake(0, 0, 60.0, 60.0), [[self tabBarImage] CGImage]);
UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return result;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
but I don't have the border outline cracked yet, but will update if I do crack it.

Striped Lines appear out of nowhere

I am trying to code a routine that would allow me to create a UIImage that is a rectangle filled with stripes on a gradient background.
My code is below and works fine for most of the cases I tried it out. Interestingly, and this is the hook, it doesn't work when I pass it 21 as height and 5 as stripedWidth.
Once I do this, the stripes appear as they should... horizontally.. but vertically they start at like (y=) -40 and end at about (y=) 4 or so. To see this better, each this image showing the effect in question:
Has anyone any idea why this is happening, or even better, what I can do against it?
-(UIImage*) stripedTextureWithStartingColor:(UIColor*) startColor withEndingColor:(UIColor*) endColor withHeight:(NSUInteger) height withStripeWidth:(NSUInteger) stripeWidth withStripeColor:(UIColor*) stripedColor {
CGSize size = CGSizeMake(2 * stripeWidth, height);
UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
#try {
CGContextSetAllowsAntialiasing(context, true);
CGContextSetShouldAntialias(context, true);
NSArray* colors = [NSArray arrayWithObjects:(id) startColor.CGColor, (id) endColor.CGColor, nil];
CGFloat locations[2];
locations[0] = 0.0;
locations[1] = 1.0;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef) colors, locations);
CGColorSpaceRelease(colorSpace);
CGContextDrawLinearGradient(context, gradient, CGPointZero, CGPointMake(0, size.height - 1), 0);
CGGradientRelease(gradient);
CGContextFillPath(context);
int lineWidth = (int) stripeWidth;
CGContextSetLineWidth(context, lineWidth / 2);
int lineCount = (float) size.height / (float) lineWidth;
lineCount -= 2;
for (int i=0; i<lineCount; i++) {
CGContextSetStrokeColorWithColor(context, stripedColor.CGColor);
float x1 = -size.height + i * 2 * lineWidth - lineWidth;
float y1 = size.height - 1 + lineWidth;
float x2 = -size.height + i * 2 * lineWidth + size.height - lineWidth;
float y2 = -lineWidth;
CGContextMoveToPoint(context, x1, y1);
CGContextAddLineToPoint(context, x2, y2);
CGContextStrokePath(context);
}
UIColor* lineTopColor = [[UIColor whiteColor] colorWithAlphaComponent:0.9];
UIColor* lineBottomColor = [[UIColor darkGrayColor] colorWithAlphaComponent:0.5];
CGContextSetStrokeColorWithColor(context, lineTopColor.CGColor);
CGContextMoveToPoint(context, 0, 0);
CGContextAddLineToPoint(context, size.width + 1, 0);
CGContextStrokePath(context);
CGContextSetStrokeColorWithColor(context, lineBottomColor.CGColor);
CGContextMoveToPoint(context, 0, size.height - 1);
CGContextAddLineToPoint(context, size.width + 1, size.height - 1);
CGContextStrokePath(context);
}
#finally {
CGContextRestoreGState(context);
}
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
Found it, my algorithm was slightly incorrect with the starting of the lines

Resources