I have set image's content mode aspect fit.
Now issue is that, when I'm drawing line on image, that time image's content mode set scaletofill and my image stretched. So I want solution for when I'm drawing line on image, image content mode remain same.
U can download myproject from this link.
I'm using following code:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if(self.tempImage.image==nil)
{
return;
}
colorPicker.hidden = YES;
UITouch *touch = [touches anyObject];
lastPoint = [touch locationInView:self.view];
lastPoint.y -= 20;
_pointsArray = [NSMutableArray array];
[_pointsArray addObject:NSStringFromCGPoint(lastPoint)];
UIGraphicsBeginImageContext(self.view.frame.size);
CGContextRef context = UIGraphicsGetCurrentContext();
[self.tempImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, brush);
CGContextSetStrokeColorWithColor(UIGraphicsGetCurrentContext(), self.selectedColor.CGColor);
CGContextMoveToPoint(context, lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(context, lastPoint.x, lastPoint.y);
CGContextStrokePath(context);
self.tempImage.image = UIGraphicsGetImageFromCurrentImageContext();
[self setupExternalScreen];
UIGraphicsEndImageContext();
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
if(self.tempImage.image==nil)
{
return;
}
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.view];
currentPoint.y -= 20;
UIGraphicsBeginImageContext(self.view.frame.size);
[self.tempImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextMoveToPoint(context, lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(context, currentPoint.x, currentPoint.y);
//Now set our brush size and opacity and brush stroke color:
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, brush);
CGContextSetStrokeColorWithColor(UIGraphicsGetCurrentContext(), self.selectedColor.CGColor);
CGContextSetBlendMode(context,kCGBlendModeNormal);
CGContextStrokePath(context);
self.tempImage.image = UIGraphicsGetImageFromCurrentImageContext();
[self.tempImage setAlpha:opacity];
UIGraphicsEndImageContext();
lastPoint = currentPoint;
[self setupExternalScreen];
[self.pointsArray addObject:NSStringFromCGPoint(lastPoint)];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if(self.tempImage.image==nil)
{
return;
}
//handle single tap, make _pointsArray has two identical points, draw a line between them
if (_pointsArray.count == 1) {
[_pointsArray addObject:NSStringFromCGPoint(lastPoint)];
}
[self.stack addObject:_pointsArray];
NSLog(#"color -> %# \nwidth->%f", self.selectedColor.description, brush);
NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
[dic setObject:self.selectedColor forKey:#"color"];
[dic setObject:[NSNumber numberWithFloat:brush] forKey:#"width"];
[self.contextArray addObject:dic];
[self setupExternalScreen];
[self.undoManager registerUndoWithTarget: self
selector: #selector(popDrawing)
object: nil];
}
In this code, view frame set in UIGraphicsBeginImageContext. I think it will possible using subclass of UIImageView. I don't know exact solution.
Please see this Screenshot, u will easily understand my problem
Thanks in advance
Related
In my xcode project, the user draws an object manually. So for example they can draw a apple or triangle.
I need to save I guess the coordinates or the line path of what they draw.
How can I store the line path or re-create the image that the user has drawn. I don't want to save the image, but I want to learn from the image the user drew by knowing the specific line path?
Here is the code
.h
int mouseMoved;
BOOL mouseSwiped;
CGPoint lastPoint;
UIImageView *drawImage;
viewdidload {
drawImage = [[UIImageView alloc] initWithImage:nil];
drawImage.frame = self.view.frame;
[self.view addSubview:drawImage];
self.view.backgroundColor = [UIColor lightGrayColor];
mouseMoved = 0;
}
.m
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
BOOL mouseSwiped = NO;
UITouch *touch = [touches anyObject];
if ([touch tapCount] == 2) {
drawImage.image = nil;
return;
}
lastPoint = [touch locationInView:self.view];
lastPoint.y -= 20;
}
- (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)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
if ([touch tapCount] == 2) {
drawImage.image = nil;
return;
}
_startPoint = [touch locationInView:self.view];
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();
}
}
-(void)digitalSignatureCalled{
//viewSign.backgroundColor = [UIColor lightGrayColor];
//create a frame for our signature capture based on whats remaining
imageFrame = CGRectMake(0, 50, 500, 450);
//allocate an image view and add to the main view
mySignatureImage = [[UIImageView alloc] initWithImage:nil];
mySignatureImage.frame = imageFrame;
mySignatureImage.backgroundColor = [UIColor whiteColor];
[viewSign addSubview:mySignatureImage];
}
//when one or more fingers touch down in a view or window
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
//did our finger moved yet?
fingerMoved = NO;
UITouch *touch = [touches anyObject];
//just clear the image if the user tapped twice on the screen
if ([touch tapCount] == 2) {
mySignatureImage.image = nil;
return;
}
//we need 3 points of contact to make our signature smooth using quadratic bezier curve
currentPoint = [touch locationInView:mySignatureImage];
lastContactPoint1 = [touch previousLocationInView:mySignatureImage];
lastContactPoint2 = [touch previousLocationInView:mySignatureImage];
}
//when one or more fingers associated with an event move within a view or window
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
//well its obvious that our finger moved on the screen
fingerMoved = YES;
UITouch *touch = [touches anyObject];
//save previous contact locations
lastContactPoint2 = lastContactPoint1;
lastContactPoint1 = [touch previousLocationInView:mySignatureImage];
//save current location
currentPoint = [touch locationInView:mySignatureImage];
//find mid points to be used for quadratic bezier curve
CGPoint midPoint1 = [self midPoint:lastContactPoint1 withPoint:lastContactPoint2];
CGPoint midPoint2 = [self midPoint:currentPoint withPoint:lastContactPoint1];
//create a bitmap-based graphics context and makes it the current context
UIGraphicsBeginImageContext(imageFrame.size);
//draw the entire image in the specified rectangle frame
[mySignatureImage.image drawInRect:CGRectMake(0, 0, imageFrame.size.width, imageFrame.size.height)];
//set line cap, width, stroke color and begin path
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 3.0f);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0.0, 0.0, 0.0, 1.0);
CGContextBeginPath(UIGraphicsGetCurrentContext());
//begin a new new subpath at this point
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), midPoint1.x, midPoint1.y);
//create quadratic Bézier curve from the current point using a control point and an end point
CGContextAddQuadCurveToPoint(UIGraphicsGetCurrentContext(),
lastContactPoint1.x, lastContactPoint1.y, midPoint2.x, midPoint2.y);
//set the miter limit for the joins of connected lines in a graphics context
CGContextSetMiterLimit(UIGraphicsGetCurrentContext(), 2.0);
//paint a line along the current path
CGContextStrokePath(UIGraphicsGetCurrentContext());
//set the image based on the contents of the current bitmap-based graphics context
mySignatureImage.image = UIGraphicsGetImageFromCurrentImageContext();
//remove the current bitmap-based graphics context from the top of the stack
UIGraphicsEndImageContext();
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
//just clear the image if the user tapped twice on the screen
if ([touch tapCount] == 2) {
mySignatureImage.image = nil;
return;
}
//if the finger never moved draw a point
if(!fingerMoved) {
UIGraphicsBeginImageContext(imageFrame.size);
[mySignatureImage.image drawInRect:CGRectMake(0, 0, imageFrame.size.width, imageFrame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 3.0f);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), 0.0, 0.0, 0.0, 1.0);
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
CGContextFlush(UIGraphicsGetCurrentContext());
mySignatureImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
}
//calculate midpoint between two points
- (CGPoint) midPoint:(CGPoint )p0 withPoint: (CGPoint) p1 {
return (CGPoint) {
(p0.x + p1.x) / 2.0,
(p0.y + p1.y) / 2.0
};
}
-(void)clickToSave:(id)sender{
//convert image into .png format.
viewNewSign.image = mySignatureImage.image;
if (mySignatureImage.image == nil) {
imgString = #"NoSignature";
}else{
imgString = [self getStringFromImage:mySignatureImage.image];
}
NSLog(#"image saved = %#",imgString);
NSLog(#"image length = %lu",(unsigned long)imgString.length);
viewSign.hidden = TRUE;
scroll.scrollEnabled = YES;
[scroll bringSubviewToFront:viewSign];
}
-(NSString *)getStringFromImage:(UIImage *)image{
if(image){
NSData *dataObj = UIImagePNGRepresentation(image);
//[appDelegate showAlert:#"Data Size" message:[NSString stringWithFormat:#"Data length = %lu",(unsigned long)dataObj.length]];
return [dataObj base64EncodedStringWithOptions:0];
} else {
return #"";
}
}
-(void)clickToClear:(id)sender{
[self digitalSignatureCalled];
}
- (UIImage*)imageWithImage:(UIImage*)image
scaledToSize:(CGSize)newSize;
{
UIGraphicsBeginImageContext( newSize );
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
I am using this raywenderlich tutorial for the drawing on Image. That tutorial is with no image in background but here I want to draw on image from gallery.
So basically there are two UIImageView one is mainImage and tempDrawImage.
I am doing self.mainImage.image = randomImageFromGallery as a background image on which I want to draw
Now it shows up well n drawing also happens but the problem is image gets scale on every touch end.
Why the image keeps on scaling whats wrong with the code I am not doing anything on tempDrawImage where all the drawing happens ?
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
mouseSwiped = NO;
UITouch *touch = [touches anyObject];
lastPoint = [touch locationInView:self.view];
UIGraphicsBeginImageContext(self.view.frame.size);
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
mouseSwiped = YES;
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.view];
CGContextRef ctxt = UIGraphicsGetCurrentContext();
CGContextMoveToPoint(ctxt, lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(ctxt, currentPoint.x, currentPoint.y);
CGContextSetLineCap(ctxt, kCGLineCapRound);
CGContextSetLineWidth(ctxt, brush );
CGContextSetRGBStrokeColor(ctxt, red, green, blue, 1.0);
CGContextSetBlendMode(ctxt,kCGBlendModeNormal);
CGContextStrokePath(ctxt);
self.tempDrawImage.image = UIGraphicsGetImageFromCurrentImageContext();
[self.tempDrawImage setAlpha:opacity];
lastPoint = currentPoint;
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesCancelled:touches withEvent:event];
UIGraphicsEndImageContext();
if(!mouseSwiped)
{
self.tempDrawImage.image = nil;
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if(!mouseSwiped) {
UIGraphicsEndImageContext();
UIGraphicsBeginImageContext(self.view.frame.size);
[self.tempDrawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), brush);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), red, green, blue, opacity);
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
CGContextFlush(UIGraphicsGetCurrentContext());
self.tempDrawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
UIGraphicsBeginImageContext(self.mainImage.frame.size);
[self.mainImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) blendMode:kCGBlendModeNormal alpha:1.0];
[self.tempDrawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) blendMode:kCGBlendModeNormal alpha:opacity];
self.mainImage.image = UIGraphicsGetImageFromCurrentImageContext();
self.tempDrawImage.image = nil;
UIGraphicsEndImageContext();
}
Check the size of the frames of all of the views you're using. Somewhere there is a mismatch so that one of the images your displaying is being scaled for display. Either the size the image is drawn at or the size it's displayed at needs to be changed.
If I understand well, you have a picture, and you want to draw up to this picture...
I propose :
set your tempDrawImage as inherited from UIView instead of UIImageView.
Store the points in an array while touches actions (touchesBegan, touchesMoved,...)
draw in the procedure (void)drawRect:(CGRect)rect
I am following the tutorial to create a simple drawing pad app (http://www.raywenderlich.com/18840/how-to-make-a-simple-drawing-app-with-uikit#comments)
The app has a single UIViewController and a UIImageView in it. After implementing touchBegin, touchMoved, and touchEnd, I could draw but after every stroke ends, the whole picture moves up. So after several strokes, the whole picture will be distorted and squeezed to the very top of the screen. Any suggestions? Thank you very much.
Here is the code:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
self.mouseSwiped = NO;
UITouch *touch = [touches anyObject];
self.lastPoint =[touch locationInView:self.view];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
self.mouseSwiped = YES;
//find out the position where the touch event happened
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.view];
//Setup the drawing context and prepare to draw something
UIGraphicsBeginImageContext(self.view.frame.size);
//Create a drawing area that is of the same size as the view dimensions
[self.mainImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
//Set the drawing starting point
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), self.lastPoint.x, self.lastPoint.y);
//Setup a line from the starting point to specified point, i.e current point in this case
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
//Set the drawing style
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), self.brush);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), self.red, self.green, self.blue, 1);
CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeNormal);
//Paint the line
CGContextStrokePath(UIGraphicsGetCurrentContext());
self.mainImage.image=UIGraphicsGetImageFromCurrentImageContext();
[self.mainImage setAlpha:self.opacity];
UIGraphicsEndImageContext();
self.lastPoint = currentPoint;
}
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
if(!self.mouseSwiped){
UIGraphicsBeginImageContext(self.view.frame.size);
[self.mainImage.image drawInRect:
CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), self.brush);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(),
self.red, self.green, self.blue, self.opacity);
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), self.lastPoint.x, self.lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), self.lastPoint.x, self.lastPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
CGContextFlush(UIGraphicsGetCurrentContext());
self.mainImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
UIGraphicsBeginImageContext(self.mainImage.frame.size);
[self.mainImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height) blendMode:kCGBlendModeNormal alpha:self.opacity];
self.mainImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
You probably have a mismatch between the size of the 2 views you're using, so as you move between the 2 different coordinate spaces you get a scaling effect.
Hi I am currently working on an app that contains taking notes by drawing. I followed ray wenderlich tutorials and as far I've got, I ended up with this code:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
mouseSwiped = NO;
UITouch *touch = [touches anyObject];
lastPoint = [touch locationInView:self];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
CGFloat red,green,blue,alpha;
mouseSwiped = YES;
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self];
UIGraphicsBeginImageContext(self.mainImage.frame.size);
[self.tempDrawImage.image drawInRect:CGRectMake(0, 0, self.mainImage.frame.size.width, self.mainImage.frame.size.height)];
CGContextSetBlendMode(UIGraphicsGetCurrentContext(),[self getBlendMode]);
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x , lastPoint.y );
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x , currentPoint.y );
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), [self getBrushSize] );
[[self getPaintColor] getRed:&red green:&green blue:&blue alpha:&alpha];
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), red, green, blue, 1);
CGContextSetBlendMode(UIGraphicsGetCurrentContext(),[self getBlendMode]);
CGContextStrokePath(UIGraphicsGetCurrentContext());
self.tempDrawImage.image = UIGraphicsGetImageFromCurrentImageContext();
[self.tempDrawImage setAlpha:[self getPaintAlpha]];
UIGraphicsEndImageContext();
lastPoint = currentPoint;
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
CGFloat red,green,blue;
if(!mouseSwiped) {
UIGraphicsBeginImageContext(self.mainImage.frame.size);
[self.tempDrawImage.image drawInRect:CGRectMake(0, 0, self.mainImage.frame.size.width, self.mainImage.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), [self getBrushSize]);
[[self getPaintColor] getRed:&red green:&green blue:&blue alpha:nil];
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), red, green, blue, [self getPaintAlpha]);
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y - self.mainImage.frame.origin.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y - self.mainImage.frame.origin.y );
CGContextStrokePath(UIGraphicsGetCurrentContext());
CGContextFlush(UIGraphicsGetCurrentContext());
self.tempDrawImage.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
UIGraphicsBeginImageContext(self.mainImage.frame.size);
[self.mainImage.image drawInRect:CGRectMake(0, 0, self.mainImage.frame.size.width, self.mainImage.frame.size.height) blendMode:[self getBlendMode] alpha:1.0];
[self.tempDrawImage.image drawInRect:CGRectMake(0, 0, self.mainImage.frame.size.width, self.mainImage.frame.size.height) blendMode:[self getBlendMode] alpha:[self getPaintAlpha]];
if(self.drawMode != DrawEraser)
{
self.mainImage.image = UIGraphicsGetImageFromCurrentImageContext();
self.tempDrawImage.image = nil;
}
UIGraphicsEndImageContext();
mouseSwiped = NO;
}
This code was working just fine with a small frame but when I increased the frame as 2 times bigger than before, unfortunately performance is not so good. So I was thinking about optimizing the code. I especially focused on touchesMoved method. As far as I understand, it draws the whole image on the context and changes it some and assigns the context to image. Drawing whole image seemed to be overload. So I was wondering, if I can draw some parts of the image to the context and do some changes and then draw this part of the context to the image.
you're right - redrawing the whole image every time in touchesMoved is a bad idea. I think you should create and keep a reference to the context at the beginning. In touches moved, you should draw on to that and create an image from the context. You can use CGBitmapContextCreate() to create the context instead of UIGraphicsBeginImageContext() and CGBitmapContextCreateImage() to create an image from the context instead of UIGraphicsGetImageFromCurrentImageContext(). Here is the documentation on how to use those (https://developer.apple.com/library/mac/#documentation/graphicsimaging/reference/CGBitmapContext/Reference/reference.html).
I am using apps like bamboo book and paper, in iPad, the experience is really good, how is it work? which technology does it used when draw lines or curves on screen?
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
mouseSwiped = NO;
UITouch *touch = [touches anyObject];
if ([touch tapCount] == 2) {
//self.imageView.image = nil;
return;
}
lastPoint = [touch locationInView:self.view];
lastPoint.y -= 20;
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
mouseSwiped = YES;
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.view];
currentPoint.y -= 20;
CGFloat components[3];
[self getRGBComponents:components forColor:self.colorView.backgroundColor];
NSLog(#"%f %f %f", components[0], components[1], components[2]);
UIGraphicsBeginImageContext(self.view.frame.size);
[self.imageView.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 10.0);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), components[0], components[1], components[2],5.0);
CGContextBeginPath(UIGraphicsGetCurrentContext());
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), currentPoint.x, currentPoint.y);
CGContextSetBlendMode(UIGraphicsGetCurrentContext(), kCGBlendModeNormal);
CGContextStrokePath(UIGraphicsGetCurrentContext());
self.imageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
lastPoint = currentPoint;
mouseMoved++;
if (mouseMoved == 10) {
mouseMoved = 0;
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
if ([touch tapCount] == 2) {
//self.imageView.image = nil;
return;
}
if(!mouseSwiped) {
CGFloat components[3];
[self getRGBComponents:components forColor:self.colorView.backgroundColor];
NSLog(#"%f %f %f", components[0], components[1], components[2]);
UIGraphicsBeginImageContext(self.view.frame.size);
[self.imageView.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
CGContextSetLineCap(UIGraphicsGetCurrentContext(), kCGLineCapRound);
CGContextSetLineWidth(UIGraphicsGetCurrentContext(), 5.0);
CGContextSetRGBStrokeColor(UIGraphicsGetCurrentContext(), components[0], components[1], components[2], 5.0);
CGContextMoveToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextAddLineToPoint(UIGraphicsGetCurrentContext(), lastPoint.x, lastPoint.y);
CGContextStrokePath(UIGraphicsGetCurrentContext());
CGContextFlush(UIGraphicsGetCurrentContext());
self.imageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
}
Also check following link
http://www.techotopia.com/index.php/An_iOS_4_iPhone_Graphics_Drawing_Tutorial_using_Quartz_2D
https://stackoverflow.com/questions/6449661/drawing-2d-images-on-iphone-tutorials
http://mobile.tutsplus.com/tutorials/iphone/ios-sdk_freehand-drawing/
http://www.raywenderlich.com/18840/how-to-make-a-simple-drawing-app-with-uikit