Zoom effect in a UIView image - ios

When user hovers over the image,tapping on certain body part presents the magnified image of that area. I wanted to know any possible third party frameworks that address such kind of feature or code snippets(like using which gesturerecognizers) that can help me attain this feature.
Question 2: Also I have to add a dynamic clickable Label at the point where the touch happens and ends (as you can see the wrist label in image) so that I can take the user to a separate view from this screen on clicking the label. How to make this possible?

In your drawRect method, mask off a circle (using a monochrome bitmap containing the 'mask' of your magnifying glass) and draw your subject view in there with a 2x scale transform. Then draw a magnifying glass image over that and you're done.
- (void) drawRect: (CGRect) rect {
CGContextRef context = UIGraphicsGetCurrentContext();
CGRect bounds = self.bounds;
CGImageRef mask = [UIImage imageNamed: #"loupeMask"].CGImage;
UIImage *glass = [UIImage imageNamed: #"loupeImage"];
CGContextSaveGState(context);
CGContextClipToMask(context, bounds, mask);
CGContextFillRect(context, bounds);
CGContextScaleCTM(context, 2.0, 2.0);
//draw your subject view here
CGContextRestoreGState(context);
[glass drawInRect: bounds];
}
Check this link for complete example.

Related

How to get the correctly region to crop an UIImage?

I have a UIImageView in my objective c application. On this UIImageView I load a picture then take this from camera. I apply a region to crop the UIImage. This region is a rectangle by CAShapeLayer. But my problem is that when I get the frame contained in rectangle, this isn't of the same position where is my rectangle... I'm getting a wrong region then crop.
I use this code:
CAShapeLayer *_outline = [CAShapeLayer new];
UIImageView *vistaImagen;
...
UIGraphicsBeginImageContextWithOptions(_vistaImagen.frame.size, NO, 0.0);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextAddPath(context, _boundingBox.accessibilityPath.CGPath);
CGContextClip(context);
[_vistaImagen.layer renderInContext:context];
UIImage *iii = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
What could be the problem, if I have the frame of my layer to crop added: _boundingBox.accessibilityPath.CGPath ??
Thanks!!
Well, After spending a few hours, I have found the problem. I was creating the UIGraphicsBeginImageContextWithOptions with a bad scale...
I need use scale to 1 because I'm getting the image in UIImage in real scale, but I had the scale initialized to 0.
UIImageView *vistaImagen;
UIGraphicsBeginImageContextWithOptions(_vistaImagen.frame.size, NO, 1.0);

How to improve performance in rendering image?

I am drawing image on a custom UIView. On resizing the view, the drawing performance goes down and it starts lagging.
My image drawing code is below:
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
UIBezierPath *bpath = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(0, 0, width, height)];
CGContextAddPath(context, bpath.CGPath);
CGContextClip(context);
CGContextDrawImage(context, [self bounds], image.CGImage);
}
Is this approach correct?
You would be better using Instruments to find where the bottleneck is than asking on here.
However, what you will probably find is that every time the frame changes slightly the entire view will be redrawn.
If you're just using the drawRect to clip the view into an oval (I guess there's an image behind it or something) then you would be better off using a CAShapeLayer.
Create a CAShapeLayer and give it a CGPath then add it as a clipping layer to the view.layer.
Then you can change the path on the CAShapeLayer and it will update. You'll find (I think) that it performs much better too.
If your height and width are the same, you could just use a UIImageView instead of needing a custom view, and get the circular clipping by setting properties on the image view's layer. That approach draws nice and quickly.
Just set up a UIImageView (called "image" in my example) and then have your view controller do this once:
image.layer.cornerRadius = image.size.width / 2.0;
image.layer.masksToBounds = YES;

Scaling an image is slow on an iPad 4th gen, are there faster alternatives?

I'm trying to zoom and translate an image on the screen.
here's my drawRect:
- (void)drawRect:(CGRect)rect
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
CGContextSetShouldAntialias(context, NO);
CGContextScaleCTM (context, senderScale, senderScale);
[self.image drawAtPoint:CGPointMake(imgposx, imgposy)];
CGContextRestoreGState(context);
}
When senderScale is 1.0, moving the image (imgposx/imgposy) is very smooth. But if senderScale has any other value, performance takes a big hit and the image stutters when I move it.
The image I am drawing is a UIImageobject. I create it with
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0.0);
and draw a simple UIBezierPath(stroke):
self.image = UIGraphicsGetImageFromCurrentImageContext();
Am I doing something wrong? Turning off the anti-aliasing did not improve things much.
Edit:
I tried this:
rectImage = CGRectMake(0, 0, self.frame.size.width * senderScale, self.frame.size.height * senderScale);
[image drawInRect:rectImage];
but it was just as slow as the other method.
If you want this to perform well, you should let the GPU do the heavy lifting by using CoreAnimation instead of drawing the image in your -drawRect: method. Try creating a view and doing:
myView.layer.contents = self.image.CGImage;
Then zoom and translate it by manipulating the UIView relative to its superview. If you draw the image in -drawRect: you're making it do the hard work of blitting the image for every frame. Doing it via CoreAnimation only blits once, and then subsequently lets the GPU zoom and translate the layer.

How to smooth edges of drawn image?

I'm using this code to colorize some images of a UIButton subclass:
UIImage *img = [self imageForState:controlState];
// begin a new image context, to draw our colored image onto
UIGraphicsBeginImageContextWithOptions(img.size, NO, 0.0f);
// get a reference to that context we created
CGContextRef context = UIGraphicsGetCurrentContext();
// set the fill color
[self.buttonColor setFill];
CGContextSetAllowsAntialiasing(context, true);
CGContextSetShouldAntialias(context, true);
// 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 multiply, and the original image
CGContextSetBlendMode(context, kCGBlendModeScreen);
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 the colored image
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 colored image
[self setImage:coloredImg forState:controlState];
But the images come out with rough edges. I've tried using screen, lighten, and plusLighter blend modes, because some of the images have white parts that I want to stay white. The only part I want colorized is the black areas. I've attached the original button images, and after they've been colorized. I can't get the edges to look good. When I had them as white images that were colorized using multiply blend mode, it looked much better. But I want to use black so I can use one method for colorizing images with and without white in them. I tried with anti-aliasing, that didn't help either. It looks like it just isn't anti-aliasing it. I haven't worked with Core Graphics enough to know what's up with it.
EDIT
Here's what the original PNGs look like:
and here's what it should look like:
and here's what it does look like:
The size if different, but you can see the bad quality around the edges.
Maybe your original icons (PNGs?) are just "too sharp"? Could you show us? You just draw the image at its original size without resizing, so the problem could be right from the start.
I'm not sure what is what you are trying to accomplish here. Are you trying to round the edges of the images? If so, you are better of by changing the round corner property of the UIButton's layer. Since UIButton is a subclass of UIView, you can get its layer property and change the edge color and round its corner.

image manipulation using quartz2d

CGSize cgs = CGSizeMake(250.0, 300.0);
UIGraphicsBeginImageContext(cgs);
CGRect rectangle = CGRectMake(0,0,cgs.width,cgs.height);
UIImage *myImage = [UIImage imageNamed:#"BMW.jpg"];
[myImage drawInRect:rectangle];
[myImage release];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetLineWidth(context, 5.0);
CGContextSetRGBStrokeColor(context, 0.0, 0.0, 1.0, 1.0);
CGContextStrokeRect(context, rectangle);
UIImage *testImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[testImg drawAtPoint:CGPointMake(35, 10)];
i want to give gap between image and rectangle borders in which image is drawn, like 5 on left 5 on top and 5 on right but around 30 on bottom because its the space for text that user will write and user can also select that he/she want text on top so in that case top gap will be 30 and bottom gap will be 5. Here is the code it is inside subclass of uiview in drawrect method.
using this code border and image are tightly bound together, i am unable to give gap between border and image. Any idea how can i do that?
Thanks in advance.
First of all, you have a serious bug. This line is wrong:
[myImage release];
You don't own myImage, so you should not release it. You need to read “Memory-Management Rules” in Cocoa Core Competencies. Or you should turn on ARC (automatic reference counting), and then the compiler will take care of releasing things for you. Since ARC is supported since iOS 4.0, you should almost certainly be using it if you're developing a new app.
Regarding your image drawing, you just need to modify the rectangle in which you're drawing the image. For example, you can leave a 5 pixel border on top, left, and right, and a 30 point border on the bottom like this:
CGRect imageRect = CGRectInset(rectangle, 5, 5); // move 5 points in on all sides
imageRect.size.height -= 25; // make it another 25 points shorter
[myImage drawInRect:imageRect];
If you want the 30 point border on top, you also need to modify imageRect.origin.y.

Resources