Calling drawInRect on an UIImageView's image: which rect to use? - objective-c

I'm trying to write a finger paint type program using Quartz graphics. The problem I'm having is when the screen rotates. The dots and lines I draw "creep" away from where I'm touching. With each successive touch, the previous dot creeps away. This does not happen in either of the two portrait modes, but it does in both landscape modes.
I may be mistaken but I think my problem is with this call:
[drawImage.image drawInRect:CGRectMake(0, 0, self.view.frame.size.width , self.view.frame.size.height)];
drawImage is a UIImageView in my main view controller's nib file.
I've also tried using the following:
[drawImage.image drawInRect:CGRectMake(0, 0, drawImage.frame.size.width, drawImage.frame.size.height )];
[drawImage.image drawInRect:drawImage.bounds];
[drawImage.image drawInRect:self.view.bounds];
I guess I really have no idea whether to use self or my UIImageView object for this call.
I have tried both, in both the drawInRect call and where I set up my drawing context (being consistent).
I set up the context like this in viewDidLoad (to try to make a persistant context that I don't have to reset things in each time I draw - using push and pop context).
//---------------- set up a persistent context for drawing -----------------
UIGraphicsBeginImageContext(self.view.frame.size);
context = UIGraphicsGetCurrentContext();
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, curWidth);
CGContextSetRGBStrokeColor(context, curRed, curGreen, curBlue, curAlpha);
UIGraphicsPushContext(context);
I tried to get rid of the context I set up on rotation and reinitialize it when the view rotated, thinking this was the problem, but I'm not sure I did it right.

You shouldn't be drawing that image yourself directly. Even if you set up your own context and draw into it correctly, you've got to somehow get it flushed to the screen. This is why UIKit sets up a context for you before it calls drawRect: on views. It's ready to put things on the screen and it just needs to know what to put there.
You can set up your own image context and draw into it in touchesBegan:, etc., but what you should do then is turn that into an image using UIGraphicsGetImageFromCurrentImageContext, call [myImageView setImage:theImageIJustGot], and then [myImageView setNeedsDisplay]. That signals UIKit that you have new things to put on the screen, and UIKit will take care of the rest.

Related

cocoa - draw image in NSView

I'm having difficulties understanding why the below code doesn't work, what I want to achieve is an image being displayed in the top left corner of a NSView, but nothing is showing...
NSImage *map0 = [NSImage imageNamed:#"map0.png"];
NSRect rect = NSMakeRect(0, 0, 400, 400);
[map0 drawInRect:rect fromRect:NSZeroRect operation:NSCompositeSourceAtop fraction:1.0f];
[map drawRect:rect];
EDIT:
map is the NSView into which I would like to draw the image into
You never call drawRect: directly. This routine has various pre-conditions that are provided by Cocoa, such as the creation of a CGContextRef. You implement drawRect:. Cocoa calls it.
Your drawInRect:fromRect:operation:fraction: call should be put into the drawRect: of map, which should be a subclass of NSView. This specific problem is usually better solved with an NSImageView rather than a custom NSView, but if the drawing is more complex, then a custom NSView is appropriate.

Blending two images and drawing resized image from two UIImageViews

I have two ImageViews, one called imageView and the other called subView (which is a subview of imageView).
I want to blend the images on these views together, with the user being able to switch the alpha of the blend with a pan. My code works, but right now, the code is slow as we are redrawing the image each time the pan gesture is moved. Is there a faster/more efficient way of doing this?
BONUS Q: I want to allow for my subView image to drawn zoomed in. Currently I've set my subView to be UIViewContentModeCenter, however I can't seem to draw a zoomed in part of my image with this content mode. Is there any way around this?
My drawrect:
- (void)drawRect:(CGRect)rect
{
float xCenter = self.center.x - self.currentImage1.size.width/2.0;
float yCenter = self.center.y - self.currentImage1.size.height/2.0;
subView.alpha = self.blendAmount; // Customize the opacity of the top image.
UIGraphicsBeginImageContext(self.currentImage1.size);
CGContextRef c = UIGraphicsGetCurrentContext();
CGContextSetBlendMode(c, kCGBlendModeColorBurn);
[imageView.layer renderInContext:c];
self.blendedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[self.blendedImage drawAtPoint:CGPointMake(xCenter,yCenter)];
}
You need to use GPU for image processing which is far faster than using CPU (as you're doing right now).
You can use Core Image framework which is very fast and easy to use but requires iOS 5, or you can use Open GL directly but you need to be experienced and have some knowledge about Open GL Shading.

NSRect on main screen without window

I was wondering if it is possible to create an NSRect with maybe an NSMakeRect to make a simple square that will display on the screen without a window or any view behind it, just made all in code.
This is what I have as an example
-(void)drawRect
{
NSRect myNewRect
myNewRect = NSMakeRect(100, 100, 50, 50);
}
Thats just a simple starting point but it will not show up on the screen by itself. what do i need to add?
Thanks
Every drawing operation on Mac OS X requires some window of sort. So no, you cannot draw a rect without a window. But you can create a transparent window without any borders to draw into.
First of all, you can't "display on the screen without a window or any view behind it".
You will always be drawing on some layer-backed object (UIView, etc).
And UIViews must eventually be part of some UIWindow hierarchy to display them.
So you can't "[draw] on main screen without window" at all. That's not how Core Graphics works.
However, I believe this is what you're trying to do:
-(void)drawRect
{
CGRect myNewRect = CGRectMake(100, 100, 50, 50);
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(ctx, [[UIColor redColor] CGColor]);
CGContextFillRect(ctx, myNewRect);
}
Which draws a rectangle in the UIView implementing the above drawRect method.

Drawing Transparent Images

I created a custom view to a button, as I need to implement some highlighting when the mouse is over. The class is very simple, and I already implemented mouseEntered: as well as mouseExited:. The view was registered for tracking in the init method (not sure if it's the best place).
The problem is drawing. I keep an ivar mouseOver, set to YES on mouse enter and NO on mouse exited. The other ivar is for the image, called image. The difference between mouse over or not when it comes to drawing, is the transparency. Here is my drawRect::
- (void)drawRect:(NSRect)dirtyRect
{
[image drawAtPoint:NSMakePoint(0.0,0.0)
fromRect:dirtyRect
operation:NSCompositeCopy
fraction:((mouseOver) ? 1.0 : 0.0)];
}
It works nicely, but only when the mouse first entered, apparently. I guess the problem is that the view is not cleared before drawing the other image. I tried adding:
[[NSColor clearColor] set];
NSRectFillUsingOperation(dirtyRect, NSCompositeClear);
But without success. How can I fix this?
[NSColor clearColor] is a purely transparent color. You probably want to fill using a color with some opacity, like, say, [NSColor whiteColor].

How do I MOVE a circle drawn in a subclass of UIView by overwriting the method "drawRect"?

I'm trying to figure out what i'm doing wrong but i just don't get it. Here is what i want to do:
I want to draw a circle somewhere on the screen of the iPhone and then i want the circle always to be displayed at the position where the user currently taps on the screen.
I started by creating a subclass of UIView and adding the following lines into the "drawRect" method:
- (void)drawRect:(CGRect)rect {
//Create the main view!
CGContextRef mainscreen = UIGraphicsGetCurrentContext();
//Draw the dot
//will be a circle cause rectangle is a square
CGRect dotRect = CGRectMake(50, 80, 100, 100);
[[UIColor blueColor] set];
CGContextStrokeEllipseInRect(mainscreen, dotRect);
CGContextFillEllipseInRect(mainscreen, dotRect);
}
The appears just fine but now I have no idea how to make it move around on the screen I've tried several things and nothing worked.
To draw the dot in a different location, change the origin of dotRect. To figure out where to draw it, implement -touchesBegan:withEvent: and -touchesMoved:withEvent: and record the location where the touches are occuring.