Image based core graphics drawing - iphone

I have to draw many shapes like rectangle, circle, triangle etc.I am drawing them trough core graphics.
It is working fine.
I want to ask suppose I am having an image (square image of say 1024*1024), and now I want my circle to draw as image means like I draw red color circle or other color, so if it is possible to show my image as drawn in the circle, like the image is circle,
My code for normal circle drawing:-
- (void)drawRect:(CGRect)rect{
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(ctx, [ [UIColor colorWithRed:255.0/255.0 green:0.0/255.0 blue:0.0/255.0 alpha:1] CGColor]);
CGContextSetAlpha(ctx, 0.7);
CGContextMoveToPoint(ctx, radius, radius);
CGContextAddArc(ctx, radius,radius, radius, radians(0), radians(360), 0);
CGContextClosePath(ctx);
CGContextFillPath(ctx);
}
I want to draw my image as circle.
Basically I want like we can fill colors in core graphics drawing whether circle, arc, triangle. so is that possible to fill my shape with my image instead of any solid colors.
Is this possible and if yes please suggest me how to achieve this.
Thanks in advance.

try this out for setting color in CGContextSetFillColorWithColor function [[UIColor alloc]initWithPatternImage:[UIImage imageNamed:#"pattern.jpg"]CGColor];

Add a UIView with and rectangular on the image.
In this view, you must draw the hole.
Now i not have the mac and i cannot check, but try to substitute
CGContextSetFillColorWithColor(ctx, [ [UIColor colorWithRed:255.0/255.0 green:0.0/255.0 blue:0.0/255.0 alpha:1] CGColor]);
with
CGContextSetBlendMode(currentContext, kCGBlendModeClear);
let me know

Related

Why is color transparent when attempting to draw a colored circle with drawRect?

I'm trying to draw a simple circle in a UIView. I know I can do it with QuartzCore but I want to use the drawRect method:
- (void)drawRect:(CGRect)rect
{
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextAddEllipseInRect(ctx, rect);
CGContextSetFillColor(ctx, CGColorGetComponents([[UIColor greenColor] CGColor]));
CGContextFillPath(ctx);
}
The codes above don't work when i set the [UIColor whiteColor]. When [UIColor whiteColor] the view would become transparent..
Why does the view become transparent when color is white? How can I draw a circle that's white?
The docs for CGContextSetFillColor state the following for the 2nd parameter:
An array of intensity values describing the color to set. The number of array elements must equal the number of components in the current fill color space, plus an additional component for the alpha value.
The greenColor is from the RGB color space. But whiteColor is not. So you end up passing the wrong number of color components when using whiteColor.
A much easier solution is to replace:
CGContextSetFillColor(ctx, CGColorGetComponents([[UIColor greenColor] CGColor]));
with:
[[UIColor greenColor] set];
or:
[[UIColor whiteColor] set];
Update:
Another option, if you really want to Core Graphics, is:
CGContextSetFillColorWithColor(ctx, [UIColor greenColor].CGColor);
You're having problems because of mismatch of color spaces. The context you're drawing into has an RBGA color space by default, which requires the input of four components (red, blue, green, alpha). But when you create a UIColor with [UIColor whiteColor], this color is created with a Grayscale color space, which gives you only two components (white, alpha). Therefore, inserting values of one color space to a different color space causes unintended consequences.
So you either need to change the colour space of your context with CGContextSetFillColorSpace() to a Grayscale color space...
or you can simply use the easier method CGContextSetFillColorWithColor() which takes in a CGColor of any color space and applies to the context regardless of the CGColor's color space.
- (void) drawRect:(CGRect)rect {
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextAddEllipseInRect(ctx, rect);
CGContextSetFillColorWithColor(ctx, [UIColor whiteColor].CGColor);
CGContextFillPath(ctx);
}

Improper borders in draw rect

I am trying to draw rounded corners on rectangle in drawRect method using bezier path, but somehow the rounded corner is being shown on inner side of rectangle, instead of both inner and outer sides. Code is given below. Also attached herewith is border that is currently being drawn (outer side of border is not rounded)
- (void)drawRect:(CGRect)rect
{
// Drawing code
CGContextRef context=UIGraphicsGetCurrentContext();
//Set gray color to whole context
[[UIColor lightGrayColor] set];
CGContextSetAlpha(context,0.7);
UIRectFill(rect);
// Configure the context colors and line
CGContextSetStrokeColorWithColor(context, [UIColor colorWithRed:131./255. green:148./255. blue:219./255. alpha:1.0].CGColor);
CGContextSetFillColorWithColor(context, [UIColor whiteColor].CGColor);
CGContextSetLineWidth(context, 10.0);
CGSize size=self.bounds.size;
CGFloat radius = 10.0;
CGSize guideSize=CGSizeMake(330, 130);
CGRect guideCoords= CGRectMake(size.width*.5-guideSize.width*.5, size.height*.5-guideSize.height*.5, guideSize.width , guideSize.height);
// Guide drawing
CGContextStrokeRect(context,guideCoords);
// Draw the Text
[kVinGuideMessage drawInRect:CGRectMake(guideCoords.origin.x+kSideMessageMargin, guideCoords.origin.y+guideSize.height+kMarginFromGuide, guideCoords.size.width-2*kSideMessageMargin,40) withFont:[UIFont systemFontOfSize:16.0] lineBreakMode:NSLineBreakByWordWrapping alignment:NSTextAlignmentLeft];
//Get instersection and clear color of inner overlay
CGRect holeRectIntersection = CGRectIntersection(rect,guideCoords);
//----------ADDING ROUNDED CORNERS HERE-----------//
CGPathRef clippath = [UIBezierPath bezierPathWithRoundedRect:guideCoords cornerRadius:radius].CGPath;
CGContextAddPath(context, clippath);
CGContextClip(context);
//------------------------------------------------//
[[UIColor clearColor] setFill];
UIRectFill(holeRectIntersection);
}
The outer corners are being drawn by the CGContextStrokeRect(context,guideCoords); I think. At that point you haven't set a clipping path and your line width is 10 points, so why would the outer corners be rounded? I think you'll have better luck if you set a clipping path (probably not exactly the same clipping path you've got at the bottom) before calling stroke rect on the guideCoords rectangle.

Draw a percentage of a circle

I would like to draw a circle like those in the picture in objective-c :
(source: hostingpics.net)
I just want to draw the blue circle filled with the corresponding percentage starting from the bottom. (NB : the range of the percentage is between 0 and 100) Don't worry about the tick in the center, it's just an imageView added over the circle view.
You could make 2 image views. One would contain your circle with the check mark, and the rest transparent. The other image would be below that, with a light blue rectangle. As the percentage increases, you raise the blue rectangle more and more by modifying it's frame. It would be visible of course through the transparent part of the image on top.
Hope this helps!
// Draw circle of radius r and center X,Y
CGRect r;
r.origin.y = Y-radius;
r.origin.x = X-radius;
r.size.width = 2*radius;
r.size.height 2*radius;
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextAddEllipseInRect(ctx, r);
CGContextSetFillColor(ctx, CGColorGetComponents([[UIColor lightGray] CGColor]));
CGContextFillPath(ctx);
// Draw a blue color filled path. Below is half circle filled with blue color.
CGContextBeginPath(ctx);
CGContextAddArc(ctx, X, Y, r, -M_PI_2, M_PI_2, 1);
CGContextClosePath(ctx); // could be omitted
CGContextSetFillColorWithColor(ctx, [UIColor blueColor].CGColor);
CGContextFillPath(ctx);
Idea is to draw a circle and fill it with light gray color and than draw and close path from arc of the circle (whatever angle is required) and fill it with blue color.
Adding to Levi's suggestion.
You can scale the rect image using CGAffineTransformScale.
e.g:
CGAffineTransform transform = self.rectImageView.transform;
float scale = 0.5;
self.rectImageView.transform = CGAffineTransformScale(transform, 1, scale);
This will scale the image to 50%
to set it back to 100%, just set scale = 2.

How to draw a line with a custom style using Core Graphics?

I'm currently drawing a line using Core Graphics. It's really bare bones and simple.
- (void)drawRect:(CGRect)rect {
CGContextRef c = UIGraphicsGetCurrentContext();
CGFloat red[4] = {1.0f, 0.0f, 0.0f, 1.0f};
CGContextSetStrokeColor(c, red);
CGContextBeginPath(c);
CGContextMoveToPoint(c, 5.0f, 5.0f);
CGContextAddLineToPoint(c, 300.0f, 600.0f);
CGContextSetLineWidth(c, 25);
CGContextSetLineCap(c, kCGLineCapRound);
CGContextStrokePath(c);
}
This works well. Let's say that we wanted to draw a custom style line. Say we wanted to imitate the style of a crayon for example. And that the designer handed your crayon style images: http://imgur.com/a/N40ig
To do accomplish this effect I think I need to do something like this:
Create a special colored versions of crayonImage1-crayonImage4
Every time you add a line to line you use one of the crayonImages
You alternate the crayonImages every time you draw a point.
Step 1 makes sense. I can use the following method:
- (UIImage *)image:(UIImage *)img withColor:(UIColor *)color {
// begin a new image context, to draw our colored image onto
UIGraphicsBeginImageContext(img.size);
// get a reference to that context we created
CGContextRef context = UIGraphicsGetCurrentContext();
// set the fill color
[color setFill];
// translate/flip the graphics context (for transforming from CG* coords to UI* coords
CGContextTranslateCTM(context, 0, img.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
// set the blend mode to color burn, and the original image
CGContextSetBlendMode(context, kCGBlendModeColorBurn);
CGRect rect = CGRectMake(0, 0, img.size.width, img.size.height);
CGContextDrawImage(context, rect, img.CGImage);
// set a mask that matches the shape of the image, then draw (color burn) a colored rectangle
CGContextClipToMask(context, rect, img.CGImage);
CGContextAddRect(context, rect);
CGContextDrawPath(context,kCGPathFill);
// generate a new UIImage from the graphics context we drew onto
UIImage *coloredImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
//return the color-burned image
return coloredImg;
}
I'm unsure how I can complete steps 2 and 3. Is there an API in CoreGraphics for setting an image as the point of line? If so what is it and how can I use it?
Thanks in advance,
-David
Start with the following example: http://www.ifans.com/forums/showthread.php?t=132024
But for brushes, don't draw a line. Simply draw the brush image using CGContextDrawImage.
Basically, you simply draw an image for every touch.

Blending with Quartz 2D

The above is a UITableViewCell containing two UILabels. The cell has a transparent background using [UIColor clearColor] and the background pattern (you may need to look closely to see it) is set on the UITableView using UIColor's initWithPatternImage.
What I'd like to be able to do is blend the text with the background pattern so that the text has the texture coming through. The only thing is I'm not sure of is the best way of achieving this.
I know I can use NSString instead of UILabels and draw the text directly into an image, but can this then be blended with the background even though it's not being drawn in the same drawRect (i.e. the text image would be drawn in a subclass of UITableViewCell where as the background is being drawn by the UITableView instance)?
The other way is to create an image mask from the text, have another image which is already textured (with the top half white and the bottom half dark grey) and then use that to draw the text, as outlined in this Cocoa with Love tutorial.
Whilst I can obviously use the tutorial to achieve the second implementation, I'm more inclined to explore the first as it'd use no external images and may be more efficient.
Your thoughts, links and code examples will be greatly appreciated.
Please Note: Setting a low alpha value on the UILabels does not achieve the desired effect
If you set the labels as non opaque and an alpha value less than 1.0 it should work. These can be set in either Interface Builder or as code like this:
[theIncidentLabel setOpaque:NO];
[theIncidentLabel setAlpha:0.5];
You can even just set the text color to a color with an alpha value less than 1.0.
[theIncidentLabel setTextColor:[UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.5]];
Using these settings I do see the background texture through labels in a project I'm working on. In my project the list UITableView is also transparent, and the background texture comes from an image loaded in a UIImageView behind the UITableView.
This is simple alpha blending. We figured out through a discussion in comments that this is inadequate for your needs. Instead you can use the alpha masking as explained in the tutorial mentioned.
Alternatively, you could forgo alpha masks and just draw the text to a CGImage, then draw that image on your background pattern with a different blend mode, maybe kCGBlendModeScreen. Here's the drawRect method from the above mentioned tutorial rewritten with this technique:
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
// Draw a black background
[[UIColor blackColor] setFill];
CGContextFillRect(context, rect);
// Draw the text upside-down
CGContextSaveGState(context);
CGContextTranslateCTM(context, 0, rect.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
[[UIColor lightGrayColor] setFill];
[text drawInRect:rect withFont:[UIFont fontWithName:#"HelveticaNeue-Bold" size:40.0]];
// Draw it again in a darker color.
[[UIColor darkGrayColor] setFill];
CGContextTranslateCTM(context, 0, 50.0);
[text drawInRect:rect withFont:[UIFont fontWithName:#"HelveticaNeue-Bold" size:40.0]];
CGContextRestoreGState(context);
// Create an text image from what we've drawn so far
CGImageRef textImage = CGBitmapContextCreateImage(context);
// Draw a white background (overwriting the previous work)
[[UIColor whiteColor] setFill];
CGContextFillRect(context, rect);
// Draw the background image
CGContextSaveGState(context);
[[UIImage imageNamed:#"shuttle.jpg"] drawInRect:rect];
// Set the blend mode. Try different options to meet your tastes.
CGContextSetBlendMode(context, kCGBlendModeScreen);
// Draw the text.
CGContextDrawImage(context, rect, textImage);
// Clean up.
CGContextRestoreGState(context);
CGImageRelease(textImage);
}