I already tried kCGBlendModeXOR but it turn black after the transparency.
Here my code that i done , but it not what I want.
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.view];
CGPoint lastPoint = [touch locationInView: [UIApplication sharedApplication].keyWindow];
UIGraphicsBeginImageContext(self.view.frame.size);
CGRect rect = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
[imageView_skype.image drawInRect:rect];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, 36.0);
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
CGContextSetAlpha(context,0.10);
CGContextSetBlendMode(context, kCGBlendModeXOR);
CGContextBeginPath(context);
CGContextMoveToPoint(context, lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(context, currentPoint.x, currentPoint.y);
CGContextStrokePath(context);
imageView_skype.image = UIGraphicsGetImageFromCurrentImageContext();
your can use mask to do this
http://developer.apple.com/library/ios/#documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_images/dq_images.html
in your touches moved event draw a mask image only black and white
and mask your original image
Related
Actually i got few samples for drawing image through free hand and i integrated as well in my application.I need additional functionalities such as undo/redo.How can i achieve this?Need help on this..I used following code.
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
mouseSwiped = YES;
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.view];
currentPoint.y -= 20;
UIGraphicsBeginImageContext(self.view.frame.size);
[drawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 10.0);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1.0, 0.0, 0.0, 1.0);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
lastPoint = currentPoint;
mouseMoved++;
if (mouseMoved == 10) {
mouseMoved = 0;
}
}
CGMutablePathRef path;
path = CGPathCreateMutable();
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGPathMoveToPoint(path, NULL, previousPoint.x, previousPoint.y);
CGPathAddLineToPoint(path, NULL, lastPoint.x, lastPoint.y);
CGContextAddPath(context, path);
CGContextSetLineWidth(context, 10.0);
[[UIColor greenColor] setStroke];
CGContextDrawPath(context,kCGPathFillStroke);
}
Now you can perform Undo/Redo by path's index.
You can try storing all paths in an array.
When you draw a new one, add it last and draw it, when you delete - remove the last and redraw all. Keep removed in another array so you can redo actions, clear the redo array when a new path is added to the paths array.
That's the most straight-forward method I can think of.
Not a CoreGraphics expert, I'd really appreciate some help.
I'm trying to create a mask from a path. (See red path in image).
Instead of the red path, I'd like the path to be a mask to an image underneath.
Could really use a hand. Thanks in advance
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
mouseSwiped = YES;
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.view];
currentPoint.y -= 20;
UIGraphicsBeginImageContext(self.view.frame.size);
[drawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 20.0);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1.0, 0.0, 0.0, 1.0);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
lastPoint = currentPoint;
mouseMoved++;
if (mouseMoved == 10) {
mouseMoved = 0;
}
}
Once you have the path created, use CGContextReplacePathWithStrokedPath convert it to a path you can fill to get the same results as stroking the path. Then you can use CGContextClip to set the clipping mask to this path.
The solution I came up with was:
Have UIView image on screen.
Create UIImageView image with [UIColor clearColor] background color
Use CoreGraphics to fill UIImageView with color
Save UIImageView, then in TouchesMoved or UIPanGestureRecognizer, draw savedImage, Stroke Path after setting kCGContentBlendClear, save Image and repeat.
I have successfully implemented touchesMoved and it is drawing line properly now I am facing problem in implementing erase method, please assist me where I am lacking.
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
mouseSwiped = YES;
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.view];
currentPoint.y -= 20;
UIGraphicsBeginImageContext(self.view.frame.size);
[drawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 5.0);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1.0, 0.0, 0.0, 1.0);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
lastPoint = currentPoint;
mouseMoved++;
if (mouseMoved == 10) {
mouseMoved = 0;
}
}
- (void) Erase
{
//NSSet *touches;
//UITouch *touch; //= (NSSet *)[touch anyObject];
CGPoint currentPoint; //= [touch locationInView:self.view];
currentPoint.y += 20;
if(mouseSwiped) {
UIGraphicsBeginImageContext(self.view.frame.size);
[drawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 5.0);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1.0, 0.0, 0.0, 1.0);
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
CGContextFlush(UIGraphicsGetCurrentContext());
drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
mouseMoved--;
}
I have implemented my erases successfully in touches moved but when I tap one so it erases but on mouse over and tap left it stop erasing. Then need to click(tap) again for erasing at new point. So how can I continously erases on touches moved,
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
if (eraseBtnSelected == YES) {
if ([touch tapCount] == 1) {
[self EraseButton];
}
}
}
Don't do any drawing in your event-handling methods. Ever. Use them to edit a list of things to draw, and do all of your drawing in -draw... methods like -drawRect:.
To erase something, just delete it from your list of things to draw, and redraw the view or layer in question.
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1.0, 1.0, 1.0, 1.0);
this line of code works if background colour is white if other then it is a problem
change following line
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1.0, 0.0, 0.0, 1.0);
to
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 1.0, 1.0, 1.0, 1.0);
I am working on a painting application using Quartz 2D for ipad. Now I want to add an eraser option so that user can manually erase portion of his drawn line with touch.I have also background image. Can anyone please help?
yes this is work well in my app ;-)
firstly you add this code in touch began
UITouch *touch = [touches anyObject];
lastPoint = [touch locationInView:imgview];
UIGraphicsBeginImageContext(imgview.frame.size);
[imgview.image drawInRect:CGRectMake(0, 0, imgview.frame.size.width, imgview.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), lineWidth);
CGContextSetStrokeColorWithColor(UIGraphicsGetCurrentContext(), [UIColor colorWithPatternImage:img].CGColor);
CGContextSetFillColorWithColor(UIGraphicsGetCurrentContext(), [UIColor clearColor].CGColor);
CGContextSetShouldAntialias(UIGraphicsGetCurrentContext(), YES);
CGContextBeginPath(UIGraphicsGetCurrentContext());
here img is ur background image then on move touch you simple write the line stroke code that code is this
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:imgview];
NSLog(#"asdasdas");
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
imgview.image = UIGraphicsGetImageFromCurrentImageContext();
lastPoint = currentPoint;
then you see the final result is produce ;-)
if(erase)
{
UITouch *touch = [touches anyObject];
CGPoint currentTouch = [touch locationInView:extraImageVw];
CGFloat brushSize;
if (isEraser)
{
brushSize=25.0;
}
else
{
brushSize=25.0;
}
CGColorRef strokeColor = [UIColor whiteColor].CGColor;
UIGraphicsBeginImageContext(extraImageVw.frame.size);
CGContextRef context = UIGraphicsGetCurrentContext();
[extraImageVw.image drawInRect:CGRectMake(0, 0, extraImageVw.frame.size.width, extraImageVw.frame.size.height)];
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, brushSize);
if (isEraser) {
CGContextSetStrokeColorWithColor(UIGraphicsGetCurrentContext(), [UIColor colorWithPatternImage:[UIImage imageWithContentsOfFile:fullPathToFile]].CGColor);
}
else
{
CGContextSetStrokeColorWithColor(context, strokeColor);
CGContextSetBlendMode(context, kCGBlendModeClear);
}
CGContextSaveGState(UIGraphicsGetCurrentContext());
CGContextBeginPath(context);
CGContextMoveToPoint(context, Lastpoint.x, Lastpoint.y);
CGContextAddLineToPoint(context, currentTouch.x, currentTouch.y);
CGContextStrokePath(context);
extraImageVw.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Lastpoint = [touch locationInView:extraImageVw];
}
I'm basically looking to create something akin to a very simple version of iSteam/iFog alebit for a different purpose. In effect there will be two images, one of the subject matter and the other an image of condensation or some such. The user can then wipe their finger over the screen and it will "cut" that from the top layer to reveal the lower layer. So far I've been able to draw a basic line on the screen using CoreGraphics and strokes but I can't find a way to then use this as an alpha mask for the steam layer.
If anyone could give me advice on what to use or even better some sample code I'd be very grateful as right now I'm pulling my hair out. Here is what I have so far:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
mouseSwiped = YES;
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.view];
UIGraphicsBeginImageContext(self.view.frame.size);
CGRect rect = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
[drawImage.image drawInRect:rect];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, 36.0);
CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
CGContextBeginPath(context);
CGContextMoveToPoint(context, lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(context, currentPoint.x, currentPoint.y);
CGContextStrokePath(context);
drawImage.image = UIGraphicsGetImageFromCurrentImageContext();
}
The method you want to call is CGContextClipToMask. Just draw your "steam" image and then the stroke on another CGImage. Then, clip the steam to the stroke. Something like this:
- (void)somewhereElse{
UIImage *steam = [[UIImage imageNamed:#"steamImage.png"] retain];
steamRef = steam.CGImage;
//...
}
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextDrawImage(context, self.bounds, steamRef); //draw the main image
CGContextClipToMask(context, self.bounds, maskRef); //respect alpha mask
//where maskRef is a GCImage of your stroked path
}