I need to draw over an image graffiti style, as below. My problem is that I need to have the capability to erase the lines I've drawn without erasing sections of the UIImage. At the moment I'm considering using one image for the background image and another image, with a transparent background, for the graffiti drawing, then combining the two once the drawing is complete. Is there a better way?
- (void)drawRect:(CGRect)rect
{
//Get drawing context
CGContextRef context = UIGraphicsGetCurrentContext();
//Create drawing layer if required
if(drawingLayer == nil)
{
drawingLayer = CGLayerCreateWithContext(context, bounds.size, NULL);
CGContextRef layerContext = CGLayerGetContext(drawingLayer);
CGContextScaleCTM(layerContext, scale, scale);
self.viewRect = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.width);
NSLog(#"%f %f",self.viewRect.size.width,self.viewRect.size.width);
}
//Draw paths from array
int arrayCount = [pathArray count];
for(int i = 0; i < arrayCount; i++)
{
path = [pathArray objectAtIndex:i];
UIBezierPath *bezierPath = path.bezierPath;
CGContextRef layerContext = CGLayerGetContext(drawingLayer);
CGContextAddPath(layerContext, bezierPath.CGPath);
CGContextSetLineWidth(layerContext, path.width);
CGContextSetStrokeColorWithColor(layerContext, path.color.CGColor);
CGContextSetLineCap(layerContext, kCGLineCapRound);
if(activeColor == 4)
{
CGContextSetBlendMode(layerContext, kCGBlendModeClear);
}
else
{
CGContextSetBlendMode(layerContext, kCGBlendModeNormal);
}
CGContextStrokePath(layerContext);
}
if (loadedImage == NO)
{
loadedImage = YES;
CGContextRef layerContext = CGLayerGetContext(drawingLayer);
CGContextSaveGState(layerContext);
UIGraphicsBeginImageContext (self.viewRect.size);
CGContextTranslateCTM(layerContext, 0, self.viewRect.size.height);
CGContextScaleCTM(layerContext, 1.0, -1.0);
CGContextDrawImage(layerContext, self.viewRect, self.image.CGImage);
UIGraphicsEndImageContext();
CGContextRestoreGState(layerContext);
}
[pathArray removeAllObjects];
CGContextDrawLayerInRect(context, self.viewRect, drawingLayer);
}
Related
I am working with a drawing app where I draw inside CGlayers and then draw on grahics context, but I drawing is getting blurred.
Here is my code
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();//Get a reference to current context(The context to draw)
NSLog(#"Size1%#", NSStringFromCGRect(self.bounds));
if(self.currentDrawingLayer == nil)
{
self.currentDrawingLayer = CGLayerCreateWithContext(context, self.bounds.size, NULL);
}
CGPoint mid1 = midPoint(m_previousPoint1, m_previousPoint2);
CGPoint mid2 = midPoint(m_currentPoint, m_previousPoint1);
CGContextRef layerContext = CGLayerGetContext(self.currentDrawingLayer);
// UIGraphicsBeginImageContextWithOptions(self.bounds.size,YES,0.0);
CGContextSetLineCap(layerContext, kCGLineCapRound);
CGContextSetBlendMode(layerContext, kCGBlendModeNormal);
CGContextSetLineJoin(layerContext, kCGLineJoinRound);
CGContextSetLineWidth(layerContext, self.lineWidth);
CGContextSetStrokeColorWithColor(layerContext, self.lineColor.CGColor);
CGContextSetShouldAntialias(layerContext, YES);
CGContextSetAllowsAntialiasing(layerContext, YES);
CGContextSetAlpha(layerContext, self.lineAlpha);
CGContextSetFlatness(layerContext, 1.0f);
CGContextBeginPath(layerContext);
CGContextMoveToPoint(layerContext, mid1.x, mid1.y);//Position the current point
CGContextAddQuadCurveToPoint(layerContext, m_previousPoint1.x, m_previousPoint1.y, mid2.x, mid2.y);
CGContextStrokePath(layerContext);//paints(fills) the line along the current path.
CGContextDrawLayerInRect(context, self.bounds, self.currentDrawingLayer);
}
I get blurr strokes with this code, according to docs, whenever we create the CGlayer with graphicsContext, they say that it will provide the resolution of the device, but then why I am getting blur lines.
Here is the image of blur lines
Regards
Ranjit
Substitute this in your code where you create your CGLayer:
if(self.currentDrawingLayer == nil)
{
CGFloat scale = self.contentScaleFactor;
CGRect bounds = CGRectMake(0, 0, self.bounds.size.width * scale, self.bounds.size.height * scale);
CGLayerRef layer = CGLayerCreateWithContext(context, bounds.size, NULL);
CGContextRef layerContext = CGLayerGetContext(layer);
CGContextScaleCTM(layerContext, scale, scale);
self.currentDrawingLayer = layer;
}
I am using the below code to draw a UIImage. I am using some vertices to draw, in this case, a square :
- (UIImage *)drawTexture : (NSArray *)verticesPassed {
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
CGContextRef con = CGBitmapContextCreate(NULL,
1000,
1000,
8,
0,
rgbColorSpace,
kCGImageAlphaPremultipliedFirst);
CGColorSpaceRelease(rgbColorSpace);
CGContextSetLineWidth(con, 10);
Line * start = [verticesPassed objectAtIndex:0];
StandPoint * startPoint = start.origin;
CGContextMoveToPoint(con, [startPoint.x floatValue], [startPoint.y floatValue]);
for (Line * vertice in verticesPassed) {
StandPoint * origin = vertice.origin;
CGContextAddLineToPoint(con, [origin.x floatValue], [origin.y floatValue]);
NSLog(#"Texutre point is %f %f", [origin.x floatValue], [origin.y floatValue]);
}
CGContextSetFillColorWithColor(con, [UIColor greenColor].CGColor);
CGContextFillPath(con);
[self drawText:con startX:250 startY:200 withText:standName];
[self drawText:con startX:250 startY:150 withText:standNumber];
CGImageRef cgImage = CGBitmapContextCreateImage(con);
UIImage *newImage = [[UIImage alloc]initWithCGImage:cgImage];
NSLog(#"Size is %f", newImage.size.height);
return newImage;
}
The vertices for my square are :
Texutre point is 667.000000 379.000000
Texutre point is 731.000000 379.000000
Texutre point is 731.000000 424.000000
Texutre point is 667.000000 424.000000
The problem is that in a 1000x1000 context this obviously draws a very small shape in the top right of the context.
As I want to use this UIImage as a texture, my question is how can I create a shape of the correct size without any whitespace (i.e it starts at 0,0) ?
Code from Bugivore :
- (UIImage *)drawTexture : (NSArray *)verticesPassed {
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
//This function gets the bounds or smallest rectangle required to generate a shape which
//will be used as pattern
CGRect shp = [self boundFromFrame:verticesPassed];
//Generate the shape as image so that we can make pattern out of it.
CGContextRef conPattern = CGBitmapContextCreate(NULL,
shp.size.width,
shp.size.height,
8,
0,
rgbColorSpace,
(CGBitmapInfo)kCGImageAlphaPremultipliedFirst);
CGColorSpaceRelease(rgbColorSpace);
CGContextSetLineWidth(conPattern, 10);
CGContextSetStrokeColorWithColor(conPattern, [UIColor blueColor].CGColor);
Line * start = [verticesPassed objectAtIndex:0];
StandPoint * startPoint = start.origin;
CGContextMoveToPoint(conPattern, [startPoint.x floatValue]-shp.origin.x , [startPoint.y floatValue]-shp.origin.y);
for (Line * vertice in verticesPassed) {
StandPoint * standPoint = vertice.origin;
CGContextAddLineToPoint(conPattern, [standPoint.x floatValue]-shp.origin.x, [standPoint.y floatValue]-shp.origin.y);
}
CGContextStrokePath(conPattern);
//Make the main image and color it with pattern.
CGImageRef cgImage = CGBitmapContextCreateImage(conPattern);
UIImage *imgPattern = [[UIImage alloc]initWithCGImage:cgImage];
//UIImageWriteToSavedPhotosAlbum(imgPattern, nil, nil, nil);
UIColor *patternColor = [UIColor colorWithPatternImage:imgPattern];
CGContextRef con = CGBitmapContextCreate(NULL,
500,
500,
8,
0,
rgbColorSpace,
(CGBitmapInfo)kCGImageAlphaPremultipliedFirst);
CGColorSpaceRelease(rgbColorSpace);
CGContextSetLineWidth(con, 10);
CGContextMoveToPoint(con, 0 , 0);
CGContextAddLineToPoint(con, 500 , 0 );
CGContextAddLineToPoint(con, 500, 500 );
CGContextAddLineToPoint(con, 0 , 500);
CGContextSetFillColorWithColor(con, patternColor.CGColor);
CGContextFillPath(con);
CGImageRef cgImageFinal = CGBitmapContextCreateImage(con);
UIImage *newImage = [[UIImage alloc]initWithCGImage:cgImageFinal];
UIImageWriteToSavedPhotosAlbum(newImage, nil, nil, nil);
return newImage;
}
-(CGRect)boundFromFrame:(NSArray*)verticesPassed
{
float top,left,right,bottom;
bool bFirst = YES;
for (Line * vertice in verticesPassed) {
StandPoint * standPoint = vertice.origin;
if(bFirst)
{
left = right = [standPoint.x floatValue];
top = bottom = [standPoint.y floatValue];
bFirst = NO;
}
else{
if ([standPoint.x floatValue]<left) left = [standPoint.x floatValue];
if ([standPoint.x floatValue]>right) right = [standPoint.x floatValue];
if ([standPoint.x floatValue]<top) top = [standPoint.y floatValue];
if ([standPoint.x floatValue]>bottom) bottom = [standPoint.y floatValue];
}
}
return CGRectMake(left, top, right - left, bottom-top);
}
In photo album :
Note that I have modified your code a bit to test it. But this takes array coordinates and draws a shape based on line coordinates. The uses that shape to draw pattern over 1000x1000 image. Final image is saved in your photo album so that you can test out the code.. You can replace it with return of UIImage as per your original code.. However this primarily shows you the technique how you can use the drawing to create texture.
- (void)drawTexture : (NSArray *)verticesPassed {
CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
//This function gets the bounds or smallest rectangle required to generate a shape which
//will be used as pattern
CGRect shp = [self boundFromFrame:verticesPassed];
//Generate the shape as image so that we can make pattern out of it.
CGContextRef conPattern = CGBitmapContextCreate(NULL,
shp.size.width,
shp.size.height,
8,
0,
rgbColorSpace,
kCGImageAlphaPremultipliedFirst);
CGColorSpaceRelease(rgbColorSpace);
CGContextSetLineWidth(conPattern, 10);
CGContextSetStrokeColorWithColor(conPattern, [UIColor blueColor].CGColor);
Line * start = [verticesPassed objectAtIndex:0];
CGContextMoveToPoint(conPattern, start.x-shp.origin.x , start.y-shp.origin.y);
for (Line * vertice in verticesPassed) {
CGContextAddLineToPoint(conPattern, vertice.x-shp.origin.x , vertice.y-shp.origin.y );
}
CGContextStrokePath(conPattern);
//Make the main image and color it with pattern.
CGImageRef cgImage = CGBitmapContextCreateImage(conPattern);
UIImage *imgPattern = [[UIImage alloc]initWithCGImage:cgImage];
//UIImageWriteToSavedPhotosAlbum(imgPattern, nil, nil, nil);
UIColor *patternColor = [UIColor colorWithPatternImage:imgPattern];
CGContextRef con = CGBitmapContextCreate(NULL,
1000,
1000,
8,
0,
rgbColorSpace,
kCGImageAlphaPremultipliedFirst);
CGColorSpaceRelease(rgbColorSpace);
CGContextSetLineWidth(con, 10);
CGContextMoveToPoint(con, 0 , 0);
CGContextAddLineToPoint(con, 1000 , 0 );
CGContextAddLineToPoint(con, 1000 , 1000 );
CGContextAddLineToPoint(con, 0 , 10000 );
CGContextSetFillColorWithColor(con, patternColor.CGColor);
CGContextFillPath(con);
CGImageRef cgImageFinal = CGBitmapContextCreateImage(con);
UIImage *newImage = [[UIImage alloc]initWithCGImage:cgImageFinal];
UIImageWriteToSavedPhotosAlbum(newImage, nil, nil, nil);
}
-(CGRect)boundFromFrame:(NSArray*)verticesPassed
{
float top,left,right,bottom;
bool bFirst = YES;
for (Line * vertice in verticesPassed) {
if(bFirst)
{
left = right = vertice.x;
top = bottom = vertice.y;
bFirst = NO;
}
else{
if (vertice.x<left) left = vertice.x;
if (vertice.x>right) right = vertice.x;
if (vertice.x<top) top = vertice.y;
if (vertice.x>bottom) bottom = vertice.y;
}
}
return CGRectMake(left, top, right - left, bottom-top);
}
I have an UILabel subclass that draws some text in drawinRect method using a pattern image. This pattern image is a gradient image I am creating.
-(void)drawRect:(CGRect)rect
{
UIColor *color = [UIColor colorWithPatternImage:[self gradientImage]];
[color set];
[someText drawInRect:rec withFont:font lineBreakMode:UILineBreakModeWordWrap alignment:someAlignment];
}
The gradient image method is
-(UIImage *)gradientImage
{
NSData *colorData = [[NSUserDefaults standardUserDefaults] objectForKey:#"myColor"];
UIColor *co = [NSKeyedUnarchiver unarchiveObjectWithData:colorData];
colors = [NSArray arrayWithObjects:co,co,[UIColor whiteColor],co,co,co,co,nil];
NSArray *gradientColors=colors;
CGFloat width;
CGFloat height;
CGSize textSize = [someText sizeWithFont:font];
width=textSize.width; height=textSize.height;
UIGraphicsBeginImageContext(CGSizeMake(width, height));
// get context
CGContextRef context = UIGraphicsGetCurrentContext();
// push context to make it current (need to do this manually because we are not drawing in a UIView)
UIGraphicsPushContext(context);
//draw gradient
CGGradientRef gradient;
CGColorSpaceRef rgbColorspace;
//set uniform distribution of color locations
size_t num_locations = [gradientColors count];
CGFloat locations[num_locations];
for (int k=0; k<num_locations; k++)
{
locations[k] = k / (CGFloat)(num_locations - 1); //we need the locations to start at 0.0 and end at 1.0, equaly filling the domain
}
//create c array from color array
CGFloat components[num_locations * 4];
for (int i=0; i<num_locations; i++)
{
UIColor *color = [gradientColors objectAtIndex:i];
NSAssert(color.canProvideRGBComponents, #"Color components could not be extracted from StyleLabel gradient colors.");
components[4*i+0] = color.red;
components[4*i+1] = color.green;
components[4*i+2] = color.blue;
components[4*i+3] = color.alpha;
}
rgbColorspace = CGColorSpaceCreateDeviceRGB();
gradient = CGGradientCreateWithColorComponents(rgbColorspace, components, locations, num_locations);
CGRect currentBounds = self.bounds;
CGPoint topCenter = CGPointMake(CGRectGetMidX(currentBounds), 0.0f);
CGPoint midCenter = CGPointMake(CGRectGetMidX(currentBounds), CGRectGetMidY(currentBounds));
CGContextDrawLinearGradient(context, gradient, topCenter, midCenter, 0);
CGGradientRelease(gradient);
CGColorSpaceRelease(rgbColorspace);
// pop context
UIGraphicsPopContext();
// get a UIImage from the image context
UIImage *gradientImage = UIGraphicsGetImageFromCurrentImageContext();
// clean up drawing environment
UIGraphicsEndImageContext();
return gradientImage;
}
Everything is working fine. The text is drawn with nice glossy effect. Now my problem is if I change the x or y position of the text inside the UILabel and then call the
[someText drawinRect:rec]... to redraw, the gloss effect is generated differently. It seems that the pattern image is changing with change of text position..
The following is the effect for the frame rec = CGRectMake(0, 10, self.frame.size.width, self.frame.size.height);
The following is the effect for the frame rec = CGRectMake(0, 40, self.frame.size.width, self.frame.size.height);
I hope I have explained my question well. Could not find any exact answer elsewhere. Thanks in advance.
You might want to look at using an existing 3rd party solution like FXLabel.
I'm trying to make infinite drawing in custom UIView from another thread using Core Graphics. It's impossible to obtain current CGContext so I try to create a new one. But I have no idea how to apply it to the view.
Here is the code I use in my custom view:
CG_INLINE CGContextRef CGContextCreate(CGSize size)
{
CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB();
CGContextRef ctx = CGBitmapContextCreate(nil, size.width, size.height, 8, size.width * (CGColorSpaceGetNumberOfComponents(space) + 1), space, kCGImageAlphaPremultipliedLast);
CGColorSpaceRelease(space);
return ctx;
}
- (void)drawRect:(CGRect)rect
{
CGContextRef context = CGContextCreate(self.bounds.size);
if(context)
{
[self.layer renderInContext:context];
[self drawSymbolsInContext:context];
CGContextRelease(context);
}
}
- (void)drawSymbolsInContext:(CGContextRef)context
{
for (int x = 0; x<[cellsArray count];x++)
{
for(int y=0; y<[[cellsArray objectAtIndex:x] count]; y++)
{
NSLog(#"lol %d", y);
float white[] = {1.0, 1.0, 1.0, 1.0};
CGContextSetFillColor(context, white);
CGContextFillRect(context, [self bounds]);
CGContextSetTextDrawingMode(context, kCGTextStroke);
CGContextSetRGBFillColor(context, 1.0, 0.0, 0.0, 1.0);
CGContextSelectFont(context, "Times", 12.0, kCGEncodingMacRoman);
CGAffineTransform xform = CGAffineTransformMake(
1.0, 0.0,
0.0, -1.0,
0.0, 0.0);
CGContextSetTextMatrix(context, xform);
CGContextShowTextAtPoint(context, 100.0, 100.0 + 15*y, "test", strlen("test"));
}
}
}
Here is code I use to run thead(in ViewController):
- (void)viewDidLoad
{
[super viewDidLoad];
[NSThread detachNewThreadSelector:#selector(SomeAction:) toTarget:self withObject:self.view];
}
- (void) SomeAction:(id)anObject
{
NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
DrawView *drawView = (DrawView *)anObject;
while (1)
{
COLOR col;
col.blue = 100;
col.red = 100;
col.green = 200;
int cellX = 0;
int cellY = [[rowsArray objectAtIndex:0] count];
CELL cel;
cel.x = cellX;
cel.x = cellY;
SymbolAlive *s = [[SymbolAlive alloc] initWithColor:col andFrame:cel];
[[rowsArray objectAtIndex:0] addObject:s];
[drawView drawRect:drawView.bounds];
[NSThread sleepForTimeInterval: 0.1];
}
[NSThread exit];
[autoreleasepool release];
}
Loop runs correctly. But nothing is displayed on the screen.
Any ideas?
I'm guessing you have to do your drawing on the main thread. Instead of
[drawView drawRect:drawView.bounds];
Do this
[self performSelectorOnMainThread:#selector(doDraw:) withObject:nil waitUntilDone:NO];
and then create a draw function like
- (void)doDraw:(id)notused
{
[drawView drawRect:drawView.bounds];
}
That will allow you to do the processing in the background but do the drawing on the main thread.
Also, you should be using the standard graphics context in this case.
One more comment, you can probably also move all your drawing-into-the-context into the background thread, but then call renderInContext on the main thread.
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.