This code make changes to the imageview, but it replaces its original image. I need to edit on the original image not to replace it.
- (void)drawShapes {
//NSLog(#"In drawShapes!");
UIGraphicsBeginImageContext(self.planView.frame.size);
CGContextRef context = UIGraphicsGetCurrentContext();
for(myShape *i in _collection) {
[self drawShapesSubroutine:i contextRef:context];
if(i.selected == true) {
CGContextSetLineWidth(context, 1.0f);
CGContextSetStrokeColorWithColor(context, [[UIColor darkGrayColor] CGColor]);
float num[] = {6.0, 6.0};
CGContextSetLineDash(context, 0.0, num, 2);
CGRect rectangle;
[self drawShapeSelector:i selectorRect: &rectangle];
CGContextAddRect(context, rectangle);
CGContextStrokePath(context);
//tapped = true;
}
}
if(!skipDrawingCurrentShape && (selectedIndex == -1)) {
[self drawShapesSubroutine:_currentShape contextRef:context];
}
self.planView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
When I remove this line:
self.planView.image = UIGraphicsGetImageFromCurrentImageContext();
The image doesn't disappear but also doesn't draw. I need to draw without removing the original photo.
You cant do imagview.image because, it will replace the old image with new one. If you are planning to draw something new on the image view, try to add sublayer on the imageview.
convert your image into cgiimage and add it to layer.you should convert UIGraphicsGetImageFromCurrentImageContext() into UIGraphicsGetImageFromCurrentImageContext().CGImage
you need to create a CALayer and add your CGI image to the layer.contents and use that layer as sub layer
CALayer *layer = [CALayer layer];
layer.contents = (id)UIGraphicsGetImageFromCurrentImageContext().CGImage;
and do this:
[self.imageView.layer addSublayer:layer];
Related
I currently have the following image on which I am trying to set a border. It consists of an UIImageView with an image inside (a transparent.png)
When I try to set the border for my image (see code), it gives a border to the UIImage, but it doesn't 'snap' around my image. Is it possible to achieve that effect?
See image current implementation here.
- (UIImage*)imageWithBorderFromImage:(UIImage*)source;
{
CGSize size = [source size];
UIGraphicsBeginImageContext(size);
CGRect rect = CGRectMake(0, 0, size.width, size.height);
[source drawInRect:rect blendMode:kCGBlendModeNormal alpha:1.0];
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetRGBStrokeColor(context, 1.0, 0.5, 1.0, 1.0);
CGContextStrokeRect(context, rect);
UIImage *testImg = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return testImg;
}
Try Adding a layer behind UIImageView and add a border to it that will do the trick
#define kBorderWidth 3.0.
#define kCornerRadius 8.0
CALayer *borderLayer = [CALayer layer];
CGRect borderFrame = CGRectMake(0, 0, (imageView.frame.size.width), (imageView.frame.size.height));
[borderLayer setBackgroundColor:[[UIColor clearColor] CGColor]];
[borderLayer setFrame:borderFrame];
[borderLayer setCornerRadius:kCornerRadius];
[borderLayer setBorderWidth:kBorderWidth];
[borderLayer setBorderColor:[[UIColor redColor] CGColor]];
[imageView.layer addSublayer:borderLayer];
And don't forget to import QuartzCore/QuartzCore.h
This example will draw a boarder on the layer, but change it's frame slightly to make the border around the layer.
Depending on your needs, if you don't want it to be as accurate as possible, a quick and dirty solution could be something like this:
- (UIImage *)borderedImageFromImage:(UIImage *)source andColor:(UIColor *)borderColor{
CGFloat scale = 0.95;//this determines how big the border will be, the smaller it is the bigger the border
UIImage *borderImage = [source imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
UIGraphicsBeginImageContextWithOptions(source.size, NO, source.scale);
[borderColor set];
[borderImage drawInRect:CGRectMake(0, 0, source.size.width, source.size.height)];
[source drawInRect:CGRectMake(source.size.width*(1-scale)/2,
source.size.height*(1-scale)/2,
source.size.width * scale,
source.size.height * scale)];
borderImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return borderImage;
}
and here is how to use it:
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.heartImageView.image = [self borderedImageFromImage:[UIImage imageNamed:#"heart"] andColor:[UIColor blackColor]];
}
What this essentially does is draw the image you want twice, once in the colour of the border (slightly scaled) and once with the normal colour. Your mileage may vary depending on the image.
I am trying to create a custom view to draw a music CD with the album artwork on the CD.
Currently I use core graphics to draw two circular disks inside the drawRect method. The inner disk's colour is set to the background colour of the view to make it look like the inner circle is a hollow circle.
My problem is that I can't draw the UIImage inside the the circular bezier path to get the result that I need.
Here's my drawRect code:
// Draw a CD like view using three drawing operations:
// 1st draw the main disk
// 2nd draw the image if it is set
// 3rd draw the inner disk over the image so that it looks like it is a hollow disk with the image painted on the disk.
// Note:) This view expects its aspect ratio to be set as 1:1
- (void)drawRect:(CGRect)rect
{
// Draw the main Circular CD disk
UIBezierPath* outerRing = [UIBezierPath bezierPathWithOvalInRect:self.bounds];
[self.mainColor setFill];
[outerRing fill];
[self.outerRingColor setStroke];
[outerRing stroke];
// Draw the album image if it is set
if(self.artwork){
[self.artwork drawInRect:self.bounds blendMode:kCGBlendModeNormal alpha:1.0];
}
// now draw another smaller disk inside
// this will be a percentage smaller than the whole disk's bounds and will be centered inside it
CGFloat sidePaddingCoord = ((1.0f - INNER_DISK_SIZE_PERCENTAGE) / 2) * self.bounds.size.height;
CGFloat side = INNER_DISK_SIZE_PERCENTAGE * self.bounds.size.width;
UIBezierPath* innerRing = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(sidePaddingCoord, sidePaddingCoord, side, side)];
[self.innerRingColor setFill];
[innerRing fill];
[innerRing stroke];
}
This fills the image as a square. I want the image to be clipped inside the outerRing bezier path so that it looks like a music CD.
I'm sure there is a way to use core graphics to achieve something else besides using the image's drawInRect method. Is there any way to 'clip' the image inside the circular bezier path or only draw inside the bezier path?
I've read really great posts by rob mayoff, UIBezierPath Subtract Path, iOS UIImage clip to paths, many thanks.
Here is an adoption of his code. Keep your creation code of outerRing and innerRing, add them to an array named paths.
[self.paths addObject:outerRing];
[self.paths addObject:innerRing];
Then use this help method.
- (UIImage *)maskedImage
{
CGRect rect = CGRectZero;
rect.size = self.originalImage.size;
UIGraphicsBeginImageContextWithOptions(rect.size, YES, 0.0);
UIBezierPath *clipPath = [UIBezierPath bezierPathWithRect:CGRectInfinite];
[clipPath appendPath:self.paths[1]];
clipPath.usesEvenOddFillRule = YES;
CGContextSaveGState(UIGraphicsGetCurrentContext()); {
[clipPath addClip];
[[UIColor orangeColor] setFill];
[self.paths[0] fill];
} CGContextRestoreGState(UIGraphicsGetCurrentContext());
UIImage *mask = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
UIGraphicsBeginImageContextWithOptions(rect.size, NO, 0.0); {
CGContextClipToMask(UIGraphicsGetCurrentContext(), rect, mask.CGImage);
[self.originalImage drawAtPoint:CGPointZero];
}
UIImage *maskedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return maskedImage;
}
In drawRect,
UIImage *maskedImage = [self maskedImage];
[maskedImage drawInRect:self.bounds blendMode:kCGBlendModeNormal alpha:1.0];
Try below code:
UIImageView *userImageView= [[UIImageView alloc] initWithFrame:CGRectMake(85, 55.0, 90, 90)];
userImageView.layer.cornerRadius = 90/2;
userImageView.clipsToBounds = YES;
userImageView.layer.borderWidth = 1.0f;
userImageView.layer.borderColor = [UIColor blueColor];
[self.view addSubview:userImageView]; //or add it to the view you want
UIImage *userImage = [UIImage imageNamed:#"<image you want to set>"];
userImageView= [[UIImageView alloc] initWithFrame:CGRectMake(90, 60.0, 80, 80)];
userImageView.image = userImage;
userImageView.layer.cornerRadius = 80/2;
userImageView.clipsToBounds = YES;
userImageView.layer.borderWidth = 1.0f;
userImageView.layer.borderColor = [UIColor blueColor;
[self.view addSubview:userImageView]; //or add it to the view you want
I want to crop a part of an uiimageview that on my view controller. I'm creating a rectangle on top of it:
UIGraphicsBeginImageContext(self.view.bounds.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextMoveToPoint(context, newPoint1.x, newPoint1.y);
CGContextAddLineToPoint(context, newPoint1.x, newPoint2.y);
CGContextAddLineToPoint(context, newPoint2.x, newPoint2.y);
CGContextAddLineToPoint(context, newPoint2.x, newPoint1.y);
CGContextAddLineToPoint(context, newPoint1.x, newPoint1.y);
CGContextClosePath(context);
UIColor *blue = [UIColor colorWithRed: (0.0/255.0 ) green: (0.0/255.0) blue: (255.0/255.0) alpha:0.4];
CGContextSetFillColorWithColor(context, blue.CGColor);
CGContextDrawPath(context, kCGPathFillStroke);
I can't figure out how to crop it right. I'm able to retrieve a capture of the screen : entirely blank with my rectangle on it:
UIImage *cropImage = UIGraphicsGetImageFromCurrentImageContext();
rectImage = cropImage;
UIGraphicsEndImageContext();
UIImageCrop *rectImageView = [[UIImageCrop alloc]initWithImage:rectImage];
[self.view addSubview:rectImageView];
So I'm aware that there is something I've missed about it, any help?
- (UIImage *)captureScreenInRect:(CGRect)captureFrame
{
CALayer *layer;
layer = self.view.layer;
UIGraphicsBeginImageContext(self.view.frame.size);
CGContextClipToRect (UIGraphicsGetCurrentContext(),captureFrame);
[layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *screenImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return screenImage;
}
this is just for reference change this code according to your requirement
hope this will help you
You can get cropped image using :
- (UIImage*) getCroppedImage {
CGRect rect = PASS_YOUR_RECT;
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
// translated rectangle for drawing sub image
CGRect drawRect = CGRectMake(-rect.origin.x, -rect.origin.y, your_image.size.width, your_image.size.height);
// clip to the bounds of the image context
// not strictly necessary as it will get clipped anyway?
CGContextClipToRect(context, CGRectMake(0, 0, rect.size.width, rect.size.height));
// draw image
[your_image drawInRect:drawRect];
// grab image
UIImage* croppedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return croppedImage;
}
Hope it helps you.
i am working on a project in which i have to cropped image and save cropped image in photo library. I have got success in cropping image but problem is that when i cropped image and show it ,it is stretched .i am also using aspect fit mode. But still its stretched.Here is the code
-(void)cropLassoArea {
isLassoSelected = NO;
lassoStyle = 0;
CGRect frame;
frame = mainImageView.frame;
mainImageView.frame.size = CroppedImage.size;
for (int i = 0; i < [lassoArray count]; i++) {
CAShapeLayer *layer = [lassoArray objectAtIndex:i];
CGPathRef myPath = layer.path;
UIGraphicsBeginImageContext(mainImageView.frame.size);
[mainImageView setContentMode:UIViewContentModeCenter];
[mainImageView.image drawInRect:CGRectMake(0, 0,CroppedImage.size.width,CroppedImage.size.height)];
context = UIGraphicsGetCurrentContext();
CGContextBeginPath(context);
CGContextAddPath(context, myPath);
CGContextSetStrokeColorWithColor(UIGraphicsGetCurrentContext(), [UIColor whiteColor].CGColor);
CGContextSetBlendMode(context, kCGBlendModeClear);
CGContextDrawPath(context, kCGPathFill);
CGContextEOFillPath(context);
mainImageView.image = UIGraphicsGetImageFromCurrentImageContext();
CGContextSaveGState(context);
UIGraphicsEndImageContext();
}
}
I would suggest you to download files from this location and I suggest you to go through their tutorial. Its easy and it won't stretch your image at all. I have used these files in one of my working project. You just need to import their header file and call following lines
UIImage *tmpImage = [yourImageView.image resizedImage:CGSizeMake(desiredWidth,DesiredHeight) interpolationQuality:kCGInterpolationHigh];
yourImageView.contentMode = UIViewContentModeCenter;
[yourImageView setImage:tmpImage];
Hope it helps.
How can you mask a square image into an image with round corners?
You can use CoreGraphics to create a path for a round rectangle with this code snippet:
static void addRoundedRectToPath(CGContextRef context, CGRect rect, float ovalWidth, float ovalHeight)
{
float fw, fh;
if (ovalWidth == 0 || ovalHeight == 0) {
CGContextAddRect(context, rect);
return;
}
CGContextSaveGState(context);
CGContextTranslateCTM (context, CGRectGetMinX(rect), CGRectGetMinY(rect));
CGContextScaleCTM (context, ovalWidth, ovalHeight);
fw = CGRectGetWidth (rect) / ovalWidth;
fh = CGRectGetHeight (rect) / ovalHeight;
CGContextMoveToPoint(context, fw, fh/2);
CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1);
CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1);
CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1);
CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1);
CGContextClosePath(context);
CGContextRestoreGState(context);
}
And then call CGContextClip(context); to clip it to the rectangle path. Now any drawing done, including drawing an image, will be clipped to the round rectangle shape.
As an example, assuming "image" is a UIImage, and this is in a drawRect: method:
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSaveGState(context);
addRoundedRectToPath(context, self.frame, 10, 10);
CGContextClip(context);
[image drawInRect:self.frame];
CGContextRestoreGState(context);
Here is an even easier method that is available in iPhone 3.0 and up. Every View-based object has an associated layer. Each layer can have a corner radius set, this will give you just what you want:
UIImageView * roundedView = [[UIImageView alloc] initWithImage: [UIImage imageNamed:#"wood.jpg"]];
// Get the Layer of any view
CALayer * layer = [roundedView layer];
[layer setMasksToBounds:YES];
[layer setCornerRadius:10.0];
// You can even add a border
[layer setBorderWidth:4.0];
[layer setBorderColor:[[UIColor blueColor] CGColor]];
To use these methods you might need to add:
#import <QuartzCore/QuartzCore.h>
I realize this is old news but just to boil it down a bit:
There are two possible questions here: (1) how do I apply rounded corners to a UIView (such as a UIImageView), which will be displayed on screen, and (2) how do I mask a square image (that is, a UIImage) to produce a new image with rounded corners.
For (1), the easiest course is to use CoreAnimation and set the view.layer.cornerRadius property
// Because we're using CoreAnimation, we must include QuartzCore.h
// and link QuartzCore.framework in a build phases
#import <QuartzCore/QuartzCore.h>
// start with an image
UIImage * fooImage = [UIImage imageNamed:#"foo.png"];
// put it in a UIImageView
UIView * view = [UIImageView alloc] initWithImage:fooImage];
// round its corners. This mask now applies to the view's layer's *background*
view.layer.cornerRadius = 10.f
// enable masksToBounds, so the mask applies to its foreground, the image
view.layer.masksToBounds = YES;
For (2), the best way is to use the UIKit graphics operations:
// start with an image
UIImage * fooImage = [UIImage imageNamed:#"foo.png"];
CGRect imageRect = CGRectMake(0, 0, fooImage.size.width, fooImage.size.height);
// set the implicit graphics context ("canvas") to a bitmap context for images
UIGraphicsBeginImageContextWithOptions(imageRect.size,NO,0.0);
// create a bezier path defining rounded corners
UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:imageRect cornerRadius:10.f];
// use this path for clipping in the implicit context
[path addClip];
// draw the image into the implicit context
[fooImage drawInRect:imageRect];
// save the clipped image from the implicit context into an image
UIImage *maskedImage = UIGraphicsGetImageFromCurrentImageContext();
// cleanup
UIGraphicsEndImageContext();
What's tricky about problem (2) is that you might think you could do the whole operation using the view.layer.mask property in CoreAnimation. But you can't because the CALayer renderInContext: method, which you'd use to generate a UIImage from the masked layer, seems to ignore the mask. Worse, the documentation for renderInContext: doesn't mention this, and only alludes to the behavior for OSX 10.5.
Some further context: the above approach to (2) is using UIKit's wrappers around more basic CoreGraphics functionality. You can do the same thing using the CoreGraphics calls directly – that is what the chosen answer is doing -- but then you need build the rounded rect bezier path manually from curves and lines and you also need to compensate for the fact that CoreGraphics uses a drawing coordinate system which is flipped with respect to UIKit's.
See this Post - Very simple answer
How to set round corners in UI images in iphone
UIImageView * roundedView = [[UIImageView alloc] initWithImage: [UIImage imageNamed:#"wood.jpg"]];
// Get the Layer of any view
CALayer * l = [roundedView layer];
[l setMasksToBounds:YES];
[l setCornerRadius:10.0];
Very simple.
self.profileImageView.layer.cornerRadius = self.profileImageView.frame.size.width / 2;
self.profileImageView.clipsToBounds = YES;
For every view, there is a bundled layer property. So the first line of the above is to set the corner radius of the layer object (i.e. an instance of CALayer class). To make a circular image from a squared image, the radius is set to the half of the width of UIImageView. For instance, if the width of squared image is 100 pixels. The radius is set to 50 pixels. Secondly, you have to set the clipsToBounds property to YES in order to make the layer works.
Both the methods work but the differences shows up depending on where you use it.
For Ex: If you have a table view with the cells showing an image along with other labels, etc., and you use layer to set the cornerRadius, the scrolling will take a big hit. It gets jerky.
I faced this issue when I was using Layer for an image in a table view cell and was trying to figure out the cause of that jerkiness only to find that CALayer was the culprit.
Used the first solution of doing the stuff in drawRect explained by NilObject. That works like a charm with scrolling being smooth as silk.
On the other hand, if you want to use this in static views like popover view, etc., layer is the easiest way to do it.
As I said, both the methods work well just that you need to decide based on where you want to use it.
I use this method.
+ (UIImage *)imageWithColor:(UIColor *)color andSize:(CGSize)size;
{
UIImage *img = nil;
CGRect rect = CGRectMake(0, 0, size.width, size.height);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context,
color.CGColor);
CGContextFillRect(context, rect);
img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}
Building off of algal, here are a couple methods that are nice to put in an UIImage category:
- (UIImage *) roundedCornerImageWithRadius:(CGFloat)radius
{
CGRect imageRect = CGRectMake(0, 0, self.size.width, self.size.height);
UIGraphicsBeginImageContextWithOptions(imageRect.size,NO,0.0); //scale 0 yields better results
//create a bezier path defining rounded corners and use it for clippping
UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:imageRect cornerRadius:radius];
[path addClip];
// draw the image into the implicit context
[self drawInRect:imageRect];
// get image and cleanup
UIImage *roundedCornerImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return roundedCornerImage;
}
+ (UIImage *)imageWithColor:(UIColor *)color size:(CGSize)size andCornerRadius:(CGFloat)radius
{
UIImage *image = nil;
if (size.width == 0 || size.height == 0) {
size = CGSizeMake(1.0, 1.0);
}
CGRect rect = CGRectMake(0.0f, 0.0f, size.width, size.height);
UIGraphicsBeginImageContextWithOptions(rect.size,NO,0.0); //yields sharper results than UIGraphicsBeginImageContext(rect.size)
CGContextRef context = UIGraphicsGetCurrentContext();
if (context)
{
CGContextSetFillColorWithColor(context, [color CGColor]);
if (radius > 0.0) {
//create a bezier path defining rounded corners and use it for clippping
UIBezierPath * path = [UIBezierPath bezierPathWithRoundedRect:rect cornerRadius:radius];
[path addClip];
CGContextAddPath(context, path.CGPath);
}
CGContextFillRect(context, rect);
image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
return image;
}