I would like to take an image and duplicate it. Then increase it by 105% and overlay it on the original image.
What is the correct way to do this on iOS?
This is your basic code for drawing the image and then saving it as an image again:
- (UIImage *)renderImage:(UIImage *)image atSize:(CGSize)size
{
UIGraphicsBeginImageContext(size);
[image drawInRect:CGRectMake(0.0, 0.0, size.width, size.height)];
// draw anything else into the context
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
Where it says "draw anything else into the context" you can draw the image at a reduced size by setting the appropriate rect to draw in. Then, call the renderImage method with whatever size you want the full image to be. You can use CGContextSetAlpha to set the transparency.
Related
I am trying to take a screenshot of my UIImageView and a UILabel that is on top of that.
What I have so far grabs the UIImage in the ImageView and then renders the overlay on it but the positioning of the UILabel is all wrong. I am setting the size of the capture to the actual image size(which isn't what i want).
I just want to be able to take a screenshot exactly how it appears on the screen.
CGSize imageSize = self.imageFromOtherView.size;
// define the size and grab a UIImage from it
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0);
[self.imageFromOtherView drawInRect:CGRectMake(0, 0, imageSize.width, imageSize.height)];
[self.socialLabel.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *capturedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Create a UIView to hold both the UIImageView and UILabel. Then pass this container view through this code. I have my view as a property called viewForPhoto so when the code is called it only captures that view. You can tweak it so that it receives a view. This will return the UIImage that you want.
- (UIImage *)imageByRenderingView
{
UIGraphicsBeginImageContextWithOptions(self.viewForPhotoView.bounds.size, NO, 0.0);
[self.viewForPhotoView.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resultingImage;
}
Add both those views to a common container view, and then call - (BOOL)drawViewHierarchyInRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates on the view to render it in a context.
I have a UIView whose layer has two sublayers, each of which has a 1.5 pixel border around the outside. I am trying to create a UIImage from this view with the following code
UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 0.0f);
[self drawViewHierarchyInRect:self.bounds afterScreenUpdates:NO];
UIImage * image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
The code does return a UIImage, but the image is clipped – that is, the image doesn't include the all of the borders on the sublayers. I've tried tweaking the sizes/bounds but to no effect. Any suggestions of what else I might try?
Thanks!
What happens if you send the parent layer a
drawInContext: message instead of telling the view to draw itself?
I've been struggling with this method for a while. I am drawing an avatar on top of another image. The user picture I want to be a circle, however I can't seem to figure out how. The user picture is a UIImage and not a UIImageView. I am aware of how to make a circle if it is an imageview. Below is the code. There might be a better approach.
-(UIImage *)drawImage:(UIImage*)pinImage withBadge:(UIImage *)user{
UIGraphicsBeginImageContextWithOptions(pinImage.size, NO, 0.0f);
[pinImage drawInRect:CGRectMake(0, 0, pinImage.size.width, pinImage.size.height)];
[user drawInRect:CGRectMake(20.0, 10.0, user.size.width/2, user.size.height/2)];
UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resultImage;
}
The result is good, but the user image is still square, it is not circle. I have tried making the add the User image to a UIImageView, transform it to a circle, and then use it in the method by calling yourImageView.image, but no luck. I also tried numerous other ways. My logic is more than likely incorrect.
The desired outcome is a rounded image place on top of a pin/annotation. Where the black dot would be an image (a bigger circle than this).
You can clip the image context to the path of an image
// Start the image context
UIGraphicsBeginImageContextWithOptions(pinImage.size, NO, 0.0);
UIImage *resultImage = nil;
// Get the graphics context
CGContextRef context = UIGraphicsGetCurrentContext();
// Draw the first image
[pinImage drawInRect:CGRectMake(0, 0, pinImage.size.width, pinImage.size.height)];
// Get the frame of the second image
CGRect rect = CGRectMake(20.0, 10.0, user.size.width/2, user.size.height/2)
// Add the path of an ellipse to the context
// If the rect is a square the shape will be a circle
CGContextAddEllipseInRect(context, rect);
// Clip the context to that path
CGContextClip(context);
// Do the second image which will be clipped to that circle
[user drawInRect:rect];
// Get the result
UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext();
// End the image context
UIGraphicsEndImageContext();
Create a circular path and then clip to that?
CGContextAddArc(ctx, ....);
CGContextClip(ctx);
The images that goes through here are PNGs of different shapes with a transparent background. In addition to merging them (which works fine), I'd like to give the new image a couple of pixels thick outline. But I can't seem to manage that.
(So just to clarify, I'm after an outline around the actual shapes in the context, not a rectangle around the entire image.)
+ (UIImage *)mergeBackgroundImage:(UIImage *)backgroundImage withOverlayingImage:(UIImage *)overlayImage{
UIGraphicsBeginImageContextWithOptions(backgroundImage.size, NO, backgroundImage.scale);
[backgroundImage drawInRect:CGRectMake(0, 0, backgroundImage.size.width, backgroundImage.size.height)];
[overlayImage drawInRect:CGRectMake(backgroundImage.size.width - overlayImage.size.width, backgroundImage.size.height - overlayImage.size.height, overlayImage.size.width, overlayImage.size.height)];
//Add stroke.
UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return result;
}
Thanks for your time!
Markus
If you make a CALayer who's backing is set to a CGImage of your image, you can then use it as a masking layer for your layer that requires an outline1. And once you've done that, you can render your layer into another context, and then get another UIImage from that.
// edit: Something like what's describe in this answer.
In the photo albums app there's a build in edit -> cropping tool. Is it possible to use that tool in an app instead of writing it on my own? Is it a part of the framework?
No, there is no built-in crop tool. However, it would not be that hard to write such a tool.
You'd need to create a control that let the user drag around an image in a scroll view, and collect the coordinates.
Then you'd create a graphics context and use the UIImage method drawInRect: to draw the image into a rect that's larger than the graphics context. The result would be to draw a cropped portion of the image into the context. Then you'd extract an image from the graphics context and discard the graphics context.
No that is not part of SDK, but you can easily crop images in iOS.
- (UIImage *)resizeImage:(UIImage *)image width:(float)w height:(float)h {
UIImage *croppedImage = image;
CGSize size = CGSizeMake(w, h);
UIGraphicsBeginImageContext(size);
CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height);
[image drawInRect:rect];
croppedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return croppedImage;
}
I created a crop tool that might fit your need. It's not based on a scroll view, but rather letting the user choose a frame around their image.
https://github.com/nicholjs/BFCropInterface